Skip to content

Commit 00b3543

Browse files
committed
Require message body to be indented
Fix projectfluent#12, projectfluent#17, projectfluent#18. With this change, the entire body of a message needs to indented. This makes error recovery very easy: finding the next message definition is as simple as finding the next identifier with no indentation. It also opens up a number of opportunities: we can remove the `|` syntax for multiline blocks of text and allow line breaks inside of placeables safely. The PR also allows the value to be defined on a new line, making the following examples equivalent: lipsum = Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi pellentesque congue metus, non mattis sem faucibus sit amet. lipsum = Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi pellentesque congue metus, non mattis sem faucibus sit amet. I hope this will help when attributes are present: lipsum = Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi pellentesque congue metus, non mattis sem faucibus sit amet. .attr = Attribute Lastly, quoted patterns are only available inside of placeables and cannot be used directly as values. The exact semantics of \ escapes will be defined in projectfluent#22.
1 parent f176deb commit 00b3543

File tree

1 file changed

+28
-25
lines changed

1 file changed

+28
-25
lines changed

syntax/fluent.ebnf

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,42 @@ entry ::= comment
33
| section
44
| message
55

6-
comment ::= ('//' [^#xA#xD]* NL)+
7-
section ::= '[[' __ word (__ word)* __ ']]'
6+
comment ::= ('//' (char - NL)* NL)+
7+
section ::= '[[' _ word (_ word)* _ ']]'
88

99
char ::= [https://www.w3.org/TR/REC-xml/#NT-Char]
10-
__ ::= [#x20#x9]* /* space, tab */
11-
NL ::= [#xA#xD]+ /* line feed, carriage return */
10+
special ::= [#x5b#x5c#x5d#x7b#x7d] /* special chars: { } [ \ ] */
11+
line-break ::= [#xA#xD]+ /* line feed, carriage return */
12+
inline-space ::= [#x20#x9]+ /* space, tab */
13+
break-indent ::= (line-break? inline-space)+
14+
15+
_ ::= inline-space
16+
NL ::= line-break
17+
__ ::= break-indent
1218

1319
identifier ::= [a-zA-Z_?-] [a-zA-Z0-9_?-]*
1420
external ::= '$' identifier
15-
word ::= [^#x20#x9#xA#xD#x5b#x5c#x5d]+ /* exclude: white space, [, \, ] */
21+
word ::= (((char - line-break) - inline-space) - special)+
1622
builtin ::= [A-Z_?-]+
1723
number ::= [0-9]+ ('.' [0-9]+)?
1824

1925
variant-key ::= number | variant-symbol
20-
variant-symbol ::= word (__ word)*
21-
variant ::= '[' variant-key ']' __ pattern NL
22-
default-variant ::= '*' variant
23-
variant-list ::= NL (__ variant)* __ default-variant (__ variant)*
24-
25-
attribute ::= '.' identifier __ '=' __ pattern NL
26-
attribute-list ::= NL (__ attribute)+
27-
28-
message ::= identifier __ '=' __ (pattern attribute-list? | attribute-list)
29-
pattern ::= unquoted-pattern
30-
| quoted-pattern
31-
unquoted-pattern ::= (unquoted-text | placeable | block-text)+
32-
quoted-pattern ::= '"' (quoted-text | placeable)* '"'
33-
unquoted-text ::= ([^{] | '\{')+
34-
quoted-text ::= ([^{"] | '\{' | '\"')+
35-
block-text ::= NL __ '|' unquoted-pattern
26+
variant-symbol ::= word (_ word)*
27+
variant ::= NL __ '[' _ variant-key _ ']' __ pattern
28+
default-variant ::= NL __ '*[' _ variant-key _ ']' __ pattern
29+
variant-list ::= variant* default-variant variant*
30+
31+
attribute ::= NL __ '.' identifier __ value
32+
attribute-list ::= attribute+
33+
34+
message ::= identifier (value attribute-list? | attribute-list)
35+
value ::= __ '=' pattern
36+
pattern ::= (text | placeable)+
37+
text ::= ((char - line-break) - special | break-indent | '\' special)+
38+
quoted-text ::= '"' (text | '\"')+ '"'
3639

3740
placeable ::= '{' __ (expression | select-expression | variant-list) __ '}'
38-
expression ::= quoted-pattern
41+
expression ::= quoted-text
3942
| number
4043
| identifier
4144
| external
@@ -44,10 +47,10 @@ expression ::= quoted-pattern
4447
| call-expression
4548
| placeable
4649

47-
select-expression ::= expression __ ' ->' __ variant-list
50+
select-expression ::= expression __ '->' __ variant-list
4851
attribute-expression ::= identifier '.' identifier
49-
variant-expression ::= identifier '[' __ variant-key __ ']'
52+
variant-expression ::= identifier '[' _ variant-key _ ']'
5053
call-expression ::= builtin '(' __ (argument ( __ ',' __ argument)*)? __ ')'
5154
argument ::= expression
5255
| named-argument
53-
named-argument ::= identifier __ ':' __ ('"' quoted-text? '"' | number)
56+
named-argument ::= identifier __ ':' __ ('"' word? '"' | number)

0 commit comments

Comments
 (0)