diff --git a/fluent-syntax/src/errors.js b/fluent-syntax/src/errors.js index 0d124ae01..63f5186dc 100644 --- a/fluent-syntax/src/errors.js +++ b/fluent-syntax/src/errors.js @@ -23,7 +23,7 @@ function getErrorMessage(code, args) { } case 'E0005': { const [id] = args; - return `Expected entry "${id}" to have a value, attributes or tags`; + return `Expected entry "${id}" to have a value or attributes`; } case 'E0006': { const [field] = args; diff --git a/fluent-syntax/src/ftlstream.js b/fluent-syntax/src/ftlstream.js index 3fef5b179..9fc92701b 100644 --- a/fluent-syntax/src/ftlstream.js +++ b/fluent-syntax/src/ftlstream.js @@ -226,7 +226,7 @@ export class FTLParserStream extends ParserStream { this.next(); return ret; } - throw new ParseError('E0004', 'a-zA-Z'); + throw new ParseError('E0004', 'a-zA-Z_'); } takeIDChar() { @@ -243,15 +243,11 @@ export class FTLParserStream extends ParserStream { takeSymbChar() { const closure = ch => { - if (ch === undefined) { - return false; - } - const cc = ch.charCodeAt(0); return ((cc >= 97 && cc <= 122) || // a-z (cc >= 65 && cc <= 90) || // A-Z (cc >= 48 && cc <= 57) || // 0-9 - cc === 95 || cc === 45 || cc === 32); // _- + cc === 95 || cc === 45 || cc === 32); // _- }; return this.takeChar(closure); diff --git a/fluent-syntax/src/parser.js b/fluent-syntax/src/parser.js index 3d8321beb..df2bddc72 100644 --- a/fluent-syntax/src/parser.js +++ b/fluent-syntax/src/parser.js @@ -153,7 +153,7 @@ export default class FluentParser { ps.next(); - if (ps.current() === '/') { + if (ps.currentIs('/')) { content += '\n'; ps.next(); ps.expectChar('/'); @@ -212,7 +212,7 @@ export default class FluentParser { tags = this.getTags(ps); } - if (pattern === undefined && attrs === undefined && tags === undefined) { + if (pattern === undefined && attrs === undefined) { throw new ParseError('E0005', id.name); } @@ -566,7 +566,14 @@ export default class FluentParser { ps.expectChar(')'); - return new AST.CallExpression(literal.id, args); + if (!/^[A-Z_-]+$/.test(literal.id.name)) { + throw new ParseError('E0008'); + } + + return new AST.CallExpression( + new AST.Function(literal.id.name), + args + ); } return literal; diff --git a/fluent-syntax/test/fixtures_behavior/attribute_expression_with_wrong_attr.ftl b/fluent-syntax/test/fixtures_behavior/attribute_expression_with_wrong_attr.ftl index 5fbf7b777..ad7e751ab 100644 --- a/fluent-syntax/test/fixtures_behavior/attribute_expression_with_wrong_attr.ftl +++ b/fluent-syntax/test/fixtures_behavior/attribute_expression_with_wrong_attr.ftl @@ -1,7 +1,7 @@ key = { foo.23 } -//~ ERROR E0004, pos 12, args "a-zA-Z" +//~ ERROR E0004, pos 12, args "a-zA-Z_" key = { foo. } -//~ ERROR E0004, pos 31, args "a-zA-Z" +//~ ERROR E0004, pos 31, args "a-zA-Z_" diff --git a/fluent-syntax/test/fixtures_behavior/call_expression_with_bad_id.ftl b/fluent-syntax/test/fixtures_behavior/call_expression_with_bad_id.ftl new file mode 100644 index 000000000..aa86f73fa --- /dev/null +++ b/fluent-syntax/test/fixtures_behavior/call_expression_with_bad_id.ftl @@ -0,0 +1,3 @@ +key = { no-caps-name() } + +//~ ERROR E0008, pos 22 diff --git a/fluent-syntax/test/fixtures_behavior/non_id_attribute_name.ftl b/fluent-syntax/test/fixtures_behavior/non_id_attribute_name.ftl index 1cf580b29..c44257e52 100644 --- a/fluent-syntax/test/fixtures_behavior/non_id_attribute_name.ftl +++ b/fluent-syntax/test/fixtures_behavior/non_id_attribute_name.ftl @@ -1,3 +1,3 @@ key = Value .2 = Foo -//~ ERROR E0004, pos 17, args "a-zA-Z" +//~ ERROR E0004, pos 17, args "a-zA-Z_" diff --git a/fluent-syntax/test/fixtures_behavior/unclosed_empty_placeable_error.ftl b/fluent-syntax/test/fixtures_behavior/unclosed_empty_placeable_error.ftl index 0c86cfb18..c714e5caa 100644 --- a/fluent-syntax/test/fixtures_behavior/unclosed_empty_placeable_error.ftl +++ b/fluent-syntax/test/fixtures_behavior/unclosed_empty_placeable_error.ftl @@ -1,2 +1,2 @@ bar = Bar { -//~ ERROR E0004, pos 11, args "a-zA-Z" +//~ ERROR E0004, pos 11, args "a-zA-Z_" diff --git a/fluent-syntax/test/fixtures_behavior/variant_ends_abruptly.ftl b/fluent-syntax/test/fixtures_behavior/variant_ends_abruptly.ftl index 94dfcd4b5..4fc37412e 100644 --- a/fluent-syntax/test/fixtures_behavior/variant_ends_abruptly.ftl +++ b/fluent-syntax/test/fixtures_behavior/variant_ends_abruptly.ftl @@ -1,3 +1,3 @@ key = { $foo -> *[ -//~ ERROR E0004, pos 22, args "a-zA-Z" +//~ ERROR E0004, pos 22, args "a-zA-Z_" diff --git a/fluent-syntax/test/fixtures_behavior/variant_expression_empty_key.ftl b/fluent-syntax/test/fixtures_behavior/variant_expression_empty_key.ftl index c6fd0b8d1..950bf3289 100644 --- a/fluent-syntax/test/fixtures_behavior/variant_expression_empty_key.ftl +++ b/fluent-syntax/test/fixtures_behavior/variant_expression_empty_key.ftl @@ -1,2 +1,2 @@ key = { foo[] } -//~ ERROR E0004, pos 12, args "a-zA-Z" +//~ ERROR E0004, pos 12, args "a-zA-Z_" diff --git a/fluent-syntax/test/fixtures_behavior/variant_starts_from_nl.ftl b/fluent-syntax/test/fixtures_behavior/variant_starts_from_nl.ftl index 139f4f108..5fb3db3e6 100644 --- a/fluent-syntax/test/fixtures_behavior/variant_starts_from_nl.ftl +++ b/fluent-syntax/test/fixtures_behavior/variant_starts_from_nl.ftl @@ -1,4 +1,4 @@ key = { *[one] Value } -//~ ERROR E0004, pos 7, args "a-zA-Z" +//~ ERROR E0004, pos 7, args "a-zA-Z_" diff --git a/fluent-syntax/test/fixtures_behavior/variant_with_leading_space_in_name.ftl b/fluent-syntax/test/fixtures_behavior/variant_with_leading_space_in_name.ftl index 0b8f9c956..51a8f1af4 100644 --- a/fluent-syntax/test/fixtures_behavior/variant_with_leading_space_in_name.ftl +++ b/fluent-syntax/test/fixtures_behavior/variant_with_leading_space_in_name.ftl @@ -1,4 +1,4 @@ key = { *[ one] Foo } -//~ ERROR E0004, pos 18, args "a-zA-Z" +//~ ERROR E0004, pos 18, args "a-zA-Z_"