From 91e7cff6a0ce2c0be21548545ddfe851c0cc412d Mon Sep 17 00:00:00 2001 From: Zibi Braniecki Date: Mon, 22 Oct 2018 08:10:17 -0700 Subject: [PATCH] Make trailing `=` optional if Message has no value --- spec/fluent.ebnf | 2 +- syntax/grammar.mjs | 24 ++- test/fixtures/messages-no-equal.ftl | 27 +++ test/fixtures/messages-no-equal.json | 248 +++++++++++++++++++++++++++ 4 files changed, 293 insertions(+), 8 deletions(-) create mode 100644 test/fixtures/messages-no-equal.ftl create mode 100644 test/fixtures/messages-no-equal.json diff --git a/spec/fluent.ebnf b/spec/fluent.ebnf index ad07904..032d035 100644 --- a/spec/fluent.ebnf +++ b/spec/fluent.ebnf @@ -11,7 +11,7 @@ Resource ::= (Entry | blank_block | junk_line)* Entry ::= (Message line_end) | (Term line_end) | CommentLine -Message ::= Identifier blank_inline? "=" blank_inline? ((Pattern Attribute*) | (Attribute+)) +Message ::= Identifier ((blank_inline? "=" blank_inline? ((Pattern? Attribute+) | Pattern)) | (blank_inline? Attribute+)) Term ::= "-" Identifier blank_inline? "=" blank_inline? Value Attribute* /* Adjacent comment lines of the same comment type are joined together during diff --git a/syntax/grammar.mjs b/syntax/grammar.mjs index bfa4e50..da829bc 100644 --- a/syntax/grammar.mjs +++ b/syntax/grammar.mjs @@ -40,17 +40,27 @@ let Entry = defer(() => let Message = defer(() => sequence( Identifier.abstract, - maybe(blank_inline), - string("="), - maybe(blank_inline), either( sequence( - Pattern.abstract, - repeat(Attribute).abstract), + maybe(blank_inline), + string("="), + maybe(blank_inline), + either( + sequence( + maybe(Pattern).abstract, + repeat1(Attribute).abstract, + ), + Pattern.abstract, + ), + ), sequence( + maybe(blank_inline), always(null).abstract, - repeat1(Attribute).abstract))) - .map(flatten(1)) + repeat1(Attribute).abstract, + ), + ) + ) + .map(flatten(2)) .map(keep_abstract) .chain(list_into(FTL.Message))); diff --git a/test/fixtures/messages-no-equal.ftl b/test/fixtures/messages-no-equal.ftl new file mode 100644 index 0000000..b2ee975 --- /dev/null +++ b/test/fixtures/messages-no-equal.ftl @@ -0,0 +1,27 @@ +key01 = Value + +key02 = Value + .attr = Attribute + +key02 = Value + .attr1 = Attribute 1 + .attr2 = Attribute 2 + +key03 + .attr = Attribute + +key04 + .attr1 = Attribute 1 + .attr2 = Attribute 2 + +# < whitespace > +key05 + .attr1 = Attribute 1 + +key06 = {""} + +# JUNK Missing value +key07 = + +# JUNK Missing = +key08 diff --git a/test/fixtures/messages-no-equal.json b/test/fixtures/messages-no-equal.json new file mode 100644 index 0000000..1a5b5c4 --- /dev/null +++ b/test/fixtures/messages-no-equal.json @@ -0,0 +1,248 @@ +{ + "type": "Resource", + "body": [ + { + "type": "Message", + "id": { + "type": "Identifier", + "name": "key01" + }, + "value": { + "type": "Pattern", + "elements": [ + { + "type": "TextElement", + "value": "Value" + } + ] + }, + "attributes": [], + "comment": null + }, + { + "type": "Message", + "id": { + "type": "Identifier", + "name": "key02" + }, + "value": { + "type": "Pattern", + "elements": [ + { + "type": "TextElement", + "value": "Value" + } + ] + }, + "attributes": [ + { + "type": "Attribute", + "id": { + "type": "Identifier", + "name": "attr" + }, + "value": { + "type": "Pattern", + "elements": [ + { + "type": "TextElement", + "value": "Attribute" + } + ] + } + } + ], + "comment": null + }, + { + "type": "Message", + "id": { + "type": "Identifier", + "name": "key02" + }, + "value": { + "type": "Pattern", + "elements": [ + { + "type": "TextElement", + "value": "Value" + } + ] + }, + "attributes": [ + { + "type": "Attribute", + "id": { + "type": "Identifier", + "name": "attr1" + }, + "value": { + "type": "Pattern", + "elements": [ + { + "type": "TextElement", + "value": "Attribute 1" + } + ] + } + }, + { + "type": "Attribute", + "id": { + "type": "Identifier", + "name": "attr2" + }, + "value": { + "type": "Pattern", + "elements": [ + { + "type": "TextElement", + "value": "Attribute 2" + } + ] + } + } + ], + "comment": null + }, + { + "type": "Message", + "id": { + "type": "Identifier", + "name": "key03" + }, + "value": null, + "attributes": [ + { + "type": "Attribute", + "id": { + "type": "Identifier", + "name": "attr" + }, + "value": { + "type": "Pattern", + "elements": [ + { + "type": "TextElement", + "value": "Attribute" + } + ] + } + } + ], + "comment": null + }, + { + "type": "Message", + "id": { + "type": "Identifier", + "name": "key04" + }, + "value": null, + "attributes": [ + { + "type": "Attribute", + "id": { + "type": "Identifier", + "name": "attr1" + }, + "value": { + "type": "Pattern", + "elements": [ + { + "type": "TextElement", + "value": "Attribute 1" + } + ] + } + }, + { + "type": "Attribute", + "id": { + "type": "Identifier", + "name": "attr2" + }, + "value": { + "type": "Pattern", + "elements": [ + { + "type": "TextElement", + "value": "Attribute 2" + } + ] + } + } + ], + "comment": null + }, + { + "type": "Message", + "id": { + "type": "Identifier", + "name": "key05" + }, + "value": null, + "attributes": [ + { + "type": "Attribute", + "id": { + "type": "Identifier", + "name": "attr1" + }, + "value": { + "type": "Pattern", + "elements": [ + { + "type": "TextElement", + "value": "Attribute 1" + } + ] + } + } + ], + "comment": { + "type": "Comment", + "content": " < whitespace >" + } + }, + { + "type": "Message", + "id": { + "type": "Identifier", + "name": "key06" + }, + "value": { + "type": "Pattern", + "elements": [ + { + "type": "Placeable", + "expression": { + "type": "StringLiteral", + "value": "" + } + } + ] + }, + "attributes": [], + "comment": null + }, + { + "type": "Comment", + "content": "JUNK Missing value" + }, + { + "type": "Junk", + "annotations": [], + "content": "key07 =\n" + }, + { + "type": "Comment", + "content": "JUNK Missing =" + }, + { + "type": "Junk", + "annotations": [], + "content": "key08\n" + } + ] +}