-
Notifications
You must be signed in to change notification settings - Fork 0
/
fluent.ebnf
140 lines (123 loc) · 5.99 KB
/
fluent.ebnf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/* An FTL file defines a Resource consisting of Entries. */
Resource ::= (Entry | blank_block | Junk)*
/* Entries are the main building blocks of Fluent. They define translations and
* contextual and semantic information about the translations. During the AST
* construction, adjacent comment lines of the same comment type (defined by
* the number of #) are joined together. Single-# comments directly preceding
* Messages and Terms are attached to the Message or Term and are not
* standalone Entries. */
Entry ::= (Message line_end)
| (Term line_end)
| CommentLine
Message ::= Identifier blank_inline? "=" blank_inline? ((Pattern Attribute*) | (Attribute+))
Term ::= "-" Identifier blank_inline? "=" blank_inline? Pattern Attribute*
/* Adjacent comment lines of the same comment type are joined together during
* the AST construction. */
CommentLine ::= ("###" | "##" | "#") ("\u0020" comment_char*)? line_end
comment_char ::= any_char - line_end
/* Junk represents unparsed content.
*
* Junk is parsed line-by-line until a line is found which looks like it might
* be a beginning of a new message, term, or a comment. Any whitespace
* following a broken Entry is also considered part of Junk.
*/
Junk ::= junk_line (junk_line - "#" - "-" - [a-zA-Z])*
junk_line ::= /[^\n]*/ ("\u000A" | EOF)
/* Attributes of Messages and Terms. */
Attribute ::= line_end blank? "." Identifier blank_inline? "=" blank_inline? Pattern
/* Patterns are values of Messages, Terms, Attributes and Variants. */
Pattern ::= PatternElement+
/* TextElement and Placeable can occur inline or as block.
* Text needs to be indented and start with a non-special character.
* Placeables can start at the beginning of the line or be indented.
* Adjacent TextElements are joined in AST creation. */
PatternElement ::= inline_text
| block_text
| inline_placeable
| block_placeable
inline_text ::= text_char+
block_text ::= blank_block blank_inline indented_char inline_text?
inline_placeable ::= "{" blank? (SelectExpression | InlineExpression) blank? "}"
block_placeable ::= blank_block blank_inline? inline_placeable
/* Rules for validating expressions in Placeables and as selectors of
* SelectExpressions are documented in spec/valid.md and enforced in
* syntax/abstract.js. */
InlineExpression ::= StringLiteral
| NumberLiteral
| FunctionReference
| MessageReference
| TermReference
| VariableReference
| inline_placeable
/* Literals */
StringLiteral ::= "\"" quoted_char* "\""
NumberLiteral ::= "-"? digits ("." digits)?
/* Inline Expressions */
FunctionReference ::= Identifier CallArguments
MessageReference ::= Identifier AttributeAccessor?
TermReference ::= "-" Identifier AttributeAccessor? CallArguments?
VariableReference ::= "$" Identifier
AttributeAccessor ::= "." Identifier
CallArguments ::= blank? "(" blank? argument_list blank? ")"
argument_list ::= (Argument blank? "," blank?)* Argument?
Argument ::= NamedArgument
| InlineExpression
NamedArgument ::= Identifier blank? ":" blank? (StringLiteral | NumberLiteral)
/* Block Expressions */
SelectExpression ::= InlineExpression blank? "->" blank_inline? variant_list
variant_list ::= Variant* DefaultVariant Variant* line_end
Variant ::= line_end blank? VariantKey blank_inline? Pattern
DefaultVariant ::= line_end blank? "*" VariantKey blank_inline? Pattern
VariantKey ::= "[" blank? (NumberLiteral | Identifier) blank? "]"
/* Identifier */
Identifier ::= [a-zA-Z] [a-zA-Z0-9_-]*
/* Content Characters
*
* Translation content can be written using any Unicode characters. However,
* some characters are considered special depending on the type of content
* they're in. See text_char and quoted_char for more information.
*
* Some Unicode characters, even if allowed, should be avoided in Fluent
* resources. See spec/recommendations.md.
*/
any_char ::= [\\u{0}-\\u{10FFFF}]
/* Text elements
*
* The primary storage for content are text elements. Text elements are not
* delimited with quotes and may span multiple lines as long as all lines are
* indented. The opening brace ({) marks a start of a placeable in the pattern
* and may not be used in text elements verbatim. Due to the indentation
* requirement some text characters may not appear as the first character on a
* new line.
*/
special_text_char ::= "{"
| "}"
text_char ::= any_char - special_text_char - line_end
indented_char ::= text_char - "[" - "*" - "."
/* String literals
*
* For special-purpose content, quoted string literals can be used where text
* elements are not a good fit. String literals are delimited with double
* quotes and may not contain line breaks. String literals use the backslash
* (\) as the escape character. The literal double quote can be inserted via
* the \" escape sequence. The literal backslash can be inserted with \\. The
* literal opening brace ({) is allowed in string literals because they may not
* comprise placeables.
*/
special_quoted_char ::= "\""
| "\\"
special_escape ::= "\\" special_quoted_char
unicode_escape ::= ("\\u" /[0-9a-fA-F]{4}/)
| ("\\U" /[0-9a-fA-F]{6}/)
quoted_char ::= (any_char - special_quoted_char - line_end)
| special_escape
| unicode_escape
/* Numbers */
digits ::= [0-9]+
/* Whitespace */
blank_inline ::= "\u0020"+
line_end ::= "\u000D\u000A"
| "\u000A"
| EOF
blank_block ::= (blank_inline? line_end)+
blank ::= (blank_inline | line_end)+