diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /third_party/rust/jsparagus/js_parser | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/jsparagus/js_parser')
-rw-r--r-- | third_party/rust/jsparagus/js_parser/README.md | 67 | ||||
-rw-r--r-- | third_party/rust/jsparagus/js_parser/__init__.py | 0 | ||||
-rw-r--r-- | third_party/rust/jsparagus/js_parser/es-lexical-simplified.esgrammar | 485 | ||||
-rw-r--r-- | third_party/rust/jsparagus/js_parser/es-simplified.esgrammar | 1453 | ||||
-rw-r--r-- | third_party/rust/jsparagus/js_parser/es.esgrammar | 1668 | ||||
-rw-r--r-- | third_party/rust/jsparagus/js_parser/esgrammar.pgen | 290 | ||||
-rwxr-xr-x | third_party/rust/jsparagus/js_parser/extract_es_grammar.py | 567 | ||||
-rwxr-xr-x | third_party/rust/jsparagus/js_parser/generate_js_parser_tables.py | 140 | ||||
-rw-r--r-- | third_party/rust/jsparagus/js_parser/lexer.py | 315 | ||||
-rw-r--r-- | third_party/rust/jsparagus/js_parser/load_es_grammar.py | 129 | ||||
-rw-r--r-- | third_party/rust/jsparagus/js_parser/parse_esgrammar.py | 545 | ||||
-rw-r--r-- | third_party/rust/jsparagus/js_parser/parser.py | 42 | ||||
-rw-r--r-- | third_party/rust/jsparagus/js_parser/slash.esgrammar | 1683 | ||||
-rwxr-xr-x | third_party/rust/jsparagus/js_parser/try_it.py | 59 |
14 files changed, 7443 insertions, 0 deletions
diff --git a/third_party/rust/jsparagus/js_parser/README.md b/third_party/rust/jsparagus/js_parser/README.md new file mode 100644 index 0000000000..a8a814619d --- /dev/null +++ b/third_party/rust/jsparagus/js_parser/README.md @@ -0,0 +1,67 @@ +## jsparagus/js_parser: Generating a parser for JavaScript + +In this directory: + +* **esgrammar.pgen** A grammar for the mini-language the ECMAScript + standard uses to describe ES grammar. + +* **es.esgrammar** - The actual grammar for ECMAScript, in emu-grammar + format, extracted automatically from the spec. + +* **extract_es_grammar.py** - The script that creates *es.esgrammar*. + +* **es-simplified.esgrammar** - A hacked version of *es.esgrammar* that + jsparagus can actually handle. + +* **generate_js_parser_tables.py** - A script to generate a JS parser + based on *es-simplified.esgrammar*. Read on for instructions. + + +## How to run it + +To generate a parser, follow these steps: + +```console +$ cd .. +$ make init +$ make all +``` + +**Note:** The last step currently takes about 35 seconds to run on my +laptop. jsparagus is slow. + +Once you're done, to see your parser run, try this: + +```console +$ cd crates/driver +$ cargo run --release +``` + +The build also produces a copy of the JS parser in Python. +After `make all`, you can use `make jsdemo` to run that. + + +### How simplified is "es-simplified"? + +Here are the differences between *es.esgrammar*, the actual ES grammar, +and *es-simplified.esgrammar*, the simplified version that jsparagus can +actually handle: + +* The four productions with [~Yield] and [~Await] conditions are dropped. + This means that `yield` and `await` do not match *IdentifierReference* + or *LabelIdentifier*. I think it's better to do that in the lexer. + +* Truncated lookahead. + + `ValueError: unsupported: lookahead > 1 token, [['{'], ['function'], ['async', ('no-LineTerminator-here',), 'function'], ['class'], ['let', '[']]` + +* Delete a rule that uses `but not` since it's not implemented. + + Identifier : + IdentifierName but not ReservedWord + + Making sense of this rule in the context of an LR parser is an + interesting task; see issue #28. + +* Ban loops of the form `for (async of EXPR) STMT` by adjusting a + lookahead assertion. The grammar is not LR(1). diff --git a/third_party/rust/jsparagus/js_parser/__init__.py b/third_party/rust/jsparagus/js_parser/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/third_party/rust/jsparagus/js_parser/__init__.py diff --git a/third_party/rust/jsparagus/js_parser/es-lexical-simplified.esgrammar b/third_party/rust/jsparagus/js_parser/es-lexical-simplified.esgrammar new file mode 100644 index 0000000000..6b0fd1baf6 --- /dev/null +++ b/third_party/rust/jsparagus/js_parser/es-lexical-simplified.esgrammar @@ -0,0 +1,485 @@ +InputElementDiv :: + WhiteSpace + LineTerminator + Comment + CommonToken + DivPunctuator + RightBracePunctuator + +InputElementRegExp :: + WhiteSpace + LineTerminator + Comment + CommonToken + RightBracePunctuator + RegularExpressionLiteral + +InputElementRegExpOrTemplateTail :: + WhiteSpace + LineTerminator + Comment + CommonToken + RegularExpressionLiteral + TemplateSubstitutionTail + +InputElementTemplateTail :: + WhiteSpace + LineTerminator + Comment + CommonToken + DivPunctuator + TemplateSubstitutionTail + + +WhiteSpace :: + <TAB> + <VT> + <FF> + <SP> + <NBSP> + <ZWNBSP> + <USP> + + +LineTerminator :: + <LF> + <CR> + <LS> + <PS> + +LineTerminatorSequence :: + <LF> + <LS> + <PS> + <CR> <LF> + + +MultiLineCommentChars :: + MultiLineCommentPiece + MultiLineCommentChars MultiLineCommentPiece + +MultiLineCommentPiece :: + MultiLineNotAsteriskChar + Stars MultiLineNotForwardSlashOrAsteriskChar + +MultiLineNotAsteriskChar :: + SourceCharacter but not `*` + +MultiLineNotForwardSlashOrAsteriskChar :: + SourceCharacter but not one of `/` or `*` + +SingleLineComment :: + `//` SingleLineCommentChars? + +SingleLineCommentChars :: + SingleLineCommentChar SingleLineCommentChars? + +SingleLineCommentChar :: + SourceCharacter but not LineTerminator + + +CommonToken :: + IdentifierName + Punctuator + NumericLiteral + StringLiteral + Template + + +Identifier :: + `TODO` + +IdentifierName :: + IdentifierStart + IdentifierName IdentifierPart + +IdentifierStart :: + UnicodeIDStart + `$` + `_` + `\` UnicodeEscapeSequence + +IdentifierPart :: + UnicodeIDContinue + `$` + `\` UnicodeEscapeSequence + <ZWNJ> + <ZWJ> + +UnicodeIDStart :: + `TODO` + +UnicodeIDContinue :: + `TODO` + + +ReservedWord :: + Keyword + FutureReservedWord + NullLiteral + BooleanLiteral + + +Keyword :: one of + `await` + `break` + `case` `catch` `class` `const` `continue` + `debugger` `default` `delete` `do` + `else` `export` `extends` + `finally` `for` `function` + `if` `import` `in` `instanceof` + `new` + `return` + `super` `switch` + `this` `throw` `try` `typeof` + `var` `void` + `while` `with` + `yield` + + +FutureReservedWord :: + `enum` + + +Punctuator :: one of + `{` `(` `)` `[` `]` + `.` `...` `;` `,` + `<` `>` `<=` `>=` + `==` `!=` `===` `!==` + `+` `-` `*` `%` `**` + `++` `--` + `<<` `>>` `>>>` + `&` `|` `^` + `!` `~` + `&&` `||` + `?` `:` + `=` `+=` `-=` `*=` `%=` `**=` `<<=` `>>=` `>>>=` `&=` `|=` `^=` + `=>` + +DivPunctuator :: + `/` + `/=` + +RightBracePunctuator :: + `}` + + +NullLiteral :: + `null` + + +BooleanLiteral :: + `true` + `false` + + +DecimalLiteral :: + DecimalIntegerLiteral `.` DecimalDigits? ExponentPart? + `.` DecimalDigits ExponentPart? + DecimalIntegerLiteral ExponentPart? + +DecimalDigits :: + DecimalDigit + DecimalDigits DecimalDigit + +DecimalDigit :: one of + `0` `1` `2` `3` `4` `5` `6` `7` `8` `9` + +NonZeroDigit :: one of + `1` `2` `3` `4` `5` `6` `7` `8` `9` + +ExponentPart :: + ExponentIndicator SignedInteger + +ExponentIndicator :: one of + `e` `E` + +SignedInteger :: + DecimalDigits + `+` DecimalDigits + `-` DecimalDigits + +BinaryIntegerLiteral :: + `0b` BinaryDigits + `0B` BinaryDigits + +BinaryDigits :: + BinaryDigit + BinaryDigits BinaryDigit + +BinaryDigit :: one of + `0` `1` + +OctalIntegerLiteral :: + `0o` OctalDigits + `0O` OctalDigits + +OctalDigits :: + OctalDigit + OctalDigits OctalDigit + +OctalDigit :: one of + `0` `1` `2` `3` `4` `5` `6` `7` + +HexIntegerLiteral :: + `0x` HexDigits + `0X` HexDigits + +HexDigits :: + HexDigit + HexDigits HexDigit + +HexDigit :: one of + `0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `a` `b` `c` `d` `e` `f` `A` `B` `C` `D` `E` `F` + + +StringLiteral :: + `"` DoubleStringCharacters? `"` + `'` SingleStringCharacters? `'` + +DoubleStringCharacters :: + DoubleStringCharacter DoubleStringCharacters? + +SingleStringCharacters :: + SingleStringCharacter SingleStringCharacters? + +DoubleStringCharacter :: + SourceCharacter but not one of `"` or `\` or LineTerminator + <LS> + <PS> + `\` EscapeSequence + LineContinuation + +SingleStringCharacter :: + SourceCharacter but not one of `'` or `\` or LineTerminator + <LS> + <PS> + `\` EscapeSequence + LineContinuation + +LineContinuation :: + `\` LineTerminatorSequence + + +CharacterEscapeSequence :: + SingleEscapeCharacter + NonEscapeCharacter + +SingleEscapeCharacter :: one of + `'` `"` `\` `b` `f` `n` `r` `t` `v` + +NonEscapeCharacter :: + SourceCharacter but not one of EscapeCharacter or LineTerminator + +EscapeCharacter :: + SingleEscapeCharacter + DecimalDigit + `x` + `u` + +HexEscapeSequence :: + `x` HexDigit HexDigit + +UnicodeEscapeSequence :: + `u` Hex4Digits + `u{` CodePoint `}` + +Hex4Digits :: + HexDigit HexDigit HexDigit HexDigit + + +RegularExpressionLiteral :: + `/` RegularExpressionBody `/` RegularExpressionFlags + +RegularExpressionBody :: + RegularExpressionFirstChar RegularExpressionChars + +RegularExpressionChars :: + [empty] + RegularExpressionChars RegularExpressionChar + +RegularExpressionFirstChar :: + RegularExpressionNonTerminator but not one of `*` or `\` or `/` or `[` + RegularExpressionBackslashSequence + RegularExpressionClass + +RegularExpressionChar :: + RegularExpressionNonTerminator but not one of `\` or `/` or `[` + RegularExpressionBackslashSequence + RegularExpressionClass + +RegularExpressionBackslashSequence :: + `\` RegularExpressionNonTerminator + +RegularExpressionNonTerminator :: + SourceCharacter but not LineTerminator + +RegularExpressionClass :: + `[` RegularExpressionClassChars `]` + +RegularExpressionClassChars :: + [empty] + RegularExpressionClassChars RegularExpressionClassChar + +RegularExpressionClassChar :: + RegularExpressionNonTerminator but not one of `]` or `\` + RegularExpressionBackslashSequence + +RegularExpressionFlags :: + [empty] + RegularExpressionFlags IdentifierPart + + +Template :: + NoSubstitutionTemplate + TemplateHead + +NoSubstitutionTemplate :: + ``` TemplateCharacters? ``` + +TemplateHead :: + ``` TemplateCharacters? `${` + +TemplateSubstitutionTail :: + TemplateMiddle + TemplateTail + +TemplateMiddle :: + `}` TemplateCharacters? `${` + +TemplateTail :: + `}` TemplateCharacters? ``` + +TemplateCharacters :: + TemplateCharacter TemplateCharacters? + +TemplateCharacter :: + `$` [lookahead != `{` ] + `\` EscapeSequence + `\` NotEscapeSequence + LineContinuation + LineTerminatorSequence + SourceCharacter but not one of ``` or `\` or `$` or LineTerminator + +NotEscapeSequence :: + `0` DecimalDigit + DecimalDigit but not `0` + `x` [lookahead <! HexDigit] + `x` HexDigit [lookahead <! HexDigit] + `u` [lookahead <! HexDigit] [lookahead != `{`] + `u` HexDigit [lookahead <! HexDigit] + `u` HexDigit HexDigit [lookahead <! HexDigit] + `u` HexDigit HexDigit HexDigit [lookahead <! HexDigit] + `u` `{` [lookahead <! HexDigit] + `u` `{` NotCodePoint [lookahead <! HexDigit] + `u` `{` CodePoint [lookahead <! HexDigit] [lookahead != `}`] + +NotCodePoint :: + HexDigits [> but only if MV of |HexDigits| > 0x10FFFF ] + +CodePoint :: + HexDigits [> but only if MV of |HexDigits| ≤ 0x10FFFF ] + + +ControlLetter :: one of + `a` `b` `c` `d` `e` `f` `g` `h` `i` `j` `k` `l` `m` `n` `o` `p` `q` `r` `s` `t` `u` `v` `w` `x` `y` `z` + `A` `B` `C` `D` `E` `F` `G` `H` `I` `J` `K` `L` `M` `N` `O` `P` `Q` `R` `S` `T` `U` `V` `W` `X` `Y` `Z` + + +NumericLiteral :: + DecimalLiteral + BinaryIntegerLiteral + OctalIntegerLiteral + HexIntegerLiteral + LegacyOctalIntegerLiteral + +LegacyOctalIntegerLiteral :: + `0` OctalDigit + LegacyOctalIntegerLiteral OctalDigit + +DecimalIntegerLiteral :: + `0` + NonZeroDigit DecimalDigits? + NonOctalDecimalIntegerLiteral + +NonOctalDecimalIntegerLiteral :: + `0` NonOctalDigit + LegacyOctalLikeDecimalIntegerLiteral NonOctalDigit + NonOctalDecimalIntegerLiteral DecimalDigit + +LegacyOctalLikeDecimalIntegerLiteral :: + `0` OctalDigit + LegacyOctalLikeDecimalIntegerLiteral OctalDigit + +NonOctalDigit :: one of + `8` `9` + + +EscapeSequence :: + CharacterEscapeSequence + LegacyOctalEscapeSequence + HexEscapeSequence + UnicodeEscapeSequence + +LegacyOctalEscapeSequence :: + OctalDigit [lookahead <! OctalDigit] + ZeroToThree OctalDigit [lookahead <! OctalDigit] + FourToSeven OctalDigit + ZeroToThree OctalDigit OctalDigit + +ZeroToThree :: one of + `0` `1` `2` `3` + +FourToSeven :: one of + `4` `5` `6` `7` + + +Comment :: + MultiLineComment + SingleLineComment + SingleLineHTMLOpenComment + SingleLineHTMLCloseComment + SingleLineDelimitedComment + +MultiLineComment :: + `/*` FirstCommentLine? LineTerminator MultiLineCommentChars? `*/` HTMLCloseComment? + +FirstCommentLine :: + SingleLineDelimitedCommentChars + +SingleLineHTMLOpenComment :: + `<!--` SingleLineCommentChars? + +SingleLineHTMLCloseComment :: + LineTerminatorSequence HTMLCloseComment + +SingleLineDelimitedComment :: + `/*` SingleLineDelimitedCommentChars? `*/` + +HTMLCloseComment :: + WhiteSpaceSequence? SingleLineDelimitedCommentSequence? `-->` SingleLineCommentChars? + +SingleLineDelimitedCommentChars :: + SingleLineDelimitedCommentPiece + SingleLineDelimitedCommentChars SingleLineDelimitedCommentPiece + +SingleLineDelimitedCommentPiece :: + SingleLineNotAsteriskChar + Stars SingleLineNotForwardSlashOrAsteriskChar + +Stars :: + `*` + Stars `*` + +SingleLineNotAsteriskChar :: + SourceCharacter but not one of `*` or LineTerminator + +SingleLineNotForwardSlashOrAsteriskChar :: + SourceCharacter but not one of `/` or `*` or LineTerminator + +WhiteSpaceSequence :: + WhiteSpace WhiteSpaceSequence? + +SingleLineDelimitedCommentSequence :: + SingleLineDelimitedComment WhiteSpaceSequence? SingleLineDelimitedCommentSequence? + diff --git a/third_party/rust/jsparagus/js_parser/es-simplified.esgrammar b/third_party/rust/jsparagus/js_parser/es-simplified.esgrammar new file mode 100644 index 0000000000..f7ebbb2017 --- /dev/null +++ b/third_party/rust/jsparagus/js_parser/es-simplified.esgrammar @@ -0,0 +1,1453 @@ +@returns Identifier +IdentifierReference[Yield, Await] : + Identifier + => identifier_reference($0) + +@returns BindingIdentifier +BindingIdentifier[Yield, Await] : + Identifier + => binding_identifier($0) + `yield` + => binding_identifier_yield($0) + `await` + => binding_identifier_await($0) + +@returns Label +LabelIdentifier[Yield, Await] : + Identifier + => label_identifier($0) + +@returns Expression +PrimaryExpression[Yield, Await] : + `this` + => this_expr($0) + IdentifierReference[?Yield, ?Await] + => identifier_expr($0) + Literal + => $0 + ArrayLiteral[?Yield, ?Await] + => $0 + ObjectLiteral[?Yield, ?Await] + => $0 + FunctionExpression + => $0 + ClassExpression[?Yield, ?Await] + => $0 + GeneratorExpression + => $0 + AsyncFunctionExpression + => $0 + AsyncGeneratorExpression + => $0 + RegularExpressionLiteral + => regexp_literal($0) + TemplateLiteral[?Yield, ?Await, ~Tagged] + => untagged_template_expr($0) + CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await] + => uncover_parenthesized_expression($0) + +@returns CoverParenthesized +CoverParenthesizedExpressionAndArrowParameterList[Yield, Await] : + `(` Expression[+In, ?Yield, ?Await] `)` + => cover_parenthesized_expression($0, $1, $2) + `(` Expression[+In, ?Yield, ?Await] `,` `)` + => cover_arrow_parameter_list($0, expression_to_parameter_list($1), None, $3) + `(` `)` + => cover_arrow_parameter_list($0, empty_parameter_list(), None, $1) + `(` `...` BindingIdentifier[?Yield, ?Await] `)` + => cover_arrow_parameter_list($0, empty_parameter_list(), Some(binding_identifier_to_binding($2)), $3) + `(` `...` BindingPattern[?Yield, ?Await] `)` + => cover_arrow_parameter_list($0, empty_parameter_list(), Some($2), $3) + `(` Expression[+In, ?Yield, ?Await] `,` `...` BindingIdentifier[?Yield, ?Await] `)` + => cover_arrow_parameter_list($0, expression_to_parameter_list($1), Some(binding_identifier_to_binding($4)), $5) + `(` Expression[+In, ?Yield, ?Await] `,` `...` BindingPattern[?Yield, ?Await] `)` + => cover_arrow_parameter_list($0, expression_to_parameter_list($1), Some($4), $5) + + +@returns Expression +Literal : + NullLiteral + => null_literal($0) + BooleanLiteral + => boolean_literal($0) + NumericLiteral + => numeric_literal($0) + BigIntLiteral + => bigint_literal($0) + StringLiteral + => string_literal($0) + + +@returns Expression +ArrayLiteral[Yield, Await] : + `[` Elision? `]` + => array_literal_empty($0, $1, $2) + `[` ElementList[?Yield, ?Await] `]` + => array_literal($0, $1, $2) + `[` ElementList[?Yield, ?Await] `,` Elision? `]` + => array_literal_with_trailing_elision($0,$1, $3, $4) + +@returns ArrayExpression +ElementList[Yield, Await] : + Elision? AssignmentExpression[+In, ?Yield, ?Await] + => element_list_first($0, $1) + Elision? SpreadElement[?Yield, ?Await] + => element_list_first_spread($0, $1) + ElementList[?Yield, ?Await] `,` Elision? AssignmentExpression[+In, ?Yield, ?Await] + => element_list_append($0, $2, $3) + ElementList[?Yield, ?Await] `,` Elision? SpreadElement[?Yield, ?Await] + => element_list_append_spread($0, $2, $3) + +@returns ArrayExpression +Elision : + `,` + => elision_single($0) + Elision `,` + => elision_append($0, $1) + +@returns Expression +SpreadElement[Yield, Await] : + `...` AssignmentExpression[+In, ?Yield, ?Await] + => spread_element($1) + + +@returns Expression +ObjectLiteral[Yield, Await] : + `{` `}` + => object_literal_empty($0, $1) + `{` PropertyDefinitionList[?Yield, ?Await] `}` + => object_literal($0, $1, $2) + `{` PropertyDefinitionList[?Yield, ?Await] `,` `}` + => object_literal($0, $1, $2) + +@returns ObjectExpression +PropertyDefinitionList[Yield, Await] : + PropertyDefinition[?Yield, ?Await] + => property_definition_list_single($0) + PropertyDefinitionList[?Yield, ?Await] `,` PropertyDefinition[?Yield, ?Await] + => property_definition_list_append($0, $2) + +@returns ObjectProperty +PropertyDefinition[Yield, Await] : + IdentifierReference[?Yield, ?Await] + => shorthand_property($0) + CoverInitializedName[?Yield, ?Await] + => $0 + PropertyName[?Yield, ?Await] `:` AssignmentExpression[+In, ?Yield, ?Await] + => property_definition($0, $2) + MethodDefinition[?Yield, ?Await] + => property_definition_method($0) + `...` AssignmentExpression[+In, ?Yield, ?Await] + => property_definition_spread($1) + +@returns PropertyName +PropertyName[Yield, Await] : + LiteralPropertyName + => $0 + ComputedPropertyName[?Yield, ?Await] + => $0 + +@returns PropertyName +LiteralPropertyName : + IdentifierName + => property_name_identifier($0) + StringLiteral + => property_name_string($0) + NumericLiteral + => property_name_numeric($0) + BigIntLiteral + => property_name_bigint($0) + +@returns PropertyName +ComputedPropertyName[Yield, Await] : + `[` AssignmentExpression[+In, ?Yield, ?Await] `]` + => computed_property_name($0, $1, $2) + +@returns ObjectProperty +CoverInitializedName[Yield, Await] : + IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await] + => cover_initialized_name($0, $1) + +@returns Expression +Initializer[In, Yield, Await] : + `=` AssignmentExpression[?In, ?Yield, ?Await] + => $1 + + +@returns TemplateExpression +TemplateLiteral[Yield, Await, Tagged] : + NoSubstitutionTemplate + => template_literal($0) + SubstitutionTemplate[?Yield, ?Await, ?Tagged] + => $0 + +@returns TemplateExpression +SubstitutionTemplate[Yield, Await, Tagged] : + TemplateHead Expression[+In, ?Yield, ?Await] TemplateSpans[?Yield, ?Await, ?Tagged] + => substitution_template($0, $1, $2) + +@returns Void +TemplateSpans[Yield, Await, Tagged] : + TemplateTail + => template_spans(None, $0) + TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateTail + => template_spans(Some($0), $1) + +@returns Void +TemplateMiddleList[Yield, Await, Tagged] : + TemplateMiddle Expression[+In, ?Yield, ?Await] + => template_middle_list_single($0, $1) + TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateMiddle Expression[+In, ?Yield, ?Await] + => template_middle_list_append($0, $1, $2) + +@returns Expression +MemberExpression[Yield, Await] : + PrimaryExpression[?Yield, ?Await] + => $0 + MemberExpression[?Yield, ?Await] `[` Expression[+In, ?Yield, ?Await] `]` + => computed_member_expr($0, $2, $3) + MemberExpression[?Yield, ?Await] `.` IdentifierName + => static_member_expr($0, $2) + MemberExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] + => tagged_template_expr($0, $1) + SuperProperty[?Yield, ?Await] + => $0 + MetaProperty + => $0 + `new` MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await] + => new_expr_with_arguments($0, $1, $2) + MemberExpression[?Yield, ?Await] `.` PrivateIdentifier + => private_field_expr($0, $2) + +@returns Expression +SuperProperty[Yield, Await] : + `super` `[` Expression[+In, ?Yield, ?Await] `]` + => super_property_computed($0, $2, $3) + `super` `.` IdentifierName + => super_property_static($0, $2) + +@returns Expression +MetaProperty : + NewTarget + => $0 + +@returns Expression +NewTarget : + `new` `.` `target` + => new_target_expr($0, $2) + +@returns Expression +NewExpression[Yield, Await] : + MemberExpression[?Yield, ?Await] + => $0 + `new` NewExpression[?Yield, ?Await] + => new_expr_without_arguments($0, $1) + +@returns Expression +CallExpression[Yield, Await] : + CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] + => $0 + SuperCall[?Yield, ?Await] + => $0 + ImportCall[?Yield, ?Await] + => $0 + CallExpression[?Yield, ?Await] Arguments[?Yield, ?Await] + => call_expr($0, $1) + CallExpression[?Yield, ?Await] `[` Expression[+In, ?Yield, ?Await] `]` + => computed_member_expr($0, $2, $3) + CallExpression[?Yield, ?Await] `.` IdentifierName + => static_member_expr($0, $2) + CallExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] + => tagged_template_expr($0, $1) + CallExpression[?Yield, ?Await] `.` PrivateIdentifier + => private_field_expr($0, $2) + +@returns Expression +SuperCall[Yield, Await] : + `super` Arguments[?Yield, ?Await] + => super_call($0, $1) + +@returns Expression +ImportCall[Yield, Await] : + `import` `(` AssignmentExpression[+In, ?Yield, ?Await] `)` + => import_call($0, $2, $3) + +@returns Arguments +Arguments[Yield, Await] : + `(` `)` + => arguments_empty($0, $1) + `(` ArgumentList[?Yield, ?Await] `)` + => arguments($0, $1, $2) + `(` ArgumentList[?Yield, ?Await] `,` `)` + => arguments($0, $1, $3) + +@returns Arguments +ArgumentList[Yield, Await] : + AssignmentExpression[+In, ?Yield, ?Await] + => arguments_single($0) + `...` AssignmentExpression[+In, ?Yield, ?Await] + => arguments_spread_single($1) + ArgumentList[?Yield, ?Await] `,` AssignmentExpression[+In, ?Yield, ?Await] + => arguments_append($0, $2) + ArgumentList[?Yield, ?Await] `,` `...` AssignmentExpression[+In, ?Yield, ?Await] + => arguments_append_spread($0, $3) + +@returns Expression +OptionalExpression[Yield, Await] : + MemberExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] + => optional_expr($0, $1) + CallExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] + => optional_expr($0, $1) + OptionalExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] + => optional_expr($0, $1) + +@returns Expression +OptionalChain[Yield, Await] : + `?.` `[` Expression[+In, ?Yield, ?Await] `]` + => optional_computed_member_expr_tail($0, $2, $3) + `?.` IdentifierName + => optional_static_member_expr_tail($0, $1) + `?.` PrivateIdentifier + => optional_private_field_member_expr_tail($0, $1) + `?.` Arguments[?Yield, ?Await] + => optional_call_expr_tail($0, $1) + `?.` TemplateLiteral[?Yield, ?Await, +Tagged] + => error_optional_chain_with_template() + OptionalChain[?Yield, ?Await] `[` Expression[+In, ?Yield, ?Await] `]` + => optional_computed_member_expr($0, $2, $3) + OptionalChain[?Yield, ?Await] `.` IdentifierName + => optional_static_member_expr($0, $2) + OptionalChain[?Yield, ?Await] `.` PrivateIdentifier + => optional_private_field_member_expr($0, $2) + OptionalChain[?Yield, ?Await] Arguments[?Yield, ?Await] + => optional_call_expr($0, $1) + OptionalChain[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] + => error_optional_chain_with_template() + +@returns Expression +LeftHandSideExpression[Yield, Await] : + NewExpression[?Yield, ?Await] + => $0 + CallExpression[?Yield, ?Await] + => $0 + OptionalExpression[?Yield, ?Await] + => $0 + + +@returns Expression +CallMemberExpression[Yield, Await] : + MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await] + => call_expr($0, $1) + + +@returns Expression +UpdateExpression[Yield, Await] : + LeftHandSideExpression[?Yield, ?Await] + => $0 + LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] `++` + => post_increment_expr($0, $1) + LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] `--` + => post_decrement_expr($0, $1) + `++` UnaryExpression[?Yield, ?Await] + => pre_decrement_expr($0, $1) + `--` UnaryExpression[?Yield, ?Await] + => pre_decrement_expr($0, $1) + + +@returns Expression +UnaryExpression[Yield, Await] : + UpdateExpression[?Yield, ?Await] + => $0 + `delete` UnaryExpression[?Yield, ?Await] + => delete_expr($0, $1) + `void` UnaryExpression[?Yield, ?Await] + => void_expr($0, $1) + `typeof` UnaryExpression[?Yield, ?Await] + => typeof_expr($0, $1) + `+` UnaryExpression[?Yield, ?Await] + => unary_plus_expr($0, $1) + `-` UnaryExpression[?Yield, ?Await] + => unary_minus_expr($0, $1) + `~` UnaryExpression[?Yield, ?Await] + => bitwise_not_expr($0, $1) + `!` UnaryExpression[?Yield, ?Await] + => logical_not_expr($0, $1) + [+Await] AwaitExpression[?Yield] + => $0 + + +@returns Expression +ExponentiationExpression[Yield, Await] : + UnaryExpression[?Yield, ?Await] + => $0 + UpdateExpression[?Yield, ?Await] `**` ExponentiationExpression[?Yield, ?Await] + => binary_expr(pow_op($1), $0, $2) + + +@returns Expression +MultiplicativeExpression[Yield, Await] : + ExponentiationExpression[?Yield, ?Await] + => $0 + MultiplicativeExpression[?Yield, ?Await] MultiplicativeOperator ExponentiationExpression[?Yield, ?Await] + => multiplicative_expr($0, $1, $2) + +@returns BinaryOperator +MultiplicativeOperator : + `*` + => box_op(mul_op($0)) + `/` + => box_op(div_op($0)) + `%` + => box_op(mod_op($0)) + + +@returns Expression +AdditiveExpression[Yield, Await] : + MultiplicativeExpression[?Yield, ?Await] + => $0 + AdditiveExpression[?Yield, ?Await] `+` MultiplicativeExpression[?Yield, ?Await] + => binary_expr(add_op($1), $0, $2) + AdditiveExpression[?Yield, ?Await] `-` MultiplicativeExpression[?Yield, ?Await] + => binary_expr(sub_op($1), $0, $2) + + +@returns Expression +ShiftExpression[Yield, Await] : + AdditiveExpression[?Yield, ?Await] + => $0 + ShiftExpression[?Yield, ?Await] `<<` AdditiveExpression[?Yield, ?Await] + => binary_expr(left_shift_op($1), $0, $2) + ShiftExpression[?Yield, ?Await] `>>` AdditiveExpression[?Yield, ?Await] + => binary_expr(right_shift_op($1), $0, $2) + ShiftExpression[?Yield, ?Await] `>>>` AdditiveExpression[?Yield, ?Await] + => binary_expr(right_shift_ext_op($1), $0, $2) + + +@returns Expression +RelationalExpression[In, Yield, Await] : + ShiftExpression[?Yield, ?Await] + => $0 + RelationalExpression[?In, ?Yield, ?Await] `<` ShiftExpression[?Yield, ?Await] + => binary_expr(less_than_op($1), $0, $2) + RelationalExpression[?In, ?Yield, ?Await] `>` ShiftExpression[?Yield, ?Await] + => binary_expr(greater_than_op($1), $0, $2) + RelationalExpression[?In, ?Yield, ?Await] `<=` ShiftExpression[?Yield, ?Await] + => binary_expr(less_than_or_equal_op($1), $0, $2) + RelationalExpression[?In, ?Yield, ?Await] `>=` ShiftExpression[?Yield, ?Await] + => binary_expr(greater_than_or_equal_op($1), $0, $2) + RelationalExpression[?In, ?Yield, ?Await] `instanceof` ShiftExpression[?Yield, ?Await] + => binary_expr(instanceof_op($1), $0, $2) + [+In] RelationalExpression[+In, ?Yield, ?Await] `in` ShiftExpression[?Yield, ?Await] + => binary_expr(in_op($1), $0, $2) + + +@returns Expression +EqualityExpression[In, Yield, Await] : + RelationalExpression[?In, ?Yield, ?Await] + => $0 + EqualityExpression[?In, ?Yield, ?Await] `==` RelationalExpression[?In, ?Yield, ?Await] + => binary_expr(equals_op($1), $0, $2) + EqualityExpression[?In, ?Yield, ?Await] `!=` RelationalExpression[?In, ?Yield, ?Await] + => binary_expr(not_equals_op($1), $0, $2) + EqualityExpression[?In, ?Yield, ?Await] `===` RelationalExpression[?In, ?Yield, ?Await] + => binary_expr(strict_equals_op($1), $0, $2) + EqualityExpression[?In, ?Yield, ?Await] `!==` RelationalExpression[?In, ?Yield, ?Await] + => binary_expr(strict_not_equals_op($1), $0, $2) + + +@returns Expression +BitwiseANDExpression[In, Yield, Await] : + EqualityExpression[?In, ?Yield, ?Await] + => $0 + BitwiseANDExpression[?In, ?Yield, ?Await] `&` EqualityExpression[?In, ?Yield, ?Await] + => binary_expr(bitwise_and_op($1), $0, $2) + +@returns Expression +BitwiseXORExpression[In, Yield, Await] : + BitwiseANDExpression[?In, ?Yield, ?Await] + => $0 + BitwiseXORExpression[?In, ?Yield, ?Await] `^` BitwiseANDExpression[?In, ?Yield, ?Await] + => binary_expr(bitwise_xor_op($1), $0, $2) + +@returns Expression +BitwiseORExpression[In, Yield, Await] : + BitwiseXORExpression[?In, ?Yield, ?Await] + => $0 + BitwiseORExpression[?In, ?Yield, ?Await] `|` BitwiseXORExpression[?In, ?Yield, ?Await] + => binary_expr(bitwise_or_op($1), $0, $2) + +@returns Expression +LogicalANDExpression[In, Yield, Await] : + BitwiseORExpression[?In, ?Yield, ?Await] + => $0 + LogicalANDExpression[?In, ?Yield, ?Await] `&&` BitwiseORExpression[?In, ?Yield, ?Await] + => binary_expr(logical_and_op($1), $0, $2) + +@returns Expression +LogicalORExpression[In, Yield, Await] : + LogicalANDExpression[?In, ?Yield, ?Await] + => $0 + LogicalORExpression[?In, ?Yield, ?Await] `||` LogicalANDExpression[?In, ?Yield, ?Await] + => binary_expr(logical_or_op($1), $0, $2) + +@returns Expression +ShortCircuitExpression[In, Yield, Await] : + LogicalORExpression[?In, ?Yield, ?Await] + => $0 + CoalesceExpression[?In, ?Yield, ?Await] + => $0 + +@returns Expression +CoalesceExpression[In, Yield, Await] : + CoalesceExpressionHead[?In, ?Yield, ?Await] `??` BitwiseORExpression[?In, ?Yield, ?Await] + => binary_expr(coalesce_op($1), $0, $2) + +@returns Expression +CoalesceExpressionHead[In, Yield, Await] : + CoalesceExpression[?In, ?Yield, ?Await] + => $0 + BitwiseORExpression[?In, ?Yield, ?Await] + => $0 + +@returns Expression +ConditionalExpression[In, Yield, Await] : + ShortCircuitExpression[?In, ?Yield, ?Await] + => $0 + ShortCircuitExpression[?In, ?Yield, ?Await] `?` AssignmentExpression[+In, ?Yield, ?Await] `:` AssignmentExpression[?In, ?Yield, ?Await] + => conditional_expr($0, $2, $4) + + +@returns Expression +AssignmentExpression[In, Yield, Await] : + ConditionalExpression[?In, ?Yield, ?Await] + => $0 + [+Yield] YieldExpression[?In, ?Await] + => $0 + ArrowFunction[?In, ?Yield, ?Await] + => $0 + AsyncArrowFunction[?In, ?Yield, ?Await] + => $0 + LeftHandSideExpression[?Yield, ?Await] `=` AssignmentExpression[?In, ?Yield, ?Await] + => assignment_expr($0, $2) + LeftHandSideExpression[?Yield, ?Await] AssignmentOperator AssignmentExpression[?In, ?Yield, ?Await] + => compound_assignment_expr($0, $1, $2) + LeftHandSideExpression[?Yield, ?Await] LogicalAssignmentOperator AssignmentExpression[?In, ?Yield, ?Await] + => compound_assignment_expr($0, $1, $2) + +@returns CompoundAssignmentOperator +AssignmentOperator : + `*=` + => box_assign_op(mul_assign_op($0)) + `/=` + => box_assign_op(div_assign_op($0)) + `%=` + => box_assign_op(mod_assign_op($0)) + `+=` + => box_assign_op(add_assign_op($0)) + `-=` + => box_assign_op(sub_assign_op($0)) + `<<=` + => box_assign_op(left_shift_assign_op($0)) + `>>=` + => box_assign_op(right_shift_assign_op($0)) + `>>>=` + => box_assign_op(right_shift_ext_assign_op($0)) + `&=` + => box_assign_op(bitwise_and_assign_op($0)) + `^=` + => box_assign_op(bitwise_xor_assign_op($0)) + `|=` + => box_assign_op(bitwise_or_assign_op($0)) + `**=` + => box_assign_op(pow_assign_op($0)) + +@returns CompoundAssignmentOperator +LogicalAssignmentOperator : + `&&=` + => box_assign_op(logical_and_assign_op($0)) + `||=` + => box_assign_op(logical_or_assign_op($0)) + `??=` + => box_assign_op(coalesce_assign_op($0)) + +AssignmentPattern[Yield, Await] : + ObjectAssignmentPattern[?Yield, ?Await] + ArrayAssignmentPattern[?Yield, ?Await] + +ObjectAssignmentPattern[Yield, Await] : + `{` `}` + `{` AssignmentRestProperty[?Yield, ?Await] `}` + `{` AssignmentPropertyList[?Yield, ?Await] `}` + `{` AssignmentPropertyList[?Yield, ?Await] `,` AssignmentRestProperty[?Yield, ?Await]? `}` + +ArrayAssignmentPattern[Yield, Await] : + `[` Elision? AssignmentRestElement[?Yield, ?Await]? `]` + `[` AssignmentElementList[?Yield, ?Await] `]` + `[` AssignmentElementList[?Yield, ?Await] `,` Elision? AssignmentRestElement[?Yield, ?Await]? `]` + +AssignmentRestProperty[Yield, Await] : + `...` DestructuringAssignmentTarget[?Yield, ?Await] + +AssignmentPropertyList[Yield, Await] : + AssignmentProperty[?Yield, ?Await] + AssignmentPropertyList[?Yield, ?Await] `,` AssignmentProperty[?Yield, ?Await] + +AssignmentElementList[Yield, Await] : + AssignmentElisionElement[?Yield, ?Await] + AssignmentElementList[?Yield, ?Await] `,` AssignmentElisionElement[?Yield, ?Await] + +AssignmentElisionElement[Yield, Await] : + Elision? AssignmentElement[?Yield, ?Await] + +AssignmentProperty[Yield, Await] : + IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]? + PropertyName[?Yield, ?Await] `:` AssignmentElement[?Yield, ?Await] + +AssignmentElement[Yield, Await] : + DestructuringAssignmentTarget[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]? + +AssignmentRestElement[Yield, Await] : + `...` DestructuringAssignmentTarget[?Yield, ?Await] + +DestructuringAssignmentTarget[Yield, Await] : + LeftHandSideExpression[?Yield, ?Await] + + +@returns Expression +Expression[In, Yield, Await] : + AssignmentExpression[?In, ?Yield, ?Await] + => $0 + Expression[?In, ?Yield, ?Await] `,` AssignmentExpression[?In, ?Yield, ?Await] + => binary_expr(comma_op($1), $0, $2) + + +@returns Statement +Statement[Yield, Await, Return] : + BlockStatement[?Yield, ?Await, ?Return] + => $0 + VariableStatement[?Yield, ?Await] + => $0 + EmptyStatement + => $0 + ExpressionStatement[?Yield, ?Await] + => $0 + IfStatement[?Yield, ?Await, ?Return] + => $0 + BreakableStatement[?Yield, ?Await, ?Return] + => $0 + ContinueStatement[?Yield, ?Await] + => $0 + BreakStatement[?Yield, ?Await] + => $0 + [+Return] ReturnStatement[?Yield, ?Await] + => $0 + WithStatement[?Yield, ?Await, ?Return] + => $0 + LabelledStatement[?Yield, ?Await, ?Return] + => $0 + ThrowStatement[?Yield, ?Await] + => $0 + TryStatement[?Yield, ?Await, ?Return] + => $0 + DebuggerStatement + => $0 + +@returns Statement +Declaration[Yield, Await] : + HoistableDeclaration[?Yield, ?Await, ~Default] + => $0 + ClassDeclaration[?Yield, ?Await, ~Default] + => $0 + LexicalDeclaration[+In, ?Yield, ?Await] + => $0 + +@returns Statement +HoistableDeclaration[Yield, Await, Default] : + FunctionDeclaration[?Yield, ?Await, ?Default] + => $0 + GeneratorDeclaration[?Yield, ?Await, ?Default] + => $0 + AsyncFunctionDeclaration[?Yield, ?Await, ?Default] + => $0 + AsyncGeneratorDeclaration[?Yield, ?Await, ?Default] + => $0 + +@returns Statement +BreakableStatement[Yield, Await, Return] : + IterationStatement[?Yield, ?Await, ?Return] + => $0 + SwitchStatement[?Yield, ?Await, ?Return] + => $0 + + +@returns Statement +BlockStatement[Yield, Await, Return] : + Block[?Yield, ?Await, ?Return] + => block_statement($0) + +@returns Block +Block[Yield, Await, Return] : + `{` StatementList[?Yield, ?Await, ?Return]? `}` + => block($0, $1, $2) + +@returns Vec<Statement> +StatementList[Yield, Await, Return] : + StatementListItem[?Yield, ?Await, ?Return] + => statement_list_single($0) + StatementList[?Yield, ?Await, ?Return] StatementListItem[?Yield, ?Await, ?Return] + => statement_list_append($0, $1) + +@returns Statement +StatementListItem[Yield, Await, Return] : + Statement[?Yield, ?Await, ?Return] + => $0 + Declaration[?Yield, ?Await] + => $0 + + +@returns Statement +LexicalDeclaration[In, Yield, Await] : + LetOrConst BindingList[?In, ?Yield, ?Await] `;` + => lexical_declaration($0, $1) + +@returns VariableDeclarationOrExpression +ForLexicalDeclaration[In, Yield, Await] : + LetOrConst BindingList[?In, ?Yield, ?Await] `;` + => for_lexical_declaration($0, $1) + +@returns VariableDeclarationKind +LetOrConst : + `let` + => let_kind($0) + `const` + => const_kind($0) + +@returns Vec<VariableDeclarator> +BindingList[In, Yield, Await] : + LexicalBinding[?In, ?Yield, ?Await] + => variable_declaration_list_single($0) + BindingList[?In, ?Yield, ?Await] `,` LexicalBinding[?In, ?Yield, ?Await] + => variable_declaration_list_append($0, $2) + +@returns VariableDeclarator +LexicalBinding[In, Yield, Await] : + BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]? + => variable_declaration(binding_identifier_to_binding($0), $1) + BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await] + => variable_declaration($0, Some($1)) + + +@returns Statement +VariableStatement[Yield, Await] : + `var` VariableDeclarationList[+In, ?Yield, ?Await] `;` + => variable_statement($0, $1) + +@returns Vec<VariableDeclarator> +VariableDeclarationList[In, Yield, Await] : + VariableDeclaration[?In, ?Yield, ?Await] + => variable_declaration_list_single($0) + VariableDeclarationList[?In, ?Yield, ?Await] `,` VariableDeclaration[?In, ?Yield, ?Await] + => variable_declaration_list_append($0, $2) + +@returns VariableDeclarator +VariableDeclaration[In, Yield, Await] : + BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]? + => variable_declaration(binding_identifier_to_binding($0), $1) + BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await] + => variable_declaration($0, Some($1)) + + +@returns Binding +BindingPattern[Yield, Await] : + ObjectBindingPattern[?Yield, ?Await] + => $0 + ArrayBindingPattern[?Yield, ?Await] + => $0 + +@returns Binding +ObjectBindingPattern[Yield, Await] : + `{` `}` + => object_binding_pattern($0, binding_property_list_empty(), None, $1) + `{` BindingRestProperty[?Yield, ?Await] `}` + => object_binding_pattern($0, binding_property_list_empty(), Some($1), $2) + `{` BindingPropertyList[?Yield, ?Await] `}` + => object_binding_pattern($0, $1, None, $2) + `{` BindingPropertyList[?Yield, ?Await] `,` BindingRestProperty[?Yield, ?Await]? `}` + => object_binding_pattern($0, $1, $3, $4) + +@returns Binding +ArrayBindingPattern[Yield, Await] : + `[` Elision? BindingRestElement[?Yield, ?Await]? `]` + => array_binding_pattern($0, binding_element_list_empty(), $1, $2, $3) + `[` BindingElementList[?Yield, ?Await] `]` + => array_binding_pattern($0, $1, None, None, $2) + `[` BindingElementList[?Yield, ?Await] `,` Elision? BindingRestElement[?Yield, ?Await]? `]` + => array_binding_pattern($0, $1, $3, $4, $5) + +@returns BindingIdentifier +BindingRestProperty[Yield, Await] : + `...` BindingIdentifier[?Yield, ?Await] + => $1 + +@returns Vec<BindingProperty> +BindingPropertyList[Yield, Await] : + BindingProperty[?Yield, ?Await] + => binding_property_list_single($0) + BindingPropertyList[?Yield, ?Await] `,` BindingProperty[?Yield, ?Await] + => binding_property_list_append($0, $2) + +@returns Vec<Option<Parameter>> +BindingElementList[Yield, Await] : + BindingElisionElement[?Yield, ?Await] + => $0 + BindingElementList[?Yield, ?Await] `,` BindingElisionElement[?Yield, ?Await] + => binding_element_list_append($0, $2) + +@returns Vec<Option<Parameter>> +BindingElisionElement[Yield, Await] : + Elision? BindingElement[?Yield, ?Await] + => binding_elision_element($0, $1) + +@returns BindingProperty +BindingProperty[Yield, Await] : + SingleNameBinding[?Yield, ?Await] + => binding_property_shorthand($0) + PropertyName[?Yield, ?Await] `:` BindingElement[?Yield, ?Await] + => binding_property($0, $2) + +@returns Parameter +BindingElement[Yield, Await] : + SingleNameBinding[?Yield, ?Await] + => $0 + BindingPattern[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]? + => binding_element_pattern($0, $1) + +@returns Parameter +SingleNameBinding[Yield, Await] : + BindingIdentifier[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]? + => single_name_binding($0, $1) + +@returns Binding +BindingRestElement[Yield, Await] : + `...` BindingIdentifier[?Yield, ?Await] + => binding_identifier_to_binding($1) + `...` BindingPattern[?Yield, ?Await] + => $1 + + +@returns Statement +EmptyStatement : + `;` + => empty_statement($0) + +@returns Statement +ExpressionStatement[Yield, Await] : + [lookahead <! {`{`, `function`, `async`, `class`, `let`}] Expression[+In, ?Yield, ?Await] `;` + => expression_statement($0) + + +@returns Statement +IfStatement[Yield, Await, Return] : + `if` `(` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] `else` Statement[?Yield, ?Await, ?Return] + => if_statement($0, $2, $4, Some($6)) + `if` `(` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] [lookahead != `else`] + => if_statement($0, $2, $4, None) + `if` `(` Expression[+In, ?Yield, ?Await] `)` FunctionDeclaration[?Yield, ?Await, ~Default] `else` Statement[?Yield, ?Await, ?Return] + => if_statement($0, $2, make_block_stmt_from_function_decl($4), Some($6)) + `if` `(` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] `else` FunctionDeclaration[?Yield, ?Await, ~Default] + => if_statement($0, $2, $4, Some(make_block_stmt_from_function_decl($6))) + `if` `(` Expression[+In, ?Yield, ?Await] `)` FunctionDeclaration[?Yield, ?Await, ~Default] `else` FunctionDeclaration[?Yield, ?Await, ~Default] + => if_statement($0, $2, make_block_stmt_from_function_decl($4), Some(make_block_stmt_from_function_decl($6))) + `if` `(` Expression[+In, ?Yield, ?Await] `)` FunctionDeclaration[?Yield, ?Await, ~Default] [lookahead != `else`] + => if_statement($0, $2, make_block_stmt_from_function_decl($4), None) + + +@returns Statement +IterationStatement[Yield, Await, Return] : + `do` Statement[?Yield, ?Await, ?Return] `while` `(` Expression[+In, ?Yield, ?Await] `)` `;` + => do_while_statement($0, $1, $4, $5) + `while` `(` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + => while_statement($0, $2, $4) + `for` `(` [lookahead != `let`] Expression[~In, ?Yield, ?Await]? `;` Expression[+In, ?Yield, ?Await]? `;` Expression[+In, ?Yield, ?Await]? `)` Statement[?Yield, ?Await, ?Return] + => for_statement($0, for_expression($2), $4, $6, $8) + `for` `(` `var` VariableDeclarationList[~In, ?Yield, ?Await] `;` Expression[+In, ?Yield, ?Await]? `;` Expression[+In, ?Yield, ?Await]? `)` Statement[?Yield, ?Await, ?Return] + => for_statement($0, Some(for_var_declaration($2, $3)), $5, $7, $9) + `for` `(` ForLexicalDeclaration[~In, ?Yield, ?Await] Expression[+In, ?Yield, ?Await]? `;` Expression[+In, ?Yield, ?Await]? `)` Statement[?Yield, ?Await, ?Return] + => for_statement_lexical($0, unbox_for_lexical_declaration($2), $3, $5, $7) + `for` `(` [lookahead != `let`] LeftHandSideExpression[?Yield, ?Await] `in` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + => for_in_statement($0, for_assignment_target($2), $4, $6) + `for` `(` `var` ForBinding[?Yield, ?Await] `in` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + => for_in_statement($0, for_in_or_of_var_declaration($2, $3, None), $5, $7) + `for` `(` `var` BindingIdentifier[?Yield, ?Await] Initializer[~In, ?Yield, ?Await] `in` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + => for_in_statement($0, for_in_or_of_var_declaration($2, binding_identifier_to_binding($3), Some($4)), $6, $8) + `for` `(` ForDeclaration[?Yield, ?Await] `in` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + => for_in_statement_lexical($0, unbox_for_declaration($2), $4, $6) + `for` `(` [lookahead <! {`async`, `let`} ] LeftHandSideExpression[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + => for_of_statement($0, for_assignment_target($2), $4, $6) + `for` `(` `var` ForBinding[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + => for_of_statement($0, for_in_or_of_var_declaration($2, $3, None), $5, $7) + `for` `(` ForDeclaration[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + => for_of_statement_lexical($0, unbox_for_declaration($2), $4, $6) + [+Await] `for` `await` `(` [lookahead <! {`async`, `let`} ] LeftHandSideExpression[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + => for_await_of_statement($0, for_assignment_target($3), $5, $7) + [+Await] `for` `await` `(` `var` ForBinding[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + => for_await_of_statement($0, for_in_or_of_var_declaration($3, $4, None), $6, $8) + [+Await] `for` `await` `(` ForDeclaration[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + => for_await_of_statement_lexical($0, unbox_for_declaration($3), $5, $7) + +@returns VariableDeclarationOrAssignmentTarget +ForDeclaration[Yield, Await] : + LetOrConst ForBinding[?Yield, ?Await] + => for_declaration($0, $1) + +@returns Binding +ForBinding[Yield, Await] : + BindingIdentifier[?Yield, ?Await] + => binding_identifier_to_binding($0) + BindingPattern[?Yield, ?Await] + => $0 + + +@returns Statement +ContinueStatement[Yield, Await] : + `continue` `;` + => continue_statement($0, None) + `continue` [no LineTerminator here] LabelIdentifier[?Yield, ?Await] `;` + => continue_statement($0, Some($1)) + + +@returns Statement +BreakStatement[Yield, Await] : + `break` `;` + => break_statement($0, None) + `break` [no LineTerminator here] LabelIdentifier[?Yield, ?Await] `;` + => break_statement($0, Some($1)) + + +@returns Statement +ReturnStatement[Yield, Await] : + `return` `;` + => return_statement($0, None) + `return` [no LineTerminator here] Expression[+In, ?Yield, ?Await] `;` + => return_statement($0, Some($1)) + + +@returns Statement +WithStatement[Yield, Await, Return] : + `with` `(` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + => with_statement($0, $2, $4) + + +@returns Statement +SwitchStatement[Yield, Await, Return] : + `switch` `(` Expression[+In, ?Yield, ?Await] `)` CaseBlock[?Yield, ?Await, ?Return] + => switch_statement($0, $2, $4) + +@returns Statement +CaseBlock[Yield, Await, Return] : + `{` CaseClauses[?Yield, ?Await, ?Return]? `}` + => case_block($0, $1, $2) + `{` CaseClauses[?Yield, ?Await, ?Return]? DefaultClause[?Yield, ?Await, ?Return] CaseClauses[?Yield, ?Await, ?Return]? `}` + => case_block_with_default($0, $1, $2, $3, $4) + +@returns Vec<SwitchCase> +CaseClauses[Yield, Await, Return] : + CaseClause[?Yield, ?Await, ?Return] + => case_clauses_single($0) + CaseClauses[?Yield, ?Await, ?Return] CaseClause[?Yield, ?Await, ?Return] + => case_clauses_append($0, $1) + +@returns SwitchCase +CaseClause[Yield, Await, Return] : + `case` Expression[+In, ?Yield, ?Await] `:` StatementList[?Yield, ?Await, ?Return]? + => case_clause($0, $1, $2, $3) + +@returns SwitchDefault +DefaultClause[Yield, Await, Return] : + `default` `:` StatementList[?Yield, ?Await, ?Return]? + => default_clause($0, $1, $2) + + +@returns Statement +LabelledStatement[Yield, Await, Return] : + LabelIdentifier[?Yield, ?Await] `:` LabelledItem[?Yield, ?Await, ?Return] + => labelled_statement($0, $2) + +@returns Statement +LabelledItem[Yield, Await, Return] : + Statement[?Yield, ?Await, ?Return] + => $0 + FunctionDeclaration[?Yield, ?Await, ~Default] + => $0 + + +@returns Statement +ThrowStatement[Yield, Await] : + `throw` [no LineTerminator here] Expression[+In, ?Yield, ?Await] `;` + => throw_statement($0, $1) + +@returns Statement +TryStatement[Yield, Await, Return] : + `try` Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] + => try_statement($0, $1, Some($2), None) + `try` Block[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] + => try_statement($0, $1, None, Some($2)) + `try` Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] + => try_statement($0, $1, Some($2), Some($3)) + +@returns CatchClause +Catch[Yield, Await, Return] : + `catch` `(` CatchParameter[?Yield, ?Await] `)` CatchBlock[?Yield, ?Await, ?Return] + => catch($0, $2, $4) + `catch` Block[?Yield, ?Await, ?Return] + => catch_no_param($0, $1) + +@returns Block +CatchBlock[Yield, Await, Return] : + `{` StatementList[?Yield, ?Await, ?Return]? `}` + => catch_block($0, $1, $2) + +@returns Block +Finally[Yield, Await, Return] : + `finally` Block[?Yield, ?Await, ?Return] + => $1 + +@returns Binding +CatchParameter[Yield, Await] : + BindingIdentifier[?Yield, ?Await] + => binding_identifier_to_binding($0) + BindingPattern[?Yield, ?Await] + => $0 + + +@returns Statement +DebuggerStatement : + `debugger` `;` + => debugger_statement($0) + + +@returns Statement +FunctionDeclaration[Yield, Await, Default] : + `function` BindingIdentifier[?Yield, ?Await] `(` FormalParameters[~Yield, ~Await] `)` `{` FunctionBody[~Yield, ~Await] `}` + => function_decl(function($0, Some($1), $2, $3, $4, $5, $6, $7)) + [+Default] `function` `(` FormalParameters[~Yield, ~Await] `)` `{` FunctionBody[~Yield, ~Await] `}` + => function_decl(function($0, None, $1, $2, $3, $4, $5, $6)) + +@returns Expression +FunctionExpression : + `function` BindingIdentifier[~Yield, ~Await]? `(` FormalParameters[~Yield, ~Await] `)` `{` FunctionBody[~Yield, ~Await] `}` + => function_expr(function($0, $1, $2, $3, $4, $5, $6, $7)) + +@returns FormalParameters +UniqueFormalParameters[Yield, Await] : + FormalParameters[?Yield, ?Await] + => unique_formal_parameters($0) + +@returns FormalParameters +FormalParameters[Yield, Await] : + [empty] + => empty_formal_parameters() + FunctionRestParameter[?Yield, ?Await] + => with_rest_parameter(empty_formal_parameters(), $0) + FormalParameterList[?Yield, ?Await] + => $0 + FormalParameterList[?Yield, ?Await] `,` + => $0 + FormalParameterList[?Yield, ?Await] `,` FunctionRestParameter[?Yield, ?Await] + => with_rest_parameter($0, $2) + +@returns FormalParameters +FormalParameterList[Yield, Await] : + FormalParameter[?Yield, ?Await] + => formal_parameter_list_single($0) + FormalParameterList[?Yield, ?Await] `,` FormalParameter[?Yield, ?Await] + => formal_parameter_list_append($0, $2) + +@returns Binding +FunctionRestParameter[Yield, Await] : + BindingRestElement[?Yield, ?Await] + => $0 + +@returns Parameter +FormalParameter[Yield, Await] : + BindingElement[?Yield, ?Await] + => $0 + +@returns FunctionBody +FunctionBody[Yield, Await] : + FunctionStatementList[?Yield, ?Await] + => function_body($0) + +@returns Vec<Statement> +FunctionStatementList[Yield, Await] : + StatementList[?Yield, ?Await, +Return]? + => function_statement_list($0) + + +@returns Expression +ArrowFunction[In, Yield, Await] : + ArrowParameters[?Yield, ?Await] [no LineTerminator here] `=>` ConciseBody[?In] + => arrow_function($0, $2) + +@returns FormalParameters +ArrowParameters[Yield, Await] : + BindingIdentifier[?Yield, ?Await] + => arrow_parameters_bare($0) + CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await] + => uncover_arrow_parameters($0) + +@returns ArrowExpressionBody +ConciseBody[In] : + [lookahead != `{` ] AssignmentExpression[?In, ~Yield, ~Await] + => concise_body_expression($0) + `{` FunctionBody[~Yield, ~Await] `}` + => concise_body_block($0, $1, $2) + + +ArrowFormalParameters[Yield, Await] : + `(` UniqueFormalParameters[?Yield, ?Await] `)` + + +@returns MethodDefinition +MethodDefinition[Yield, Await] : + ClassElementName[?Yield, ?Await] `(` UniqueFormalParameters[~Yield, ~Await] `)` `{` FunctionBody[~Yield, ~Await] `}` + => method_definition($0, $1, $2, $3, $4, $5, $6) + GeneratorMethod[?Yield, ?Await] + => $0 + AsyncMethod[?Yield, ?Await] + => $0 + AsyncGeneratorMethod[?Yield, ?Await] + => $0 + `get` ClassElementName[?Yield, ?Await] `(` `)` `{` FunctionBody[~Yield, ~Await] `}` + => getter($0, $1, $4, $5, $6) + `set` ClassElementName[?Yield, ?Await] `(` PropertySetParameterList `)` `{` FunctionBody[~Yield, ~Await] `}` + => setter($0, $1, $2, $3, $4, $5, $6, $7) + +@returns Parameter +PropertySetParameterList : + FormalParameter[~Yield, ~Await] + => $0 + + +@returns MethodDefinition +GeneratorMethod[Yield, Await] : + `*` ClassElementName[?Yield, ?Await] `(` UniqueFormalParameters[+Yield, ~Await] `)` `{` GeneratorBody `}` + => generator_method($0, $1, $2, $3, $4, $5, $6, $7) + +@returns Statement +GeneratorDeclaration[Yield, Await, Default] : + `function` `*` BindingIdentifier[?Yield, ?Await] `(` FormalParameters[+Yield, ~Await] `)` `{` GeneratorBody `}` + => function_decl(generator($0, Some($2), $3, $4, $5, $6, $7, $8)) + [+Default] `function` `*` `(` FormalParameters[+Yield, ~Await] `)` `{` GeneratorBody `}` + => function_decl(generator($0, None, $2, $3, $4, $5, $6, $7)) + +@returns Expression +GeneratorExpression : + `function` `*` BindingIdentifier[+Yield, ~Await]? `(` FormalParameters[+Yield, ~Await] `)` `{` GeneratorBody `}` + => function_expr(generator($0, $2, $3, $4, $5, $6, $7, $8)) + +@returns FunctionBody +GeneratorBody : + FunctionBody[+Yield, ~Await] + => $0 + +@returns Expression +YieldExpression[In, Await] : + `yield` + => yield_expr($0, None) + `yield` [no LineTerminator here] AssignmentExpression[?In, +Yield, ?Await] + => yield_expr($0, Some($1)) + `yield` [no LineTerminator here] `*` AssignmentExpression[?In, +Yield, ?Await] + => yield_star_expr($0, $2) + + +@returns MethodDefinition +AsyncGeneratorMethod[Yield, Await] : + `async` [no LineTerminator here] `*` ClassElementName[?Yield, ?Await] `(` UniqueFormalParameters[+Yield, +Await] `)` `{` AsyncGeneratorBody `}` + => async_generator_method($0, $2, $3, $4, $5, $6, $7, $8) + +@returns Statement +AsyncGeneratorDeclaration[Yield, Await, Default] : + `async` [no LineTerminator here] `function` `*` BindingIdentifier[?Yield, ?Await] `(` FormalParameters[+Yield, +Await] `)` `{` AsyncGeneratorBody `}` + => function_decl(async_generator($0, Some($3), $4, $5, $6, $7, $8, $9)) + [+Default] `async` [no LineTerminator here] `function` `*` `(` FormalParameters[+Yield, +Await] `)` `{` AsyncGeneratorBody `}` + => function_decl(async_generator($0, None, $3, $4, $5, $6, $7, $8)) + +@returns Expression +AsyncGeneratorExpression : + `async` [no LineTerminator here] `function` `*` BindingIdentifier[+Yield, +Await]? `(` FormalParameters[+Yield, +Await] `)` `{` AsyncGeneratorBody `}` + => function_expr(async_function($0, $3, $4, $5, $6, $7, $8, $9)) + +@returns FunctionBody +AsyncGeneratorBody : + FunctionBody[+Yield, +Await] + => $0 + + +@returns Statement +ClassDeclaration[Yield, Await, Default] : + `class` BindingIdentifier[?Yield, ?Await] ClassTail[?Yield, ?Await] + => class_declaration($0, Some($1), $2) + [+Default] `class` ClassTail[?Yield, ?Await] + => class_declaration($0, None, $1) + +@returns Expression +ClassExpression[Yield, Await] : + `class` BindingIdentifier[?Yield, ?Await]? ClassTail[?Yield, ?Await] + => class_expression($0, $1, $2) + +@returns ClassExpression +ClassTail[Yield, Await] : + ClassHeritage[?Yield, ?Await]? `{` ClassBody[?Yield, ?Await]? `}` + => class_tail($0, $2, $3) + +@returns Expression +ClassHeritage[Yield, Await] : + `extends` LeftHandSideExpression[?Yield, ?Await] + => $1 + +@returns Vec<Box<ClassElement>> +ClassBody[Yield, Await] : + ClassElementList[?Yield, ?Await] + => $0 + +@returns Vec<Box<ClassElement>> +ClassElementList[Yield, Await] : + ClassElement[?Yield, ?Await] + => $0 + ClassElementList[?Yield, ?Await] ClassElement[?Yield, ?Await] + => class_element_list_append($0, $1) + +@returns ClassElement +FieldDefinition[Yield, Await] : + ClassElementName[?Yield, ?Await] Initializer[+In, ~Yield, ~Await]? + => class_field_definition($0, $1) + +@returns ClassElementName +ClassElementName[Yield, Await] : + PropertyName[?Yield, ?Await] + => property_name_to_class_element_name($0) + PrivateIdentifier + => class_element_name_private($0) + +@returns Vec<Box<ClassElement>> +ClassElement[Yield, Await] : + MethodDefinition[?Yield, ?Await] + => class_element($0) + `static` MethodDefinition[?Yield, ?Await] + => class_element_static($0, $1) + FieldDefinition[?Yield, ?Await] `;` + => class_element_to_vec($0) + `static` FieldDefinition[?Yield, ?Await] `;` + => class_element_static_field($0, $1) + `;` + => class_element_empty() + + +@returns Statement +AsyncFunctionDeclaration[Yield, Await, Default] : + `async` [no LineTerminator here] `function` BindingIdentifier[?Yield, ?Await] `(` FormalParameters[~Yield, +Await] `)` `{` AsyncFunctionBody `}` + => function_decl(async_function($0, Some($2), $3, $4, $5, $6, $7, $8)) + [+Default] `async` [no LineTerminator here] `function` `(` FormalParameters[~Yield, +Await] `)` `{` AsyncFunctionBody `}` + => function_decl(async_function($0, None, $2, $3, $4, $5, $6, $7)) + +@returns Expression +AsyncFunctionExpression : + `async` [no LineTerminator here] `function` `(` FormalParameters[~Yield, +Await] `)` `{` AsyncFunctionBody `}` + => function_expr(async_function($0, None, $2, $3, $4, $5, $6, $7)) + `async` [no LineTerminator here] `function` BindingIdentifier[~Yield, +Await] `(` FormalParameters[~Yield, +Await] `)` `{` AsyncFunctionBody `}` + => function_expr(async_function($0, Some($2), $3, $4, $5, $6, $7, $8)) + +@returns MethodDefinition +AsyncMethod[Yield, Await] : + `async` [no LineTerminator here] PropertyName[?Yield, ?Await] `(` UniqueFormalParameters[~Yield, +Await] `)` `{` AsyncFunctionBody `}` + => async_method($0, $1, $2, $3, $4, $5, $6, $7) + +@returns FunctionBody +AsyncFunctionBody : + FunctionBody[~Yield, +Await] + => $0 + +@returns Expression +AwaitExpression[Yield] : + `await` UnaryExpression[?Yield, +Await] + => await_expr($0, $1) + + +@returns Expression +AsyncArrowFunction[In, Yield, Await] : + `async` [no LineTerminator here] AsyncArrowBindingIdentifier[?Yield] [no LineTerminator here] `=>` AsyncConciseBody[?In] + => async_arrow_function_bare($0, $1, $3) + CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] [no LineTerminator here] `=>` AsyncConciseBody[?In] + => async_arrow_function($0, $2) + +@returns ArrowExpressionBody +AsyncConciseBody[In] : + [lookahead != `{`] AssignmentExpression[?In, ~Yield, +Await] + => concise_body_expression($0) + `{` AsyncFunctionBody `}` + => concise_body_block($0, $1, $2) + +@returns BindingIdentifier +AsyncArrowBindingIdentifier[Yield] : + BindingIdentifier[?Yield, +Await] + => $0 + +@returns Expression +CoverCallExpressionAndAsyncArrowHead[Yield, Await] : + MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await] + => call_expr($0, $1) + + +AsyncArrowHead : + `async` [no LineTerminator here] ArrowFormalParameters[~Yield, +Await] + + +@returns Script +Script : + ScriptBody? + => script($0) + +@returns Script +ScriptBody : + StatementList[~Yield, ~Await, ~Return] + => script_body($0) + +@returns Vec<Statement> +Module : + ModuleBody? + => module($0) + +@returns Vec<Statement> +ModuleBody : + ModuleItemList + => $0 + +@returns Vec<Statement> +ModuleItemList : + ModuleItem + => module_item_list_single($0) + ModuleItemList ModuleItem + => module_item_list_append($0, $1) + +@returns Statement +ModuleItem : + ImportDeclaration + => $0 + ExportDeclaration + => $0 + StatementListItem[~Yield, ~Await, ~Return] + => $0 + + +@returns Statement +ImportDeclaration : + `import` ImportClause FromClause `;` + => import_declaration(Some($1), $2) + `import` ModuleSpecifier `;` + => import_declaration(None, $1) + +@returns Void +ImportClause : + ImportedDefaultBinding + => import_clause(Some($0), None, None) + NameSpaceImport + => import_clause(None, Some($0), None) + NamedImports + => import_clause(None, None, Some($0)) + ImportedDefaultBinding `,` NameSpaceImport + => import_clause(Some($0), Some($2), None) + ImportedDefaultBinding `,` NamedImports + => import_clause(Some($0), None, Some($2)) + +@returns BindingIdentifier +ImportedDefaultBinding : + ImportedBinding + => $0 + +@returns Void +NameSpaceImport : + `*` `as` ImportedBinding + => name_space_import($2) + +@returns Void +NamedImports : + `{` `}` + => imports_list_empty() + `{` ImportsList `}` + => $1 + `{` ImportsList `,` `}` + => $1 + +@returns Token +FromClause : + `from` ModuleSpecifier + => $1 + +@returns Void +ImportsList : + ImportSpecifier + => imports_list_append(imports_list_empty(), $0) + ImportsList `,` ImportSpecifier + => imports_list_append($0, $2) + +@returns Void +ImportSpecifier : + ImportedBinding + => import_specifier($0) + IdentifierName `as` ImportedBinding + => import_specifier_renaming($0, $2) + +@returns Token +ModuleSpecifier : + StringLiteral + => module_specifier($0) + +@returns BindingIdentifier +ImportedBinding : + BindingIdentifier[~Yield, ~Await] + => $0 + + +@returns Statement +ExportDeclaration : + `export` `*` FromClause `;` + => export_all_from($2) + `export` ExportClause FromClause `;` + => export_set_from($1, $2) + `export` ExportClause `;` + => export_set($1) + `export` VariableStatement[~Yield, ~Await] + => export_vars($1) + `export` Declaration[~Yield, ~Await] + => export_declaration($1) + `export` `default` HoistableDeclaration[~Yield, ~Await, +Default] + => export_default_hoistable($2) + `export` `default` ClassDeclaration[~Yield, ~Await, +Default] + => export_default_class($2) + `export` `default` [lookahead <! {`function`, `async`, `class`}] AssignmentExpression[+In, ~Yield, ~Await] `;` + => export_default_value($2) + +@returns Void +ExportClause : + `{` `}` + => exports_list_empty() + `{` ExportsList `}` + => $1 + `{` ExportsList `,` `}` + => $1 + +@returns Void +ExportsList : + ExportSpecifier + => exports_list_append(exports_list_empty(), $0) + ExportsList `,` ExportSpecifier + => exports_list_append($0, $2) + +@returns Void +ExportSpecifier : + IdentifierName + => export_specifier($0) + IdentifierName `as` IdentifierName + => export_specifier_renaming($0, $2) + diff --git a/third_party/rust/jsparagus/js_parser/es.esgrammar b/third_party/rust/jsparagus/js_parser/es.esgrammar new file mode 100644 index 0000000000..955fbdfe00 --- /dev/null +++ b/third_party/rust/jsparagus/js_parser/es.esgrammar @@ -0,0 +1,1668 @@ + +StringNumericLiteral ::: + StrWhiteSpace? + StrWhiteSpace? StrNumericLiteral StrWhiteSpace? + +StrWhiteSpace ::: + StrWhiteSpaceChar StrWhiteSpace? + +StrWhiteSpaceChar ::: + WhiteSpace + LineTerminator + +StrNumericLiteral ::: + StrDecimalLiteral + BinaryIntegerLiteral + OctalIntegerLiteral + HexIntegerLiteral + +StrDecimalLiteral ::: + StrUnsignedDecimalLiteral + `+` StrUnsignedDecimalLiteral + `-` StrUnsignedDecimalLiteral + +StrUnsignedDecimalLiteral ::: + `Infinity` + DecimalDigits `.` DecimalDigits? ExponentPart? + `.` DecimalDigits ExponentPart? + DecimalDigits ExponentPart? + + +SourceCharacter :: + > any Unicode code point + + +InputElementDiv :: + WhiteSpace + LineTerminator + Comment + CommonToken + DivPunctuator + RightBracePunctuator + +InputElementRegExp :: + WhiteSpace + LineTerminator + Comment + CommonToken + RightBracePunctuator + RegularExpressionLiteral + +InputElementRegExpOrTemplateTail :: + WhiteSpace + LineTerminator + Comment + CommonToken + RegularExpressionLiteral + TemplateSubstitutionTail + +InputElementTemplateTail :: + WhiteSpace + LineTerminator + Comment + CommonToken + DivPunctuator + TemplateSubstitutionTail + + +WhiteSpace :: + <TAB> + <VT> + <FF> + <SP> + <NBSP> + <ZWNBSP> + <USP> + + +LineTerminator :: + <LF> + <CR> + <LS> + <PS> + +LineTerminatorSequence :: + <LF> + <CR> [lookahead != <LF> ] + <LS> + <PS> + <CR> <LF> + + +Comment :: + MultiLineComment + SingleLineComment + +MultiLineComment :: + `/*` MultiLineCommentChars? `*/` + +MultiLineCommentChars :: + MultiLineNotAsteriskChar MultiLineCommentChars? + `*` PostAsteriskCommentChars? + +PostAsteriskCommentChars :: + MultiLineNotForwardSlashOrAsteriskChar MultiLineCommentChars? + `*` PostAsteriskCommentChars? + +MultiLineNotAsteriskChar :: + SourceCharacter but not `*` + +MultiLineNotForwardSlashOrAsteriskChar :: + SourceCharacter but not one of `/` or `*` + +SingleLineComment :: + `//` SingleLineCommentChars? + +SingleLineCommentChars :: + SingleLineCommentChar SingleLineCommentChars? + +SingleLineCommentChar :: + SourceCharacter but not LineTerminator + + +CommonToken :: + IdentifierName + Punctuator + NumericLiteral + StringLiteral + Template + + +IdentifierName :: + IdentifierStart + IdentifierName IdentifierPart + +IdentifierStart :: + UnicodeIDStart + `$` + `_` + `\` UnicodeEscapeSequence + +IdentifierPart :: + UnicodeIDContinue + `$` + `\` UnicodeEscapeSequence + <ZWNJ> + <ZWJ> + +UnicodeIDStart :: + > any Unicode code point with the Unicode property “ID_Start” + +UnicodeIDContinue :: + > any Unicode code point with the Unicode property “ID_Continue” + + +ReservedWord :: + Keyword + FutureReservedWord + NullLiteral + BooleanLiteral + + +Keyword :: one of + `await` + `break` + `case` `catch` `class` `const` `continue` + `debugger` `default` `delete` `do` + `else` `export` `extends` + `finally` `for` `function` + `if` `import` `in` `instanceof` + `new` + `return` + `super` `switch` + `this` `throw` `try` `typeof` + `var` `void` + `while` `with` + `yield` + + +FutureReservedWord :: + `enum` + + +Punctuator :: one of + `{` `(` `)` `[` `]` + `.` `...` `;` `,` + `<` `>` `<=` `>=` + `==` `!=` `===` `!==` + `+` `-` `*` `%` `**` + `++` `--` + `<<` `>>` `>>>` + `&` `|` `^` + `!` `~` + `&&` `||` + `?` `:` + `=` `+=` `-=` `*=` `%=` `**=` `<<=` `>>=` `>>>=` `&=` `|=` `^=` + `=>` + +DivPunctuator :: + `/` + `/=` + +RightBracePunctuator :: + `}` + + +NullLiteral :: + `null` + + +BooleanLiteral :: + `true` + `false` + + +NumericLiteral :: + DecimalLiteral + BinaryIntegerLiteral + OctalIntegerLiteral + HexIntegerLiteral + +DecimalLiteral :: + DecimalIntegerLiteral `.` DecimalDigits? ExponentPart? + `.` DecimalDigits ExponentPart? + DecimalIntegerLiteral ExponentPart? + +DecimalIntegerLiteral :: + `0` + NonZeroDigit DecimalDigits? + +DecimalDigits :: + DecimalDigit + DecimalDigits DecimalDigit + +DecimalDigit :: one of + `0` `1` `2` `3` `4` `5` `6` `7` `8` `9` + +NonZeroDigit :: one of + `1` `2` `3` `4` `5` `6` `7` `8` `9` + +ExponentPart :: + ExponentIndicator SignedInteger + +ExponentIndicator :: one of + `e` `E` + +SignedInteger :: + DecimalDigits + `+` DecimalDigits + `-` DecimalDigits + +BinaryIntegerLiteral :: + `0b` BinaryDigits + `0B` BinaryDigits + +BinaryDigits :: + BinaryDigit + BinaryDigits BinaryDigit + +BinaryDigit :: one of + `0` `1` + +OctalIntegerLiteral :: + `0o` OctalDigits + `0O` OctalDigits + +OctalDigits :: + OctalDigit + OctalDigits OctalDigit + +OctalDigit :: one of + `0` `1` `2` `3` `4` `5` `6` `7` + +HexIntegerLiteral :: + `0x` HexDigits + `0X` HexDigits + +HexDigits :: + HexDigit + HexDigits HexDigit + +HexDigit :: one of + `0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `a` `b` `c` `d` `e` `f` `A` `B` `C` `D` `E` `F` + + +StringLiteral :: + `"` DoubleStringCharacters? `"` + `'` SingleStringCharacters? `'` + +DoubleStringCharacters :: + DoubleStringCharacter DoubleStringCharacters? + +SingleStringCharacters :: + SingleStringCharacter SingleStringCharacters? + +DoubleStringCharacter :: + SourceCharacter but not one of `"` or `\` or LineTerminator + <LS> + <PS> + `\` EscapeSequence + LineContinuation + +SingleStringCharacter :: + SourceCharacter but not one of `'` or `\` or LineTerminator + <LS> + <PS> + `\` EscapeSequence + LineContinuation + +LineContinuation :: + `\` LineTerminatorSequence + +EscapeSequence :: + CharacterEscapeSequence + `0` [lookahead <! DecimalDigit] + HexEscapeSequence + UnicodeEscapeSequence + + +CharacterEscapeSequence :: + SingleEscapeCharacter + NonEscapeCharacter + +SingleEscapeCharacter :: one of + `'` `"` `\` `b` `f` `n` `r` `t` `v` + +NonEscapeCharacter :: + SourceCharacter but not one of EscapeCharacter or LineTerminator + +EscapeCharacter :: + SingleEscapeCharacter + DecimalDigit + `x` + `u` + +HexEscapeSequence :: + `x` HexDigit HexDigit + +UnicodeEscapeSequence :: + `u` Hex4Digits + `u{` CodePoint `}` + +Hex4Digits :: + HexDigit HexDigit HexDigit HexDigit + + +RegularExpressionLiteral :: + `/` RegularExpressionBody `/` RegularExpressionFlags + +RegularExpressionBody :: + RegularExpressionFirstChar RegularExpressionChars + +RegularExpressionChars :: + [empty] + RegularExpressionChars RegularExpressionChar + +RegularExpressionFirstChar :: + RegularExpressionNonTerminator but not one of `*` or `\` or `/` or `[` + RegularExpressionBackslashSequence + RegularExpressionClass + +RegularExpressionChar :: + RegularExpressionNonTerminator but not one of `\` or `/` or `[` + RegularExpressionBackslashSequence + RegularExpressionClass + +RegularExpressionBackslashSequence :: + `\` RegularExpressionNonTerminator + +RegularExpressionNonTerminator :: + SourceCharacter but not LineTerminator + +RegularExpressionClass :: + `[` RegularExpressionClassChars `]` + +RegularExpressionClassChars :: + [empty] + RegularExpressionClassChars RegularExpressionClassChar + +RegularExpressionClassChar :: + RegularExpressionNonTerminator but not one of `]` or `\` + RegularExpressionBackslashSequence + +RegularExpressionFlags :: + [empty] + RegularExpressionFlags IdentifierPart + + +Template :: + NoSubstitutionTemplate + TemplateHead + +NoSubstitutionTemplate :: + ``` TemplateCharacters? ``` + +TemplateHead :: + ``` TemplateCharacters? `${` + +TemplateSubstitutionTail :: + TemplateMiddle + TemplateTail + +TemplateMiddle :: + `}` TemplateCharacters? `${` + +TemplateTail :: + `}` TemplateCharacters? ``` + +TemplateCharacters :: + TemplateCharacter TemplateCharacters? + +TemplateCharacter :: + `$` [lookahead != `{` ] + `\` EscapeSequence + `\` NotEscapeSequence + LineContinuation + LineTerminatorSequence + SourceCharacter but not one of ``` or `\` or `$` or LineTerminator + +NotEscapeSequence :: + `0` DecimalDigit + DecimalDigit but not `0` + `x` [lookahead <! HexDigit] + `x` HexDigit [lookahead <! HexDigit] + `u` [lookahead <! HexDigit] [lookahead != `{`] + `u` HexDigit [lookahead <! HexDigit] + `u` HexDigit HexDigit [lookahead <! HexDigit] + `u` HexDigit HexDigit HexDigit [lookahead <! HexDigit] + `u` `{` [lookahead <! HexDigit] + `u` `{` NotCodePoint [lookahead <! HexDigit] + `u` `{` CodePoint [lookahead <! HexDigit] [lookahead != `}`] + +NotCodePoint :: + HexDigits [> but only if MV of |HexDigits| > 0x10FFFF ] + +CodePoint :: + HexDigits [> but only if MV of |HexDigits| ≤ 0x10FFFF ] + + +IdentifierReference[Yield, Await] : + Identifier + [~Yield] `yield` + [~Await] `await` + +BindingIdentifier[Yield, Await] : + Identifier + `yield` + `await` + +LabelIdentifier[Yield, Await] : + Identifier + [~Yield] `yield` + [~Await] `await` + +Identifier : + IdentifierName but not ReservedWord + + +PrimaryExpression[Yield, Await] : + `this` + IdentifierReference[?Yield, ?Await] + Literal + ArrayLiteral[?Yield, ?Await] + ObjectLiteral[?Yield, ?Await] + FunctionExpression + ClassExpression[?Yield, ?Await] + GeneratorExpression + AsyncFunctionExpression + AsyncGeneratorExpression + RegularExpressionLiteral + TemplateLiteral[?Yield, ?Await, ~Tagged] + CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await] #parencover + +CoverParenthesizedExpressionAndArrowParameterList[Yield, Await] : + `(` Expression[+In, ?Yield, ?Await] `)` + `(` Expression[+In, ?Yield, ?Await] `,` `)` + `(` `)` + `(` `...` BindingIdentifier[?Yield, ?Await] `)` + `(` `...` BindingPattern[?Yield, ?Await] `)` + `(` Expression[+In, ?Yield, ?Await] `,` `...` BindingIdentifier[?Yield, ?Await] `)` + `(` Expression[+In, ?Yield, ?Await] `,` `...` BindingPattern[?Yield, ?Await] `)` + + +ParenthesizedExpression[Yield, Await] : + `(` Expression[+In, ?Yield, ?Await] `)` + + +Literal : + NullLiteral + BooleanLiteral + NumericLiteral + StringLiteral + + +ArrayLiteral[Yield, Await] : + `[` Elision? `]` + `[` ElementList[?Yield, ?Await] `]` + `[` ElementList[?Yield, ?Await] `,` Elision? `]` + +ElementList[Yield, Await] : + Elision? AssignmentExpression[+In, ?Yield, ?Await] + Elision? SpreadElement[?Yield, ?Await] + ElementList[?Yield, ?Await] `,` Elision? AssignmentExpression[+In, ?Yield, ?Await] + ElementList[?Yield, ?Await] `,` Elision? SpreadElement[?Yield, ?Await] + +Elision : + `,` + Elision `,` + +SpreadElement[Yield, Await] : + `...` AssignmentExpression[+In, ?Yield, ?Await] + + +ObjectLiteral[Yield, Await] : + `{` `}` + `{` PropertyDefinitionList[?Yield, ?Await] `}` + `{` PropertyDefinitionList[?Yield, ?Await] `,` `}` + +PropertyDefinitionList[Yield, Await] : + PropertyDefinition[?Yield, ?Await] + PropertyDefinitionList[?Yield, ?Await] `,` PropertyDefinition[?Yield, ?Await] + +PropertyDefinition[Yield, Await] : + IdentifierReference[?Yield, ?Await] + CoverInitializedName[?Yield, ?Await] + PropertyName[?Yield, ?Await] `:` AssignmentExpression[+In, ?Yield, ?Await] + MethodDefinition[?Yield, ?Await] + `...` AssignmentExpression[+In, ?Yield, ?Await] + +PropertyName[Yield, Await] : + LiteralPropertyName + ComputedPropertyName[?Yield, ?Await] + +LiteralPropertyName : + IdentifierName + StringLiteral + NumericLiteral + +ComputedPropertyName[Yield, Await] : + `[` AssignmentExpression[+In, ?Yield, ?Await] `]` + +CoverInitializedName[Yield, Await] : + IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await] + +Initializer[In, Yield, Await] : + `=` AssignmentExpression[?In, ?Yield, ?Await] + + +TemplateLiteral[Yield, Await, Tagged] : + NoSubstitutionTemplate + SubstitutionTemplate[?Yield, ?Await, ?Tagged] + +SubstitutionTemplate[Yield, Await, Tagged] : + TemplateHead Expression[+In, ?Yield, ?Await] TemplateSpans[?Yield, ?Await, ?Tagged] + +TemplateSpans[Yield, Await, Tagged] : + TemplateTail + TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateTail + +TemplateMiddleList[Yield, Await, Tagged] : + TemplateMiddle Expression[+In, ?Yield, ?Await] + TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateMiddle Expression[+In, ?Yield, ?Await] + + +MemberExpression[Yield, Await] : + PrimaryExpression[?Yield, ?Await] + MemberExpression[?Yield, ?Await] `[` Expression[+In, ?Yield, ?Await] `]` + MemberExpression[?Yield, ?Await] `.` IdentifierName + MemberExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] + SuperProperty[?Yield, ?Await] + MetaProperty + `new` MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await] + +SuperProperty[Yield, Await] : + `super` `[` Expression[+In, ?Yield, ?Await] `]` + `super` `.` IdentifierName + +MetaProperty : + NewTarget + +NewTarget : + `new` `.` `target` + +NewExpression[Yield, Await] : + MemberExpression[?Yield, ?Await] + `new` NewExpression[?Yield, ?Await] + +CallExpression[Yield, Await] : + CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] #callcover + SuperCall[?Yield, ?Await] + ImportCall[?Yield, ?Await] + CallExpression[?Yield, ?Await] Arguments[?Yield, ?Await] + CallExpression[?Yield, ?Await] `[` Expression[+In, ?Yield, ?Await] `]` + CallExpression[?Yield, ?Await] `.` IdentifierName + CallExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] + +SuperCall[Yield, Await] : + `super` Arguments[?Yield, ?Await] + +ImportCall[Yield, Await] : + `import` `(` AssignmentExpression[+In, ?Yield, ?Await] `)` + +Arguments[Yield, Await] : + `(` `)` + `(` ArgumentList[?Yield, ?Await] `)` + `(` ArgumentList[?Yield, ?Await] `,` `)` + +ArgumentList[Yield, Await] : + AssignmentExpression[+In, ?Yield, ?Await] + `...` AssignmentExpression[+In, ?Yield, ?Await] + ArgumentList[?Yield, ?Await] `,` AssignmentExpression[+In, ?Yield, ?Await] + ArgumentList[?Yield, ?Await] `,` `...` AssignmentExpression[+In, ?Yield, ?Await] + +LeftHandSideExpression[Yield, Await] : + NewExpression[?Yield, ?Await] + CallExpression[?Yield, ?Await] + + +CallMemberExpression[Yield, Await] : + MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await] + + +UpdateExpression[Yield, Await] : + LeftHandSideExpression[?Yield, ?Await] + LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] `++` + LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] `--` + `++` UnaryExpression[?Yield, ?Await] + `--` UnaryExpression[?Yield, ?Await] + + +UnaryExpression[Yield, Await] : + UpdateExpression[?Yield, ?Await] + `delete` UnaryExpression[?Yield, ?Await] + `void` UnaryExpression[?Yield, ?Await] + `typeof` UnaryExpression[?Yield, ?Await] + `+` UnaryExpression[?Yield, ?Await] + `-` UnaryExpression[?Yield, ?Await] + `~` UnaryExpression[?Yield, ?Await] + `!` UnaryExpression[?Yield, ?Await] + [+Await] AwaitExpression[?Yield] + + +ExponentiationExpression[Yield, Await] : + UnaryExpression[?Yield, ?Await] + UpdateExpression[?Yield, ?Await] `**` ExponentiationExpression[?Yield, ?Await] + + +MultiplicativeExpression[Yield, Await] : + ExponentiationExpression[?Yield, ?Await] + MultiplicativeExpression[?Yield, ?Await] MultiplicativeOperator ExponentiationExpression[?Yield, ?Await] + +MultiplicativeOperator : one of + `*` `/` `%` + + +AdditiveExpression[Yield, Await] : + MultiplicativeExpression[?Yield, ?Await] + AdditiveExpression[?Yield, ?Await] `+` MultiplicativeExpression[?Yield, ?Await] + AdditiveExpression[?Yield, ?Await] `-` MultiplicativeExpression[?Yield, ?Await] + + +ShiftExpression[Yield, Await] : + AdditiveExpression[?Yield, ?Await] + ShiftExpression[?Yield, ?Await] `<<` AdditiveExpression[?Yield, ?Await] + ShiftExpression[?Yield, ?Await] `>>` AdditiveExpression[?Yield, ?Await] + ShiftExpression[?Yield, ?Await] `>>>` AdditiveExpression[?Yield, ?Await] + + +RelationalExpression[In, Yield, Await] : + ShiftExpression[?Yield, ?Await] + RelationalExpression[?In, ?Yield, ?Await] `<` ShiftExpression[?Yield, ?Await] + RelationalExpression[?In, ?Yield, ?Await] `>` ShiftExpression[?Yield, ?Await] + RelationalExpression[?In, ?Yield, ?Await] `<=` ShiftExpression[?Yield, ?Await] + RelationalExpression[?In, ?Yield, ?Await] `>=` ShiftExpression[?Yield, ?Await] + RelationalExpression[?In, ?Yield, ?Await] `instanceof` ShiftExpression[?Yield, ?Await] + [+In] RelationalExpression[+In, ?Yield, ?Await] `in` ShiftExpression[?Yield, ?Await] + + +EqualityExpression[In, Yield, Await] : + RelationalExpression[?In, ?Yield, ?Await] + EqualityExpression[?In, ?Yield, ?Await] `==` RelationalExpression[?In, ?Yield, ?Await] + EqualityExpression[?In, ?Yield, ?Await] `!=` RelationalExpression[?In, ?Yield, ?Await] + EqualityExpression[?In, ?Yield, ?Await] `===` RelationalExpression[?In, ?Yield, ?Await] + EqualityExpression[?In, ?Yield, ?Await] `!==` RelationalExpression[?In, ?Yield, ?Await] + + +BitwiseANDExpression[In, Yield, Await] : + EqualityExpression[?In, ?Yield, ?Await] + BitwiseANDExpression[?In, ?Yield, ?Await] `&` EqualityExpression[?In, ?Yield, ?Await] + +BitwiseXORExpression[In, Yield, Await] : + BitwiseANDExpression[?In, ?Yield, ?Await] + BitwiseXORExpression[?In, ?Yield, ?Await] `^` BitwiseANDExpression[?In, ?Yield, ?Await] + +BitwiseORExpression[In, Yield, Await] : + BitwiseXORExpression[?In, ?Yield, ?Await] + BitwiseORExpression[?In, ?Yield, ?Await] `|` BitwiseXORExpression[?In, ?Yield, ?Await] + + +LogicalANDExpression[In, Yield, Await] : + BitwiseORExpression[?In, ?Yield, ?Await] + LogicalANDExpression[?In, ?Yield, ?Await] `&&` BitwiseORExpression[?In, ?Yield, ?Await] + +LogicalORExpression[In, Yield, Await] : + LogicalANDExpression[?In, ?Yield, ?Await] + LogicalORExpression[?In, ?Yield, ?Await] `||` LogicalANDExpression[?In, ?Yield, ?Await] + + +ConditionalExpression[In, Yield, Await] : + LogicalORExpression[?In, ?Yield, ?Await] + LogicalORExpression[?In, ?Yield, ?Await] `?` AssignmentExpression[+In, ?Yield, ?Await] `:` AssignmentExpression[?In, ?Yield, ?Await] + + +AssignmentExpression[In, Yield, Await] : + ConditionalExpression[?In, ?Yield, ?Await] + [+Yield] YieldExpression[?In, ?Await] + ArrowFunction[?In, ?Yield, ?Await] + AsyncArrowFunction[?In, ?Yield, ?Await] + LeftHandSideExpression[?Yield, ?Await] `=` AssignmentExpression[?In, ?Yield, ?Await] #assignment + LeftHandSideExpression[?Yield, ?Await] AssignmentOperator AssignmentExpression[?In, ?Yield, ?Await] + +AssignmentOperator : one of + `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `>>>=` `&=` `^=` `|=` `**=` + + +AssignmentPattern[Yield, Await] : + ObjectAssignmentPattern[?Yield, ?Await] + ArrayAssignmentPattern[?Yield, ?Await] + +ObjectAssignmentPattern[Yield, Await] : + `{` `}` + `{` AssignmentRestProperty[?Yield, ?Await] `}` + `{` AssignmentPropertyList[?Yield, ?Await] `}` + `{` AssignmentPropertyList[?Yield, ?Await] `,` AssignmentRestProperty[?Yield, ?Await]? `}` + +ArrayAssignmentPattern[Yield, Await] : + `[` Elision? AssignmentRestElement[?Yield, ?Await]? `]` + `[` AssignmentElementList[?Yield, ?Await] `]` + `[` AssignmentElementList[?Yield, ?Await] `,` Elision? AssignmentRestElement[?Yield, ?Await]? `]` + +AssignmentRestProperty[Yield, Await] : + `...` DestructuringAssignmentTarget[?Yield, ?Await] + +AssignmentPropertyList[Yield, Await] : + AssignmentProperty[?Yield, ?Await] + AssignmentPropertyList[?Yield, ?Await] `,` AssignmentProperty[?Yield, ?Await] + +AssignmentElementList[Yield, Await] : + AssignmentElisionElement[?Yield, ?Await] + AssignmentElementList[?Yield, ?Await] `,` AssignmentElisionElement[?Yield, ?Await] + +AssignmentElisionElement[Yield, Await] : + Elision? AssignmentElement[?Yield, ?Await] + +AssignmentProperty[Yield, Await] : + IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]? + PropertyName[?Yield, ?Await] `:` AssignmentElement[?Yield, ?Await] + +AssignmentElement[Yield, Await] : + DestructuringAssignmentTarget[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]? + +AssignmentRestElement[Yield, Await] : + `...` DestructuringAssignmentTarget[?Yield, ?Await] + +DestructuringAssignmentTarget[Yield, Await] : + LeftHandSideExpression[?Yield, ?Await] + + +Expression[In, Yield, Await] : + AssignmentExpression[?In, ?Yield, ?Await] + Expression[?In, ?Yield, ?Await] `,` AssignmentExpression[?In, ?Yield, ?Await] + + +Statement[Yield, Await, Return] : + BlockStatement[?Yield, ?Await, ?Return] + VariableStatement[?Yield, ?Await] + EmptyStatement + ExpressionStatement[?Yield, ?Await] + IfStatement[?Yield, ?Await, ?Return] + BreakableStatement[?Yield, ?Await, ?Return] + ContinueStatement[?Yield, ?Await] + BreakStatement[?Yield, ?Await] + [+Return] ReturnStatement[?Yield, ?Await] + WithStatement[?Yield, ?Await, ?Return] + LabelledStatement[?Yield, ?Await, ?Return] + ThrowStatement[?Yield, ?Await] + TryStatement[?Yield, ?Await, ?Return] + DebuggerStatement + +Declaration[Yield, Await] : + HoistableDeclaration[?Yield, ?Await, ~Default] + ClassDeclaration[?Yield, ?Await, ~Default] + LexicalDeclaration[+In, ?Yield, ?Await] + +HoistableDeclaration[Yield, Await, Default] : + FunctionDeclaration[?Yield, ?Await, ?Default] + GeneratorDeclaration[?Yield, ?Await, ?Default] + AsyncFunctionDeclaration[?Yield, ?Await, ?Default] + AsyncGeneratorDeclaration[?Yield, ?Await, ?Default] + +BreakableStatement[Yield, Await, Return] : + IterationStatement[?Yield, ?Await, ?Return] + SwitchStatement[?Yield, ?Await, ?Return] + + +BlockStatement[Yield, Await, Return] : + Block[?Yield, ?Await, ?Return] + +Block[Yield, Await, Return] : + `{` StatementList[?Yield, ?Await, ?Return]? `}` + +StatementList[Yield, Await, Return] : + StatementListItem[?Yield, ?Await, ?Return] + StatementList[?Yield, ?Await, ?Return] StatementListItem[?Yield, ?Await, ?Return] + +StatementListItem[Yield, Await, Return] : + Statement[?Yield, ?Await, ?Return] + Declaration[?Yield, ?Await] + + +LexicalDeclaration[In, Yield, Await] : + LetOrConst BindingList[?In, ?Yield, ?Await] `;` + +LetOrConst : + `let` + `const` + +BindingList[In, Yield, Await] : + LexicalBinding[?In, ?Yield, ?Await] + BindingList[?In, ?Yield, ?Await] `,` LexicalBinding[?In, ?Yield, ?Await] + +LexicalBinding[In, Yield, Await] : + BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]? + BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await] + + +VariableStatement[Yield, Await] : + `var` VariableDeclarationList[+In, ?Yield, ?Await] `;` + +VariableDeclarationList[In, Yield, Await] : + VariableDeclaration[?In, ?Yield, ?Await] + VariableDeclarationList[?In, ?Yield, ?Await] `,` VariableDeclaration[?In, ?Yield, ?Await] + +VariableDeclaration[In, Yield, Await] : + BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]? + BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await] + + +BindingPattern[Yield, Await] : + ObjectBindingPattern[?Yield, ?Await] + ArrayBindingPattern[?Yield, ?Await] + +ObjectBindingPattern[Yield, Await] : + `{` `}` + `{` BindingRestProperty[?Yield, ?Await] `}` + `{` BindingPropertyList[?Yield, ?Await] `}` + `{` BindingPropertyList[?Yield, ?Await] `,` BindingRestProperty[?Yield, ?Await]? `}` + +ArrayBindingPattern[Yield, Await] : + `[` Elision? BindingRestElement[?Yield, ?Await]? `]` + `[` BindingElementList[?Yield, ?Await] `]` + `[` BindingElementList[?Yield, ?Await] `,` Elision? BindingRestElement[?Yield, ?Await]? `]` + +BindingRestProperty[Yield, Await] : + `...` BindingIdentifier[?Yield, ?Await] + +BindingPropertyList[Yield, Await] : + BindingProperty[?Yield, ?Await] + BindingPropertyList[?Yield, ?Await] `,` BindingProperty[?Yield, ?Await] + +BindingElementList[Yield, Await] : + BindingElisionElement[?Yield, ?Await] + BindingElementList[?Yield, ?Await] `,` BindingElisionElement[?Yield, ?Await] + +BindingElisionElement[Yield, Await] : + Elision? BindingElement[?Yield, ?Await] + +BindingProperty[Yield, Await] : + SingleNameBinding[?Yield, ?Await] + PropertyName[?Yield, ?Await] `:` BindingElement[?Yield, ?Await] + +BindingElement[Yield, Await] : + SingleNameBinding[?Yield, ?Await] + BindingPattern[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]? + +SingleNameBinding[Yield, Await] : + BindingIdentifier[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]? + +BindingRestElement[Yield, Await] : + `...` BindingIdentifier[?Yield, ?Await] + `...` BindingPattern[?Yield, ?Await] + + +EmptyStatement : + `;` + + +ExpressionStatement[Yield, Await] : + [lookahead <! {`{`, `function`, `async` [no |LineTerminator| here] `function`, `class`, `let` `[`}] Expression[+In, ?Yield, ?Await] `;` + + +IfStatement[Yield, Await, Return] : + `if` `(` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] `else` Statement[?Yield, ?Await, ?Return] + `if` `(` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + + +IterationStatement[Yield, Await, Return] : + `do` Statement[?Yield, ?Await, ?Return] `while` `(` Expression[+In, ?Yield, ?Await] `)` `;` + `while` `(` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + `for` `(` [lookahead != `let` `[`] Expression[~In, ?Yield, ?Await]? `;` Expression[+In, ?Yield, ?Await]? `;` Expression[+In, ?Yield, ?Await]? `)` Statement[?Yield, ?Await, ?Return] + `for` `(` `var` VariableDeclarationList[~In, ?Yield, ?Await] `;` Expression[+In, ?Yield, ?Await]? `;` Expression[+In, ?Yield, ?Await]? `)` Statement[?Yield, ?Await, ?Return] + `for` `(` LexicalDeclaration[~In, ?Yield, ?Await] Expression[+In, ?Yield, ?Await]? `;` Expression[+In, ?Yield, ?Await]? `)` Statement[?Yield, ?Await, ?Return] + `for` `(` [lookahead != `let` `[`] LeftHandSideExpression[?Yield, ?Await] `in` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + `for` `(` `var` ForBinding[?Yield, ?Await] `in` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + `for` `(` ForDeclaration[?Yield, ?Await] `in` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + `for` `(` [lookahead != `let` ] LeftHandSideExpression[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + `for` `(` `var` ForBinding[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + `for` `(` ForDeclaration[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + [+Await] `for` `await` `(` [lookahead != `let` ] LeftHandSideExpression[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + [+Await] `for` `await` `(` `var` ForBinding[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + [+Await] `for` `await` `(` ForDeclaration[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + +ForDeclaration[Yield, Await] : + LetOrConst ForBinding[?Yield, ?Await] + +ForBinding[Yield, Await] : + BindingIdentifier[?Yield, ?Await] + BindingPattern[?Yield, ?Await] + + +ContinueStatement[Yield, Await] : + `continue` `;` + `continue` [no LineTerminator here] LabelIdentifier[?Yield, ?Await] `;` + + +BreakStatement[Yield, Await] : + `break` `;` + `break` [no LineTerminator here] LabelIdentifier[?Yield, ?Await] `;` + + +ReturnStatement[Yield, Await] : + `return` `;` + `return` [no LineTerminator here] Expression[+In, ?Yield, ?Await] `;` + + +WithStatement[Yield, Await, Return] : + `with` `(` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + + +SwitchStatement[Yield, Await, Return] : + `switch` `(` Expression[+In, ?Yield, ?Await] `)` CaseBlock[?Yield, ?Await, ?Return] + +CaseBlock[Yield, Await, Return] : + `{` CaseClauses[?Yield, ?Await, ?Return]? `}` + `{` CaseClauses[?Yield, ?Await, ?Return]? DefaultClause[?Yield, ?Await, ?Return] CaseClauses[?Yield, ?Await, ?Return]? `}` + +CaseClauses[Yield, Await, Return] : + CaseClause[?Yield, ?Await, ?Return] + CaseClauses[?Yield, ?Await, ?Return] CaseClause[?Yield, ?Await, ?Return] + +CaseClause[Yield, Await, Return] : + `case` Expression[+In, ?Yield, ?Await] `:` StatementList[?Yield, ?Await, ?Return]? + +DefaultClause[Yield, Await, Return] : + `default` `:` StatementList[?Yield, ?Await, ?Return]? + + +LabelledStatement[Yield, Await, Return] : + LabelIdentifier[?Yield, ?Await] `:` LabelledItem[?Yield, ?Await, ?Return] + +LabelledItem[Yield, Await, Return] : + Statement[?Yield, ?Await, ?Return] + FunctionDeclaration[?Yield, ?Await, ~Default] + + +ThrowStatement[Yield, Await] : + `throw` [no LineTerminator here] Expression[+In, ?Yield, ?Await] `;` + + +TryStatement[Yield, Await, Return] : + `try` Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] + `try` Block[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] + `try` Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] + +Catch[Yield, Await, Return] : + `catch` `(` CatchParameter[?Yield, ?Await] `)` Block[?Yield, ?Await, ?Return] + `catch` Block[?Yield, ?Await, ?Return] + +Finally[Yield, Await, Return] : + `finally` Block[?Yield, ?Await, ?Return] + +CatchParameter[Yield, Await] : + BindingIdentifier[?Yield, ?Await] + BindingPattern[?Yield, ?Await] + + +DebuggerStatement : + `debugger` `;` + + +FunctionDeclaration[Yield, Await, Default] : + `function` BindingIdentifier[?Yield, ?Await] `(` FormalParameters[~Yield, ~Await] `)` `{` FunctionBody[~Yield, ~Await] `}` + [+Default] `function` `(` FormalParameters[~Yield, ~Await] `)` `{` FunctionBody[~Yield, ~Await] `}` + +FunctionExpression : + `function` BindingIdentifier[~Yield, ~Await]? `(` FormalParameters[~Yield, ~Await] `)` `{` FunctionBody[~Yield, ~Await] `}` + +UniqueFormalParameters[Yield, Await] : + FormalParameters[?Yield, ?Await] + +FormalParameters[Yield, Await] : + [empty] + FunctionRestParameter[?Yield, ?Await] + FormalParameterList[?Yield, ?Await] + FormalParameterList[?Yield, ?Await] `,` + FormalParameterList[?Yield, ?Await] `,` FunctionRestParameter[?Yield, ?Await] + +FormalParameterList[Yield, Await] : + FormalParameter[?Yield, ?Await] + FormalParameterList[?Yield, ?Await] `,` FormalParameter[?Yield, ?Await] + +FunctionRestParameter[Yield, Await] : + BindingRestElement[?Yield, ?Await] + +FormalParameter[Yield, Await] : + BindingElement[?Yield, ?Await] + +FunctionBody[Yield, Await] : + FunctionStatementList[?Yield, ?Await] + +FunctionStatementList[Yield, Await] : + StatementList[?Yield, ?Await, +Return]? + + +ArrowFunction[In, Yield, Await] : + ArrowParameters[?Yield, ?Await] [no LineTerminator here] `=>` ConciseBody[?In] + +ArrowParameters[Yield, Await] : + BindingIdentifier[?Yield, ?Await] + CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await] #parencover + +ConciseBody[In] : + [lookahead != `{` ] AssignmentExpression[?In, ~Yield, ~Await] + `{` FunctionBody[~Yield, ~Await] `}` + + +ArrowFormalParameters[Yield, Await] : + `(` UniqueFormalParameters[?Yield, ?Await] `)` + + +MethodDefinition[Yield, Await] : + PropertyName[?Yield, ?Await] `(` UniqueFormalParameters[~Yield, ~Await] `)` `{` FunctionBody[~Yield, ~Await] `}` + GeneratorMethod[?Yield, ?Await] + AsyncMethod[?Yield, ?Await] + AsyncGeneratorMethod[?Yield, ?Await] + `get` PropertyName[?Yield, ?Await] `(` `)` `{` FunctionBody[~Yield, ~Await] `}` + `set` PropertyName[?Yield, ?Await] `(` PropertySetParameterList `)` `{` FunctionBody[~Yield, ~Await] `}` + +PropertySetParameterList : + FormalParameter[~Yield, ~Await] + + +GeneratorMethod[Yield, Await] : + `*` PropertyName[?Yield, ?Await] `(` UniqueFormalParameters[+Yield, ~Await] `)` `{` GeneratorBody `}` + +GeneratorDeclaration[Yield, Await, Default] : + `function` `*` BindingIdentifier[?Yield, ?Await] `(` FormalParameters[+Yield, ~Await] `)` `{` GeneratorBody `}` + [+Default] `function` `*` `(` FormalParameters[+Yield, ~Await] `)` `{` GeneratorBody `}` + +GeneratorExpression : + `function` `*` BindingIdentifier[+Yield, ~Await]? `(` FormalParameters[+Yield, ~Await] `)` `{` GeneratorBody `}` + +GeneratorBody : + FunctionBody[+Yield, ~Await] + +YieldExpression[In, Await] : + `yield` + `yield` [no LineTerminator here] AssignmentExpression[?In, +Yield, ?Await] + `yield` [no LineTerminator here] `*` AssignmentExpression[?In, +Yield, ?Await] + + +AsyncGeneratorMethod[Yield, Await] : + `async` [no LineTerminator here] `*` PropertyName[?Yield, ?Await] `(` UniqueFormalParameters[+Yield, +Await] `)` `{` AsyncGeneratorBody `}` + +AsyncGeneratorDeclaration[Yield, Await, Default] : + `async` [no LineTerminator here] `function` `*` BindingIdentifier[?Yield, ?Await] `(` FormalParameters[+Yield, +Await] `)` `{` AsyncGeneratorBody `}` + [+Default] `async` [no LineTerminator here] `function` `*` `(` FormalParameters[+Yield, +Await] `)` `{` AsyncGeneratorBody `}` + +AsyncGeneratorExpression : + `async` [no LineTerminator here] `function` `*` BindingIdentifier[+Yield, +Await]? `(` FormalParameters[+Yield, +Await] `)` `{` AsyncGeneratorBody `}` + +AsyncGeneratorBody : + FunctionBody[+Yield, +Await] + + +ClassDeclaration[Yield, Await, Default] : + `class` BindingIdentifier[?Yield, ?Await] ClassTail[?Yield, ?Await] + [+Default] `class` ClassTail[?Yield, ?Await] + +ClassExpression[Yield, Await] : + `class` BindingIdentifier[?Yield, ?Await]? ClassTail[?Yield, ?Await] + +ClassTail[Yield, Await] : + ClassHeritage[?Yield, ?Await]? `{` ClassBody[?Yield, ?Await]? `}` + +ClassHeritage[Yield, Await] : + `extends` LeftHandSideExpression[?Yield, ?Await] + +ClassBody[Yield, Await] : + ClassElementList[?Yield, ?Await] + +ClassElementList[Yield, Await] : + ClassElement[?Yield, ?Await] + ClassElementList[?Yield, ?Await] ClassElement[?Yield, ?Await] + +ClassElement[Yield, Await] : + MethodDefinition[?Yield, ?Await] + `static` MethodDefinition[?Yield, ?Await] + `;` + + +AsyncFunctionDeclaration[Yield, Await, Default] : + `async` [no LineTerminator here] `function` BindingIdentifier[?Yield, ?Await] `(` FormalParameters[~Yield, +Await] `)` `{` AsyncFunctionBody `}` + [+Default] `async` [no LineTerminator here] `function` `(` FormalParameters[~Yield, +Await] `)` `{` AsyncFunctionBody `}` + +AsyncFunctionExpression : + `async` [no LineTerminator here] `function` `(` FormalParameters[~Yield, +Await] `)` `{` AsyncFunctionBody `}` + `async` [no LineTerminator here] `function` BindingIdentifier[~Yield, +Await] `(` FormalParameters[~Yield, +Await] `)` `{` AsyncFunctionBody `}` + +AsyncMethod[Yield, Await] : + `async` [no LineTerminator here] PropertyName[?Yield, ?Await] `(` UniqueFormalParameters[~Yield, +Await] `)` `{` AsyncFunctionBody `}` + +AsyncFunctionBody : + FunctionBody[~Yield, +Await] + +AwaitExpression[Yield] : + `await` UnaryExpression[?Yield, +Await] + + +AsyncArrowFunction[In, Yield, Await] : + `async` [no LineTerminator here] AsyncArrowBindingIdentifier[?Yield] [no LineTerminator here] `=>` AsyncConciseBody[?In] + CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] [no LineTerminator here] `=>` AsyncConciseBody[?In] #callcover + +AsyncConciseBody[In] : + [lookahead != `{`] AssignmentExpression[?In, ~Yield, +Await] + `{` AsyncFunctionBody `}` + +AsyncArrowBindingIdentifier[Yield] : + BindingIdentifier[?Yield, +Await] + +CoverCallExpressionAndAsyncArrowHead[Yield, Await] : + MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await] + + +AsyncArrowHead : + `async` [no LineTerminator here] ArrowFormalParameters[~Yield, +Await] + + +Script : + ScriptBody? + +ScriptBody : + StatementList[~Yield, ~Await, ~Return] + + +Module : + ModuleBody? + +ModuleBody : + ModuleItemList + +ModuleItemList : + ModuleItem + ModuleItemList ModuleItem + +ModuleItem : + ImportDeclaration + ExportDeclaration + StatementListItem[~Yield, ~Await, ~Return] + + +ImportDeclaration : + `import` ImportClause FromClause `;` + `import` ModuleSpecifier `;` + +ImportClause : + ImportedDefaultBinding + NameSpaceImport + NamedImports + ImportedDefaultBinding `,` NameSpaceImport + ImportedDefaultBinding `,` NamedImports + +ImportedDefaultBinding : + ImportedBinding + +NameSpaceImport : + `*` `as` ImportedBinding + +NamedImports : + `{` `}` + `{` ImportsList `}` + `{` ImportsList `,` `}` + +FromClause : + `from` ModuleSpecifier + +ImportsList : + ImportSpecifier + ImportsList `,` ImportSpecifier + +ImportSpecifier : + ImportedBinding + IdentifierName `as` ImportedBinding + +ModuleSpecifier : + StringLiteral + +ImportedBinding : + BindingIdentifier[~Yield, ~Await] + + +ExportDeclaration : + `export` `*` FromClause `;` + `export` ExportClause FromClause `;` + `export` ExportClause `;` + `export` VariableStatement[~Yield, ~Await] + `export` Declaration[~Yield, ~Await] + `export` `default` HoistableDeclaration[~Yield, ~Await, +Default] + `export` `default` ClassDeclaration[~Yield, ~Await, +Default] + `export` `default` [lookahead <! {`function`, `async` [no |LineTerminator| here] `function`, `class`}] AssignmentExpression[+In, ~Yield, ~Await] `;` + +ExportClause : + `{` `}` + `{` ExportsList `}` + `{` ExportsList `,` `}` + +ExportsList : + ExportSpecifier + ExportsList `,` ExportSpecifier + +ExportSpecifier : + IdentifierName + IdentifierName `as` IdentifierName + + +uri ::: + uriCharacters? + +uriCharacters ::: + uriCharacter uriCharacters? + +uriCharacter ::: + uriReserved + uriUnescaped + uriEscaped + +uriReserved ::: one of + `;` `/` `?` `:` `@` `&` `=` `+` `$` `,` + +uriUnescaped ::: + uriAlpha + DecimalDigit + uriMark + +uriEscaped ::: + `%` HexDigit HexDigit + +uriAlpha ::: one of + `a` `b` `c` `d` `e` `f` `g` `h` `i` `j` `k` `l` `m` `n` `o` `p` `q` `r` `s` `t` `u` `v` `w` `x` `y` `z` + `A` `B` `C` `D` `E` `F` `G` `H` `I` `J` `K` `L` `M` `N` `O` `P` `Q` `R` `S` `T` `U` `V` `W` `X` `Y` `Z` + +uriMark ::: one of + `-` `_` `.` `!` `~` `*` `'` `(` `)` + + +NativeFunction : + `function` PropertyName[~Yield, ~Await]? `(` FormalParameters[~Yield, ~Await] `)` `{` `[` `native` `code` `]` `}` + + +Pattern[U, N] :: + Disjunction[?U, ?N] + +Disjunction[U, N] :: + Alternative[?U, ?N] + Alternative[?U, ?N] `|` Disjunction[?U, ?N] + +Alternative[U, N] :: + [empty] + Alternative[?U, ?N] Term[?U, ?N] + +Term[U, N] :: + Assertion[?U, ?N] + Atom[?U, ?N] + Atom[?U, ?N] Quantifier + +Assertion[U, N] :: + `^` + `$` + `\` `b` + `\` `B` + `(` `?` `=` Disjunction[?U, ?N] `)` + `(` `?` `!` Disjunction[?U, ?N] `)` + `(` `?` `<=` Disjunction[?U, ?N] `)` + `(` `?` `<!` Disjunction[?U, ?N] `)` + +Quantifier :: + QuantifierPrefix + QuantifierPrefix `?` + +QuantifierPrefix :: + `*` + `+` + `?` + `{` DecimalDigits `}` + `{` DecimalDigits `,` `}` + `{` DecimalDigits `,` DecimalDigits `}` + +Atom[U, N] :: + PatternCharacter + `.` + `\` AtomEscape[?U, ?N] + CharacterClass[?U] + `(` GroupSpecifier[?U] Disjunction[?U, ?N] `)` + `(` `?` `:` Disjunction[?U, ?N] `)` + +SyntaxCharacter :: one of + `^` `$` `\` `.` `*` `+` `?` `(` `)` `[` `]` `{` `}` `|` + +PatternCharacter :: + SourceCharacter but not SyntaxCharacter + +AtomEscape[U, N] :: + DecimalEscape + CharacterClassEscape[?U] + CharacterEscape[?U] + [+N] `k` GroupName[?U] + +CharacterEscape[U] :: + ControlEscape + `c` ControlLetter + `0` [lookahead <! DecimalDigit] + HexEscapeSequence + RegExpUnicodeEscapeSequence[?U] + IdentityEscape[?U] + +ControlEscape :: one of + `f` `n` `r` `t` `v` + +ControlLetter :: one of + `a` `b` `c` `d` `e` `f` `g` `h` `i` `j` `k` `l` `m` `n` `o` `p` `q` `r` `s` `t` `u` `v` `w` `x` `y` `z` + `A` `B` `C` `D` `E` `F` `G` `H` `I` `J` `K` `L` `M` `N` `O` `P` `Q` `R` `S` `T` `U` `V` `W` `X` `Y` `Z` + +GroupSpecifier[U] :: + [empty] + `?` GroupName[?U] + +GroupName[U] :: + `<` RegExpIdentifierName[?U] `>` + +RegExpIdentifierName[U] :: + RegExpIdentifierStart[?U] + RegExpIdentifierName[?U] RegExpIdentifierPart[?U] + +RegExpIdentifierStart[U] :: + UnicodeIDStart + `$` + `_` + `\` RegExpUnicodeEscapeSequence[?U] + +RegExpIdentifierPart[U] :: + UnicodeIDContinue + `$` + `\` RegExpUnicodeEscapeSequence[?U] + <ZWNJ> + <ZWJ> + +RegExpUnicodeEscapeSequence[U] :: + [+U] `u` LeadSurrogate `\u` TrailSurrogate + [+U] `u` LeadSurrogate + [+U] `u` TrailSurrogate + [+U] `u` NonSurrogate + [~U] `u` Hex4Digits + [+U] `u{` CodePoint `}` + + +LeadSurrogate :: + Hex4Digits [> but only if the SV of |Hex4Digits| is in the inclusive range 0xD800 to 0xDBFF] + +TrailSurrogate :: + Hex4Digits [> but only if the SV of |Hex4Digits| is in the inclusive range 0xDC00 to 0xDFFF] + +NonSurrogate :: + Hex4Digits [> but only if the SV of |Hex4Digits| is not in the inclusive range 0xD800 to 0xDFFF] + +IdentityEscape[U] :: + [+U] SyntaxCharacter + [+U] `/` + [~U] SourceCharacter but not UnicodeIDContinue + +DecimalEscape :: + NonZeroDigit DecimalDigits? [lookahead <! DecimalDigit] + +CharacterClassEscape[U] :: + `d` + `D` + `s` + `S` + `w` + `W` + [+U] `p{` UnicodePropertyValueExpression `}` + [+U] `P{` UnicodePropertyValueExpression `}` + +UnicodePropertyValueExpression :: + UnicodePropertyName `=` UnicodePropertyValue + LoneUnicodePropertyNameOrValue + +UnicodePropertyName :: + UnicodePropertyNameCharacters + +UnicodePropertyNameCharacters :: + UnicodePropertyNameCharacter UnicodePropertyNameCharacters? + +UnicodePropertyValue :: + UnicodePropertyValueCharacters + +LoneUnicodePropertyNameOrValue :: + UnicodePropertyValueCharacters + +UnicodePropertyValueCharacters :: + UnicodePropertyValueCharacter UnicodePropertyValueCharacters? + +UnicodePropertyValueCharacter :: + UnicodePropertyNameCharacter + `0` + `1` + `2` + `3` + `4` + `5` + `6` + `7` + `8` + `9` + +UnicodePropertyNameCharacter :: + ControlLetter + `_` + +CharacterClass[U] :: + `[` [lookahead != `^`] ClassRanges[?U] `]` + `[` `^` ClassRanges[?U] `]` + +ClassRanges[U] :: + [empty] + NonemptyClassRanges[?U] + +NonemptyClassRanges[U] :: + ClassAtom[?U] + ClassAtom[?U] NonemptyClassRangesNoDash[?U] + ClassAtom[?U] `-` ClassAtom[?U] ClassRanges[?U] + +NonemptyClassRangesNoDash[U] :: + ClassAtom[?U] + ClassAtomNoDash[?U] NonemptyClassRangesNoDash[?U] + ClassAtomNoDash[?U] `-` ClassAtom[?U] ClassRanges[?U] + +ClassAtom[U] :: + `-` + ClassAtomNoDash[?U] + +ClassAtomNoDash[U] :: + SourceCharacter but not one of `\` or `]` or `-` + `\` ClassEscape[?U] + +ClassEscape[U] :: + `b` + [+U] `-` + CharacterClassEscape[?U] + CharacterEscape[?U] + + +NumericLiteral :: + DecimalLiteral + BinaryIntegerLiteral + OctalIntegerLiteral + HexIntegerLiteral + LegacyOctalIntegerLiteral + +LegacyOctalIntegerLiteral :: + `0` OctalDigit + LegacyOctalIntegerLiteral OctalDigit + +DecimalIntegerLiteral :: + `0` + NonZeroDigit DecimalDigits? + NonOctalDecimalIntegerLiteral + +NonOctalDecimalIntegerLiteral :: + `0` NonOctalDigit + LegacyOctalLikeDecimalIntegerLiteral NonOctalDigit + NonOctalDecimalIntegerLiteral DecimalDigit + +LegacyOctalLikeDecimalIntegerLiteral :: + `0` OctalDigit + LegacyOctalLikeDecimalIntegerLiteral OctalDigit + +NonOctalDigit :: one of + `8` `9` + + +EscapeSequence :: + CharacterEscapeSequence + LegacyOctalEscapeSequence + HexEscapeSequence + UnicodeEscapeSequence + +LegacyOctalEscapeSequence :: + OctalDigit [lookahead <! OctalDigit] + ZeroToThree OctalDigit [lookahead <! OctalDigit] + FourToSeven OctalDigit + ZeroToThree OctalDigit OctalDigit + +ZeroToThree :: one of + `0` `1` `2` `3` + +FourToSeven :: one of + `4` `5` `6` `7` + + +Comment :: + MultiLineComment + SingleLineComment + SingleLineHTMLOpenComment + SingleLineHTMLCloseComment + SingleLineDelimitedComment + +MultiLineComment :: + `/*` FirstCommentLine? LineTerminator MultiLineCommentChars? `*/` HTMLCloseComment? + +FirstCommentLine :: + SingleLineDelimitedCommentChars + +SingleLineHTMLOpenComment :: + `<!--` SingleLineCommentChars? + +SingleLineHTMLCloseComment :: + LineTerminatorSequence HTMLCloseComment + +SingleLineDelimitedComment :: + `/*` SingleLineDelimitedCommentChars? `*/` + +HTMLCloseComment :: + WhiteSpaceSequence? SingleLineDelimitedCommentSequence? `-->` SingleLineCommentChars? + +SingleLineDelimitedCommentChars :: + SingleLineNotAsteriskChar SingleLineDelimitedCommentChars? + `*` SingleLinePostAsteriskCommentChars? + +SingleLineNotAsteriskChar :: + SourceCharacter but not one of `*` or LineTerminator + +SingleLinePostAsteriskCommentChars :: + SingleLineNotForwardSlashOrAsteriskChar SingleLineDelimitedCommentChars? + `*` SingleLinePostAsteriskCommentChars? + +SingleLineNotForwardSlashOrAsteriskChar :: + SourceCharacter but not one of `/` or `*` or LineTerminator + +WhiteSpaceSequence :: + WhiteSpace WhiteSpaceSequence? + +SingleLineDelimitedCommentSequence :: + SingleLineDelimitedComment WhiteSpaceSequence? SingleLineDelimitedCommentSequence? + + +Term[U, N] :: + [+U] Assertion[+U, ?N] + [+U] Atom[+U, ?N] + [+U] Atom[+U, ?N] Quantifier + [~U] QuantifiableAssertion[?N] Quantifier + [~U] Assertion[~U, ?N] + [~U] ExtendedAtom[?N] Quantifier + [~U] ExtendedAtom[?N] + +Assertion[U, N] :: + `^` + `$` + `\` `b` + `\` `B` + [+U] `(` `?` `=` Disjunction[+U, ?N] `)` + [+U] `(` `?` `!` Disjunction[+U, ?N] `)` + [~U] QuantifiableAssertion[?N] + `(` `?` `<=` Disjunction[?U, ?N] `)` + `(` `?` `<!` Disjunction[?U, ?N] `)` + +QuantifiableAssertion[N] :: + `(` `?` `=` Disjunction[~U, ?N] `)` + `(` `?` `!` Disjunction[~U, ?N] `)` + +ExtendedAtom[N] :: + `.` + `\` AtomEscape[~U, ?N] + `\` [lookahead == `c`] + CharacterClass[~U] + `(` Disjunction[~U, ?N] `)` + `(` `?` `:` Disjunction[~U, ?N] `)` + InvalidBracedQuantifier + ExtendedPatternCharacter + +InvalidBracedQuantifier :: + `{` DecimalDigits `}` + `{` DecimalDigits `,` `}` + `{` DecimalDigits `,` DecimalDigits `}` + +ExtendedPatternCharacter :: + SourceCharacter but not one of `^` `$` `\` `.` `*` `+` `?` `(` `)` `[` `|` + +AtomEscape[U, N] :: + [+U] DecimalEscape + [~U] DecimalEscape [> but only if the CapturingGroupNumber of |DecimalEscape| is <= _NcapturingParens_] + CharacterClassEscape[?U] + CharacterEscape[~U, ?N] + [+N] `k` GroupName[?U] + +CharacterEscape[U, N] :: + ControlEscape + `c` ControlLetter + `0` [lookahead <! DecimalDigit] + HexEscapeSequence + RegExpUnicodeEscapeSequence[?U] + [~U] LegacyOctalEscapeSequence + IdentityEscape[?U, ?N] + +IdentityEscape[U, N] :: + [+U] SyntaxCharacter + [+U] `/` + [~U] SourceCharacterIdentityEscape[?N] + +SourceCharacterIdentityEscape[N] :: + [~N] SourceCharacter but not `c` + [+N] SourceCharacter but not one of `c` or `k` + +ClassAtomNoDash[U, N] :: + SourceCharacter but not one of `\` or `]` or `-` + `\` ClassEscape[?U, ?N] + `\` [lookahead == `c`] + +ClassEscape[U, N] :: + `b` + [+U] `-` + [~U] `c` ClassControlLetter + CharacterClassEscape[?U] + CharacterEscape[?U, ?N] + +ClassControlLetter :: + DecimalDigit + `_` + + +IfStatement[Yield, Await, Return] : + `if` `(` Expression[+In, ?Yield, ?Await] `)` FunctionDeclaration[?Yield, ?Await, ~Default] `else` Statement[?Yield, ?Await, ?Return] + `if` `(` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] `else` FunctionDeclaration[?Yield, ?Await, ~Default] + `if` `(` Expression[+In, ?Yield, ?Await] `)` FunctionDeclaration[?Yield, ?Await, ~Default] `else` FunctionDeclaration[?Yield, ?Await, ~Default] + `if` `(` Expression[+In, ?Yield, ?Await] `)` FunctionDeclaration[?Yield, ?Await, ~Default] + + +IterationStatement[Yield, Await, Return] : + `for` `(` `var` BindingIdentifier[?Yield, ?Await] Initializer[~In, ?Yield, ?Await] `in` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + diff --git a/third_party/rust/jsparagus/js_parser/esgrammar.pgen b/third_party/rust/jsparagus/js_parser/esgrammar.pgen new file mode 100644 index 0000000000..7a0b4cb7b9 --- /dev/null +++ b/third_party/rust/jsparagus/js_parser/esgrammar.pgen @@ -0,0 +1,290 @@ +# Grammar for ECMArkup grammar descriptions + +var token CHR; # <NL> +var token EQ; # :: +var token MATCH_REF; # $0 +var token NL; # (actual newline character) +var token NT; # IdentifierName +var token NTALT; # |LineTerminator| +var token NTCALL; # Expression (when followed by `[` or `<`) +var token PRODID; # #comment +var token PROSE; # > any text following a greater than sign +var token T; # `var` +var token WPROSE; # [> any text after greater than sign, wrapped in brackets] +var token RUSTCOMMENT;# //comment + +token But = "but"; +token Empty = "empty"; +token Here = "here"; +token Lookahead = "lookahead"; +token No = "no"; +token Not = "not"; +token Of = "of"; +token One = "one"; +token Or = "or"; +token Through = "through"; +token Returns = "returns"; +token Some = "Some"; +token None = "None"; +token Arrow = "=>"; +token Comma = ","; +token OpenBracket = "["; +token CloseBracket = "]"; +token QuestionMark = "?"; +token Tilde = "~"; +token PlusSign = "+"; +token Equal = "="; +token Equals = "=="; +token IsNotEqualTo = "!="; +token IsNotIn = "<!"; +token OpenBrace = "{"; +token CloseBrace = "}"; +token OpenParen = "("; +token CloseParen = ")"; +token AtSign = "@"; +token OpenAngle = "<"; +token CloseAngle = ">"; +token Impl = "impl"; +token For = "for"; +token Let = "let"; +token SemiColon = ";"; +token Lifetime = "'"; + +// Entry point for grammar_extension! macro's content. +goal nt rust_edsl { + rust_impl rust_nt_def_list => rust_edsl($0, $1); +} + +nt rust_impl { + "impl" nt_type "for" nt_type "{" "}" ";" => rust_impl($1, $3); + "impl" "<" nt_type_params ">" nt_type "for" nt_type "{" "}" ";" => rust_param_impl($4, $6, $2); +} + +nt rust_nt_def_list { + rust_nt_def_or_blank_line; + rust_nt_def_list rust_nt_def_or_blank_line => concat($0, $1); +} + +nt rust_nt_def_or_blank_line { + NL => blank_line(); + RUSTCOMMENT => blank_line(); + rust_nt_def => nt_def_to_list($0); +} + +// grammar extension syntax for adding/removing/extending the productions. +nt rust_nt_def { + "let" nt_lhs "=" "{" rust_rhs_line "}" ";" => rust_nt_def($1, $4); +} + +nt rust_rhs_line { + rust_symbols => rust_rhs_line($0); +} + +nt rust_symbols { + rust_symbol; + rust_symbols rust_symbol => concat($0, $1); +} + +nt rust_symbol { + "{" rust_expr "}" => single($1); + symbol => single($0); + NL => empty(); +} + +nt rust_expr { + expr => rust_expr($0); +} + +// Entry point for esgrammar files. +goal nt grammar { + nt_def_list; +} + +nt nt_def_list { + nt_def_or_blank_line; + nt_def_list nt_def_or_blank_line => concat($0, $1); +} + +nt nt_def_or_blank_line { + NL => blank_line(); + nt_def => nt_def_to_list($0); +} + +nt nt_def { + nt_type_line? nt_lhs EQ NL rhs_lines NL => nt_def($0, $1, $2, $4); + nt_type_line? nt_lhs EQ "one" "of" NL t_list_lines NL => nt_def_one_of($0, $1, $2, $6); +} + +nt nt_lhs { + NT => nt_lhs_no_params($0); + NTCALL "[" params "]" => nt_lhs_with_params($0, $2); +} + +nt params { + param => single($0); + params "," param => append($0, $2); +} + +nt param { + NT; +} + +nt nt_type_line { + "@" "returns" nt_type NL => $2; +} + +// Define a type as understood by Rust type-system. +nt nt_type { + NT => simple_type($0); + NTCALL "<" nt_type_params ">" => parameterized_type($0, $2); +} + +nt nt_type_params { + nt_type_param => single($0); + nt_type_params "," nt_type_param => append($0, $2); +} + +nt nt_type_param { + nt_type; + "'" NT => lifetime_type($0); +} + +nt t_list_lines { + t_list_line; + t_list_lines t_list_line => concat($0, $1); +} + +nt t_list_line { + terminal_seq NL => t_list_line($0); +} + +nt terminal_seq { + terminal => single($0); + terminal_seq terminal => append($0, $1); +} + +nt terminal { + T => terminal($0); + CHR => chr($0); +} + +nt rhs_lines { + rhs_line => single($0); + rhs_lines rhs_line => append($0, $1); +} + +nt rhs_line { + ifdef? rhs reducer? PRODID? NL => rhs_line($0, $1, $2, $3); + PROSE NL => rhs_line_prose($0); +} + +nt rhs { + symbols; + "[" "empty" "]" => empty_rhs(); +} + +nt reducer { + NL? "=>" expr => $2; +} + +nt expr { + MATCH_REF => expr_match_ref($0); + NT "(" expr_args? ")" expr_try? => expr_call($0, $2, $4); + "Some" "(" expr ")" => expr_some($2); + "None" => expr_none(); +} + +nt expr_try { + "?"; +} + +nt expr_args { + expr => single($0); + expr_args "," expr => append($0, $2); +} + +nt ifdef { + "[" definite_sigil NT "]" => ifdef($1, $2); +} + +nt symbols { + symbol => single($0); + symbols symbol => append($0, $1); +} + +nt symbol { + terminal; + nonterminal; + nonterminal "?" => optional($0); + nonterminal "but" "not" exclusion => but_not($0, $3); + nonterminal "but" "not" "one" "of" exclusion_list => but_not_one_of($0, $5); + "[" "lookahead" lookahead_assertion "]" => $2; + no_line_terminator_here; + WPROSE => $0; +} + +nt no_line_terminator_here { + "[" "no" line_terminator "here" "]" => no_line_terminator_here($2); +} + +nt nonterminal { + NT => nonterminal($0); + NTCALL "[" args "]" => nonterminal_apply($0, $2); +} + +nt args { + arg => single($0); + args "," arg => append($0, $2); +} + +nt arg { + sigil NT => arg_expr($0, $1); +} + +nt sigil { + definite_sigil; + "?"; +} + +nt definite_sigil { + "~" => sigil_false(); + "+" => sigil_true(); +} + +nt exclusion_list { + exclusion => single($0); + exclusion_list "or" exclusion => append($0, $2); +} + +nt exclusion { + terminal => exclusion_terminal($0); + nonterminal => exclusion_nonterminal($0); + CHR "through" CHR => exclusion_chr_range($0, $2); +} + +nt lookahead_assertion { + "==" terminal => la_eq($1); + "!=" terminal => la_ne($1); + "<!" NT => la_not_in_nonterminal($1); + "<!" "{" lookahead_exclusions "}" => la_not_in_set($2); +} + +nt lookahead_exclusions { + lookahead_exclusion => single($0); + lookahead_exclusions "," lookahead_exclusion => append($0, $2); +} + +nt lookahead_exclusion { + lookahead_exclusion_element => single($0); + lookahead_exclusion lookahead_exclusion_element => append($0, $1); +} + +nt lookahead_exclusion_element { + terminal; + no_line_terminator_here; +} + +nt line_terminator { + NT; + NTALT; +} diff --git a/third_party/rust/jsparagus/js_parser/extract_es_grammar.py b/third_party/rust/jsparagus/js_parser/extract_es_grammar.py new file mode 100755 index 0000000000..b1fc35473f --- /dev/null +++ b/third_party/rust/jsparagus/js_parser/extract_es_grammar.py @@ -0,0 +1,567 @@ +"""extract_es_grammar.py - Extract the grammar from the ECMAScript spec + +To run this script, you first need to get the source of the version of +the ECMAScript spec you're interested in. + + cd ../.. + mkdir tc39 + cd tc39 + git clone git@github.com:tc39/ecma262.git + +Then: + + make js_parser/es.esgrammar + +You can also use this script on a random HTTPS URL, like: + + URL=https://raw.githubusercontent.com/tc39/proposal-class-fields/master/spec.html + python extract_esgrammar.py $URL + +""" + +import argparse +import urllib +import html5lib # type: ignore +import re +from textwrap import dedent + + +HTML = "{http://www.w3.org/1999/xhtml}" +INS_TAG = HTML + "ins" +DEL_TAG = HTML + "del" + +INS = '+' +DEL = '-' +KEEP = ' ' + + +def pre_with_code_filter_factory(e): + """Checks if the <pre> is used in the following pattern: + + ``` + <pre><code> + </code></pre> + ``` + + If so, return a filter that formats the content, removing extra spaces. + line-wrap, and backquote added by <code>. + + """ + if e.text and e.text.strip() != '': + return False + + if len(e) != 1: + return False + + if e[0].tag != '{http://www.w3.org/1999/xhtml}code': + return False + + if e[0].tail and e[0].tail.strip() != '': + return False + + def children_filter(texts): + while len(texts) > 0 and texts[0].strip() == '': + texts.pop(0) + if len(texts) > 0 and texts[0].strip() == '`': + texts.pop(0) + while len(texts) > 0 and texts[0].strip() == '': + texts.pop(0) + + while len(texts) > 0 and texts[-1].strip() == '': + texts.pop() + if len(texts) > 0 and texts[-1].strip() == '`': + texts.pop() + while len(texts) > 0 and texts[-1].strip() == '': + texts.pop() + + is_first = True + for text in texts: + for line in text.split('\n'): + line = line.strip() + if line == '': + continue + + if not is_first: + yield '\n' + is_first = False + + yield line + + return children_filter + + +# Rules for extracting text, used by extracting Early Errors. +EXTRA_RULES_FOR_EE = { + 'b': {}, + 'br': {}, + 'code': { + 'prefix': '`', + 'postfix': '`', + }, + 'emu-alg': {}, + 'emu-grammar': {}, + 'emu-note': { + 'prefix': ['NOTE', '\n'], + 'strip': True, + }, + 'emu-xref': { + 'prefix': lambda e: e.attrib.get('href'), + }, + 'ins': { + 'ignore_highlighted': True, + }, + 'p': { + 'strip': True, + }, + 'pre': { + 'prefix': ['\n', '\n', '```', '\n'], + 'postfix': ['\n', '```', '\n', '\n'], + 'strip': True, + 'children_filter_factroy': pre_with_code_filter_factory, + }, + 'sub': { + 'prefix': '_', + }, + 'sup': { + 'prefix': '^', + }, +} + + +def apply_prefix_postfix_rule(e, rule, name): + """If rule is provided, apply prefix/postfix rule to the element `e`. + """ + if not rule: + return + + fix = rule.get(name) + if callable(fix): + yield fix(e) + elif isinstance(fix, list): + for item in fix: + yield item + elif fix: + yield fix + + +def apply_strip_rule(text, rule): + """If rule is provided, apply strip rule to the text. + """ + if not text: + return + + if not rule: + yield text + return + + strip = rule.get('strip') + if strip: + yield text.strip() + else: + yield text + + +def fragment_child_chunks(e, extra_rules={}): + """Partly interpret the content of `e`, yielding `text`, + applying extra_rules. + + Concatenating the yielded `text` values gives the full text of `e`. + """ + rule = extra_rules[e.tag.replace(HTML, '')] + + children_filter = None + factroy = rule.get('children_filter_factroy') + if factroy: + children_filter = factroy(e) + + yield from apply_prefix_postfix_rule(e, rule, 'prefix') + yield from apply_strip_rule(e.text, rule) + + for child in e: + if child.tag.replace(HTML, '') not in extra_rules: + raise ValueError("unrecognized element: " + child.tag) + + texts = [] + for text in fragment_child_chunks(child, extra_rules): + if children_filter: + texts.append(text) + else: + yield text + + if children_filter: + for text in children_filter(texts): + yield text + + yield from apply_strip_rule(e.tail, rule) + yield from apply_prefix_postfix_rule(e, rule, 'postfix') + + +def is_highlighted_ins(e): + """Returns True if e matches the following pattern: + + <ins>highlighted</ins> text: + + See `fragment_chunks` comment for the details + """ + if len(e) != 0: + return False + + if not e.text: + return False + + if e.text != 'highlighted': + return False + + if not e.tail: + return False + + if not e.tail.startswith(' text:'): + return False + + return True + + +def is_negligible_ins(e, extra_rules): + """Returns True if the 'ignore_highlighted' rule is defined for <ins>, + and it matches to the negligible pattern. + + See `fragment_chunks` comment for the details + """ + + rule = extra_rules.get(e.tag.replace(HTML, '')) + if not rule: + return False + + if rule.get('ignore_highlighted'): + if is_highlighted_ins(e): + return True + + return False + + +def fragment_chunks(e, extra_rules={}): + """Partly interpret the content of `e`, yielding pairs (ty, text). + + If `extra_rules` isn't provided, the content of `e` must be text with 0 + or more <ins>/<del> elements. + + The goal is to turn the tree `e` into a simple series of tagged strings. + + Yields pairs (ty, text) where ty in (INS, DEL, KEEP). Concatenating the + yielded `text` values gives the full text of `e`. + + `extra_rules` is a dictionary that defines extra elements that is allowed + as the content of `e`. + Each item defines a rule for the tag, with the following: + * prefix + Put a prefix before the text + Possible values: + * string + * list of string + * function + receives `Element` and returns a prefix string + * postfix + Put a postfix after the text + value uses the same format as prefix + * strip + True to strip whitespaces before/after element's text + * children_filter_factroy + A function that receives `Element`, and returns a filter function or None + The filter function receives a list of texts for child nodes, and + returns a list of filtered text + * ignore_highlighted + Effective only with <ins> + Do not treat <ins> as an insertion if it matches the following pattern: + + <ins>highlighted</ins> text: + + This pattern is used in Annex B description. + """ + + rule = extra_rules.get(e.tag.replace(HTML, '')) + + for text in apply_prefix_postfix_rule(e, rule, 'prefix'): + yield KEEP, text + for text in apply_strip_rule(e.text, rule): + yield KEEP, text + + for child in e: + if child.tag == INS_TAG and not is_negligible_ins(child, extra_rules): + ty = INS + elif child.tag == DEL_TAG: + ty = DEL + else: + if child.tag.replace(HTML, '') not in extra_rules: + raise ValueError("unrecognized element: " + child.tag) + + for text in fragment_child_chunks(child, extra_rules): + yield KEEP, text + continue + + if child.text: + yield ty, child.text + if len(child) != 0: + for grandchild in child: + if grandchild.tag.replace(HTML, '') not in extra_rules: + raise ValueError("unsupported nested element {} in {}" + .format(grandchild.tag, child.tag)) + + for text in fragment_child_chunks(grandchild, extra_rules): + yield ty, text + if child.tail: + yield KEEP, child.tail + + for text in apply_strip_rule(e.tail, rule): + yield KEEP, text + for text in apply_prefix_postfix_rule(e, rule, 'postfix'): + yield KEEP, text + + +def fragment_parts(e, **kwargs): + """Like fragment_chunks, but with two fixups. + + 1. Break up pairs that include both a newline and any other text. + + 2. Move newlines inside of a preceding INS or DEL element that spans its + whole line. + """ + line_has_ins = False + line_has_del = False + for chunk_ty, text in fragment_chunks(e, **kwargs): + for piece in re.split(r'(\n)', text): + ty = chunk_ty + if piece != '': + if piece == '\n': + # Possibly move newline inside preceding INS or DEL. + if line_has_ins and not line_has_del: + ty = INS + elif line_has_del and not line_has_ins: + ty = DEL + else: + ty = KEEP + line_has_del = False + line_has_ins = False + elif piece.strip() != '': + if ty in (INS, KEEP): + line_has_ins = True + if ty in (DEL, KEEP): + line_has_del = True + yield ty, piece + + +def generate_fragment_patch(e, **kwargs): + line_before = '' + line_after = '' + + def end_line(ty): + nonlocal line_before, line_after + if line_before.rstrip() == line_after.rstrip(): + yield " ", line_after + else: + if line_before.strip() != '' or ty != INS: + yield "-", line_before + if line_after.strip() != '' or ty != DEL: + yield "+", line_after + line_before = '' + line_after = '' + + for ty, text in fragment_parts(e, **kwargs): + if text == '\n': + yield from end_line(ty) + else: + if ty in (KEEP, DEL): + line_before += text + if ty in (KEEP, INS): + line_after += text + if line_before or line_after: + yield from end_line(KEEP) + + +def dedent_pairs(pairs): + """Dedent the `pairs`'s `text` part + """ + pairs = list(pairs) + + # Using textwrap.dedent on this requires a few lines of hackery. + types = [ty for ty, _line in pairs] + dedented_lines = dedent(''.join(line + '\n' for ty, line in pairs)).splitlines() + assert len(dedented_lines) == len(pairs) + + return zip(types, dedented_lines) + + +def print_pairs(pairs): + last_line_was_empty = False + + for ty, line in pairs: + if ty == KEEP and line == '': + if last_line_was_empty: + continue + last_line_was_empty = True + else: + last_line_was_empty = False + + print(ty + line) + + +def print_fragment_patch(e): + print_pairs(dedent_pairs(generate_fragment_patch(e))) + + +def is_annex_early_errors(e): + """Returns True if the <emu-annex> element contains Early Errors. + """ + h1 = e.find('{http://www.w3.org/1999/xhtml}h1') + if 'Early Errors' in h1.text: + return True + + p = e.find('{http://www.w3.org/1999/xhtml}p') + if p: + if 'Early Error' in html5lib.serializer.serialize(p): + return True + + return False + + +def get_parent_map(document): + """Returns a map from a element to parent element. + This is necessary because `xml.etree.ElementTree.Element` doesn't have + a reference to parent element. + """ + parent_map = dict() + for parent in document.iter(): + for child in parent: + parent_map[child] = parent + return parent_map + + +def get_titles(parent_map, e): + """Returns a list of section titles for a section. + """ + titles = [] + while e.tag != '{http://www.w3.org/1999/xhtml}body': + h1 = e.find('{http://www.w3.org/1999/xhtml}h1') + titles.insert(0, h1.text) + e = parent_map[e] + + return titles + + +def generate_ul_fragment_patch(e, depth): + """Similar to generate_fragment_patch, but for <ul> + """ + first_line_prefix = '{}* '.format(' ' * depth) + other_line_prefix = '{} '.format(' ' * depth) + + for item in e: + if item.tag != '{http://www.w3.org/1999/xhtml}li': + raise ValueError("unrecognized element: " + item.tag) + + pairs = generate_fragment_patch(item, + extra_rules=EXTRA_RULES_FOR_EE) + + is_first_line = True + + for ty, line in dedent_pairs(pairs): + if is_first_line and line.strip() == '': + continue + + if is_first_line: + is_first_line = False + yield ty, '{}{}'.format(first_line_prefix, line.strip()) + else: + yield ty, '{}{}'.format(other_line_prefix, line.strip()) + + +def generate_early_errors_fragment_patch(parent_map, e): + for t in get_titles(parent_map, e): + yield KEEP, '# {}'.format(t) + yield KEEP, '# #{}'.format(e.attrib.get('id')) + yield KEEP, '' + + for child in e: + if child.tag == '{http://www.w3.org/1999/xhtml}h1': + continue + + if child.tag == '{http://www.w3.org/1999/xhtml}emu-grammar': + pairs = generate_fragment_patch(child) + yield from dedent_pairs(pairs) + yield KEEP, '' + elif child.tag == '{http://www.w3.org/1999/xhtml}ul': + yield from generate_ul_fragment_patch(child, 0) + elif child.tag == '{http://www.w3.org/1999/xhtml}emu-note': + pairs = generate_fragment_patch(child, + extra_rules=EXTRA_RULES_FOR_EE) + yield from dedent_pairs(pairs) + yield KEEP, '' + elif child.tag == '{http://www.w3.org/1999/xhtml}p': + pairs = generate_fragment_patch(child, + extra_rules=EXTRA_RULES_FOR_EE) + yield from dedent_pairs(pairs) + yield KEEP, '' + elif (child.tag == '{http://www.w3.org/1999/xhtml}emu-alg' + and e.attrib.get('id') == 'sec-__proto__-property-names-in-object-initializers'): + # "__proto__ Property Names in Object Initializers" section + # contains changes both for early errors and algorithm. + # Ignore algorithm part. + pass + else: + raise ValueError('unsupported element in early errors section: {}' + .format(child.tag)) + + +def print_early_errors(parent_map, e): + pairs = generate_early_errors_fragment_patch(parent_map, e) + print_pairs(dedent_pairs(pairs)) + + +def extract(filename, unfiltered, target): + if filename.startswith("https:"): + file_obj = urllib.request.urlopen(filename) + else: + file_obj = open(filename, "rb") + + with file_obj: + document = html5lib.parse(file_obj) + + if target == 'grammar': + for e in document.iter("{http://www.w3.org/1999/xhtml}emu-grammar"): + if unfiltered or e.attrib.get("type") == "definition": + print_fragment_patch(e) + elif target == 'ee': + parent_map = get_parent_map(document) + for e in document.iter("{http://www.w3.org/1999/xhtml}emu-clause"): + if e.attrib.get("id").endswith("-early-errors"): + print_early_errors(parent_map, e) + elif target == 'ee-annex': + parent_map = get_parent_map(document) + for e in document.iter("{http://www.w3.org/1999/xhtml}emu-annex"): + if is_annex_early_errors(e): + print_early_errors(parent_map, e) + else: + raise ValueError('Unknown target: {}'.format(target)) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description="Extract esgrammar from ECMAScript specifications.") + parser.add_argument( + 'url', + nargs=1, + help="the https: url or local filename of an HTML file containing <emu-grammar> tags") + parser.add_argument( + '--unfiltered', + action='store_true', + help="Include even <emu-grammar> elements that don't have `type=definition`") + parser.add_argument( + '--target', + default='grammar', + choices=['grammar', 'ee', 'ee-annex'], + help="What to extract (\ + grammar = esgrammar, \ + ee = early errors, \ + ee-annex = early errors in Annex\ + )") + + args = parser.parse_args() + extract(args.url[0], args.unfiltered, args.target) diff --git a/third_party/rust/jsparagus/js_parser/generate_js_parser_tables.py b/third_party/rust/jsparagus/js_parser/generate_js_parser_tables.py new file mode 100755 index 0000000000..f85f7aca86 --- /dev/null +++ b/third_party/rust/jsparagus/js_parser/generate_js_parser_tables.py @@ -0,0 +1,140 @@ +"""generate_js_parser_tables.py - Generate tables from the ES grammar.""" + +import argparse +import os +import jsparagus.gen +import jsparagus.grammar +from . import load_es_grammar + + +def hack_grammar(g): + # We throw away most of the boolean parameters in the grammar, as the + # current parser generator's approach of fully expanding them is a huge + # pain. + + PARAM_WHITELIST = ['In', 'Default'] + + def filter_params(params): + return tuple(p for p in params if p in PARAM_WHITELIST) + + def filter_args(args): + return tuple(pair for pair in args if pair[0] in PARAM_WHITELIST) + + def filter_element(e): + """ Strip nt arguments. """ + if isinstance(e, jsparagus.grammar.Nt): + return jsparagus.grammar.Nt(e.name, filter_args(e.args)) + elif isinstance(e, jsparagus.grammar.Optional): + return jsparagus.grammar.Optional(filter_element(e.inner)) + else: + return e + + def filter_condition(c): + if c is None or c[0] not in PARAM_WHITELIST: + return None + return c + + def filter_production(p): + """ Discard production conditions and nt arguments. """ + body = [filter_element(e) for e in p.body] + return jsparagus.grammar.Production(body, p.reducer, + condition=filter_condition(p.condition)) + + nonterminals = {} + for nt, nt_def in g.nonterminals.items(): + params = tuple(filter_params(nt_def.params)) + rhs_list = [filter_production(p) for p in nt_def.rhs_list] + nonterminals[nt] = jsparagus.grammar.NtDef(params, rhs_list, nt_def.type) + return g.with_nonterminals(nonterminals) + + +def main(): + # Read command-line options. + parser = argparse.ArgumentParser( + description='Ponder the ECMAScript grammar.', + allow_abbrev=False) + default_filename = os.path.join(os.path.dirname(__file__), + "es-simplified.esgrammar") + parser.add_argument( + 'filename', metavar='FILE', nargs='?', default=default_filename, + help=".esgrammar (or .jsparagus_dump) input file") + parser.add_argument( + 'handler_info', metavar='HANDLER_INFO', nargs='?', + help="JSON file that contains information about handler") + parser.add_argument( + '-e', '--extend', action='append', default=[], + help="name of a files which contains a grammar_extension Rust macro.") + parser.add_argument( + '-o', '--output', metavar='FILE', default='/dev/stdout', + help="output filename for parser tables") + parser.add_argument( + '-v', '--verbose', action='store_true', + help="print some debug output") + parser.add_argument( + '--progress', action='store_true', + help="print a dot each time a state is analyzed (thousands of them)") + parser.add_argument( + '--debug', action='store_true', + help="annotate the generated code with grammar productions") + args = parser.parse_args() + + # Check filenames. + in_filename = args.filename + if in_filename.endswith('.esgrammar'): + from_source = True + elif in_filename.endswith('.jsparagus_dump'): + from_source = False + else: + raise ValueError("input file extension should be .esgrammar or .jsparagus_dump") + + out_filename = args.output + if out_filename.endswith('.py'): + target = 'python' + elif out_filename.endswith('.rs'): + target = 'rust' + elif out_filename.endswith('.jsparagus_dump'): + target = 'dump' + else: + raise ValueError("-o file extension should be .py, .rs, or .jsparagus_dump") + + in_extend = args.extend + if from_source: + assert all(f.endswith('.rs') for f in in_extend), "Extension are only supposed to be Rust files." + else: + assert in_extend == [], "Cannot add extensions to the generated parse table." + + # Load input and analyze it. + if from_source: + grammar = load_es_grammar.load_syntactic_grammar(in_filename, in_extend) + grammar = hack_grammar(grammar) + if args.verbose: + grammar.dump() + + states = jsparagus.gen.generate_parser_states( + grammar, verbose=args.verbose, progress=args.progress) + else: + states = jsparagus.gen.ParseTable.load(in_filename) + + # Generate output. + try: + if target in ('python', 'rust'): + with open(out_filename, 'w') as f: + jsparagus.gen.generate_parser(f, states, + target=target, + verbose=args.verbose, + debug=args.debug, + handler_info=args.handler_info) + else: + assert target == 'dump' + states.save(out_filename) + except Exception: + # On failure, don't leave a partial output file lying around. + try: + os.remove(out_filename) + except Exception: + pass + raise + + +if __name__ == '__main__': + main() diff --git a/third_party/rust/jsparagus/js_parser/lexer.py b/third_party/rust/jsparagus/js_parser/lexer.py new file mode 100644 index 0000000000..2d8ed530ed --- /dev/null +++ b/third_party/rust/jsparagus/js_parser/lexer.py @@ -0,0 +1,315 @@ +"""Vague approximation of an ECMAScript lexer. + +A parser has two levels: the *lexer* scans bytes to produce tokens. The +*parser* consumes tokens and produces ASTs. + +In a traditional design, the parser drives the process. It *pulls* one token at +a time from the lexer. However, for a parser that can accept arbitrary slabs of +data, scan them, then keep going, it makes more sense for the user to feed +those slabs to the lexer, which then *pushes* tokens to the parser. So that's +what we do. + +Usage: + + from js_parser.lexer import JSLexer + from js_parser.parser import JSParser + + lexer = JSLexer(JSParser()) + lexer.write(some_source_text) + lexer.write(some_more_source_text) + ast = lexer.close() +""" + +import re +import jsparagus.lexer + + +def _get_punctuators(): + punctuators = ''' + &&= ||= ??= + { ( ) [ ] . ... ; , < > <= >= == != === !== + - * % ** ++ -- + << >> >>> & | ^ ! ~ && || ? : = += -= *= %= + **= ><<= >>= >>>= &= |= ^= => + '''.split() + + return '|'.join( + re.escape(token) + for token in sorted(punctuators, key=len, reverse=True)) + + +TOKEN_RE = re.compile(r'''(?x) + (?: + # WhiteSpace + [\ \t\v\r\n\u00a0\u2028\u2029\ufeff] + # SingleLineComment + | // [^\r\n\u2028\u2029]* (?= [\r\n\u2028\u2029] | \Z ) + # MultiLineComment + | /\* (?: [^*] | \*+[^/] )* \*+/ + )* + ( + # Incomplete MultiLineComment + /\* (?: [^*] | \*+[^/] )* \** + | # Incomplete SingleLineComment + // [^\r\n\u2028\u2029]* + | # IdentifierName + (?: [$_A-Za-z] | \\ u [0-9A-Fa-f]{4} | \\ u \{ [0-9A-Fa-f]+ \}) + (?: [$_0-9A-Za-z] | \\ u [0-9A-Fa-f]{4} | \\ u \{ [0-9A-Fa-f]+ \})* + | # NumericLiteral + [0-9][0-9A-Za-z]*(?:\.[0-9A-Za-z]*)? + | \.[0-9][0-9A-Za-z]* + | # Punctuator + <INSERT_PUNCTUATORS> + | # The slash special case + / + | # The curly brace special case + } + | # StringLiteral + ' + # SingleStringCharacters + (?: + # SourceCharacter but not one of ' or \\ or LineTerminator + # but also allow LINE SEPARATOR or PARAGRAPH SEPARATOR + [^'\\\r\n] + | \\ [^0-9xu\r\n\u2028\u2029] # CharacterEscapeSequence + | \\ x [0-9A-Fa-f]{2} # HexEscapeSequence + | \\ u [0-9A-Fa-f]{4} # UnicodeEscapeSequence + | \\ u \{ [0-9A-Fa-f]+ \} + | \\\r\n? # LineContinuation + | \\[\n\u2028\u2029] + )* + ' + | " + # DoubleStringCharacters + (?: + # SourceCharacter but not one of " or \\ or LineTerminator + # but also allow LINE SEPARATOR or PARAGRAPH SEPARATOR + [^"\\\r\n] + | \\ [^0-9xu\r\n\u2028\u2029] # CharacterEscapeSequence + | \\ x [0-9A-Fa-f]{2} # HexEscapeSequence + | \\ u [0-9A-Fa-f]{4} # UnicodeEscapeSequence + | \\ u \{ [0-9A-Fa-f]+ \} + | \\\r\n? # LineContinuation + | \\[\n\u2028\u2029] + )* + " + | # Template + ` (?: [^`\\$] | \\. )* (?: \${ | ` ) + | # illegal character or end of input (this branch matches no characters) + ) +'''.replace("<INSERT_PUNCTUATORS>", _get_punctuators())) + +DIV_RE = re.compile(r'(/=?)') + +REGEXP_RE = re.compile(r'''(?x) +( + / + (?: + # RegularExpressionFirstChar - implemented using + # RegularExpressionChars on the theory that we have already + # ruled out the possibility of a comment. + # RegularExpressionChars + (?: + # RegularExpressionNonTerminator but not one of \\ or / or [ + [^/\\\[\r\n\u2028\u2029] + | # RegularExpressionBackslashSequence + \\ [^\r\n\u2028\u2029] + | # RegularExpressionClass + \[ + # RegularExpressionClassChars + (?: + # RegularExpressionNonTerminator but not one of ] or \\ + [^]\\\r\n\u2028\u2029] + | # RegularExpressionBackslashSequence + \\ [^\r\n\u2028\u2029] + )* + \] + )+ + ) + / + (?: \w* ) +) +''') + +# Words that never match Identifier. (`await` and `yield` nonetheless +# conditionally match IdentifierReference, BindingIdentifier, and +# LabelIdentifier.) +# +# Technically the term for these is "reserved word", not "keyword", but +# whatever. +ECMASCRIPT_FULL_KEYWORDS = [ + 'await', + 'break', + 'case', + 'catch', + 'class', + 'const', + 'continue', + 'debugger', + 'default', + 'delete', + 'do', + 'else', + 'enum', + 'export', + 'extends', + 'finally', + 'for', + 'function', + 'if', + 'import', + 'in', + 'instanceof', + 'new', + 'null', + 'return', + 'super', + 'switch', + 'this', + 'throw', + 'true', + 'false', + 'try', + 'typeof', + 'var', + 'void', + 'while', + 'with', + 'yield', +] + +ECMASCRIPT_CONDITIONAL_KEYWORDS = [ + # Words that are identifiers except in strict mode + 'let', # this one is also banned at the beginning of an ExpressionStatement + 'static', + 'implements', + 'interface', + 'package', + 'private', + 'protected', + 'public', + + # Words that are always allowed as identifiers, but are also keywords in + # other contexts. + 'as', + 'async', + 'from', + 'get', + 'of', + 'set', + 'target', +] + +# Technically this set includes a reserved word that isn't currently being used +# as a keyword in the grammar: `enum`. +ALL_KEYWORDS = set(ECMASCRIPT_FULL_KEYWORDS + ECMASCRIPT_CONDITIONAL_KEYWORDS) + + +class JSLexer(jsparagus.lexer.FlatStringLexer): + """Vague approximation of an ECMAScript lexer. """ + def __init__(self, parser, filename=None): + super().__init__(parser, filename) + + def _match(self, closing): + match = TOKEN_RE.match(self.src, self.point) + assert match is not None + + if match.end() == len(self.src) and not closing: + # The current token runs right up against the end of the current + # chunk of source and thus might continue in the next chunk. Do not + # move self.point. + return None + + token = match.group(1) + if token == '': + # Whitespace followed by end of input or illegal character. + if match.end() == len(self.src): + # End of input. Success! + assert closing + self.point = match.end() + return None + else: + c = self.src[match.end()] + self.throw("unexpected character: {!r}".format(c)) + + c = token[0] + t = None + if c.isdigit() or c == '.' and token != '.': + t = 'NumericLiteral' + elif c.isalpha() or c in '$_': + if token in ALL_KEYWORDS: # TODO support strict mode + if token == 'null': + t = 'NullLiteral' + elif token in ('true', 'false'): + t = 'BooleanLiteral' + else: + t = token + else: + t = 'Name' + elif c == '/': + if token.startswith(('/*', '//')): + # Incomplete comment. (In non-closing mode, this is handled + # above, immediately after the match.) + assert match.end() == len(self.src) + assert closing + self.point = len(self.src) + self.throw("incomplete comment at end of source") + + # We choose RegExp vs. division based on what the parser can + # accept, a literal implementation of the spec. + # + # To make this correct in combination with end-of-line ASI, make + # the parser rewind the lexer one token and ask for it again in + # that case, so that the lexer asks the can-accept question again. + point = match.start(1) + if self.parser.can_accept_terminal(self, 'RegularExpressionLiteral'): + match = REGEXP_RE.match(self.src, point) + if match is None: + if closing: + self.throw("unterminated regexp literal") + else: + return None + token = 'RegularExpressionLiteral' + else: + match = DIV_RE.match(self.src, point) + token = match.group(1) + + if not closing and match.end() == len(self.src): + # At the end of a chunk, `/a*b/` could be the start of + # `/a*b/g`, and `/` could be the start of `/=`. + return None + + t = token + elif c == '`': + if token.endswith('`'): + t = 'NoSubstitutionTemplate' + else: + t = 'TemplateHead' + elif c == '"' or c == "'": + t = 'StringLiteral' + elif c == '}': + # TODO: TemplateTail + t = token + elif c in '{()[];,~?:.<>=!+-*%&|^': + t = token + else: + assert False + + self._current_match = match + self.previous_token_end = self.point + self.current_token_start = match.start(1) + self.point = match.end() + return t + + def take(self): + return self._current_match.group(1) + + def saw_line_terminator(self): + """True if there's a LineTerminator before the current token.""" + i = self.previous_token_end + j = self.current_token_start + ws_between = self.src[i:j] + return any(c in ws_between for c in '\r\n\u2028\u2029') + + def can_close(self): + match = TOKEN_RE.match(self.src) + return match.group(1) == '' and self.parser.can_close() diff --git a/third_party/rust/jsparagus/js_parser/load_es_grammar.py b/third_party/rust/jsparagus/js_parser/load_es_grammar.py new file mode 100644 index 0000000000..c50688534d --- /dev/null +++ b/third_party/rust/jsparagus/js_parser/load_es_grammar.py @@ -0,0 +1,129 @@ +""" Functions for loading the ECMAScript lexical and syntactic grammars. """ + +from jsparagus.ordered import OrderedSet, OrderedFrozenSet +from jsparagus import gen, grammar +from .lexer import ECMASCRIPT_FULL_KEYWORDS, ECMASCRIPT_CONDITIONAL_KEYWORDS +from .parse_esgrammar import parse_esgrammar + + +ECMASCRIPT_LEXICAL_SYNTHETIC_TERMINALS: grammar.SyntheticTerminalsDict = { + # Theoretically, this should be the set of all Unicode characters, but that + # would take a lot of memory, and in practice, the set is not used. + 'SourceCharacter': OrderedFrozenSet([]), +} + +ECMASCRIPT_LEXICAL_GOAL_NTS = [ + 'WhiteSpace', + 'InputElementDiv', + 'InputElementRegExp', +] + + +def load_lexical_grammar(filename): + """Load the ECMAScript lexical grammar.""" + with open(filename) as f: + grammar_text = f.read() + g = parse_esgrammar( + grammar_text, + filename=filename, + goals=ECMASCRIPT_LEXICAL_GOAL_NTS, + synthetic_terminals=ECMASCRIPT_LEXICAL_SYNTHETIC_TERMINALS, + terminal_names=ECMASCRIPT_LEXICAL_SYNTHETIC_TERMINALS.keys()) + return gen.expand_parameterized_nonterminals(g) + + +ECMASCRIPT_SYNTACTIC_GOAL_NTS = [ + 'Script', + 'Module', + # 'FormalParameters', + # 'FunctionBody', +] + +# Identifiers are complicated. A "synthetic terminal" is a shorthand symbol +# that stands for any one of a set of terminals. For example, *IdentifierName* +# stands for any token that looks like an identifier, including keywords. +# +# These sets must use the names of the terminals produced by the lexer. Except +# for `Name`, our lexer output uses the terminal symbols of the syntactic +# grammar, which include some nonterminals of the lexical grammar. The +# syntactic grammar uses `BooleanLiteral`, not `true` and `false`; and it uses +# `NullLiteral` instead of `null`. +ECMASCRIPT_SYNTHETIC_TERMINALS = { + 'IdentifierName': OrderedSet([ + 'Name', + 'BooleanLiteral', + 'NullLiteral', + 'NameWithEscape', + *ECMASCRIPT_FULL_KEYWORDS, + *ECMASCRIPT_CONDITIONAL_KEYWORDS + ]) - OrderedSet(['true', 'false', 'null']), + 'Identifier': OrderedSet([ + 'Name', + 'NameWithEscape', + *ECMASCRIPT_CONDITIONAL_KEYWORDS + ]), +} + +# Lexical nonterminals that are used as terminals in the syntactic grammar. +ECMASCRIPT_TOKEN_NAMES = [ + 'BooleanLiteral', + 'IdentifierName', + 'PrivateIdentifier', + 'NoSubstitutionTemplate', + 'NullLiteral', + 'NumericLiteral', + 'BigIntLiteral', + 'RegularExpressionLiteral', + 'StringLiteral', + 'TemplateHead', + 'TemplateMiddle', + 'TemplateTail', +] + +# List of all terminals, other than keywords, that our (hand-coded) lexer +# produces. +# +# (What our lexer implements for IdentifierName and friends is a slight +# variation on the spec. See `ECMASCRIPT_SYNTHETIC_TERMINALS` above.) +TERMINAL_NAMES_FOR_SYNTACTIC_GRAMMAR = ECMASCRIPT_TOKEN_NAMES + [ + 'Identifier', + 'Name', +] + + +def load_syntactic_grammar(filename, extensions): + """Load the ECMAScript syntactic grammar.""" + with open(filename) as f: + grammar_text = f.read() + + extensions_content = [] + for ext_filename in extensions: + # Extract grammar_extension! macro content, and store in a list. + with open(ext_filename) as ext_file: + content = None + start_line = 0 + for lineno, line in enumerate(ext_file): + if line.startswith("grammar_extension!"): + assert line.endswith("{\n") + content = "" + # +2: enumerate starts at 0, while the first line is 1. + # Also, the first line added to the content variable is the + # next one. + start_line = lineno + 2 + continue + if line.startswith("}") and content: + extensions_content.append((ext_filename, start_line, content)) + content = None + continue + if content is not None: + content += line + + g = parse_esgrammar( + grammar_text, + filename=filename, + extensions=extensions_content, + goals=ECMASCRIPT_SYNTACTIC_GOAL_NTS, + synthetic_terminals=ECMASCRIPT_SYNTHETIC_TERMINALS, + terminal_names=TERMINAL_NAMES_FOR_SYNTACTIC_GRAMMAR) + + return g diff --git a/third_party/rust/jsparagus/js_parser/parse_esgrammar.py b/third_party/rust/jsparagus/js_parser/parse_esgrammar.py new file mode 100644 index 0000000000..efcb640406 --- /dev/null +++ b/third_party/rust/jsparagus/js_parser/parse_esgrammar.py @@ -0,0 +1,545 @@ +"""Parse a grammar written in ECMArkup.""" + +from __future__ import annotations +# mypy: no-implicit-optional + +import os +import collections +from typing import Dict, Iterable, Optional, Tuple + +from jsparagus import parse_pgen, gen, grammar, extension, types +from jsparagus.lexer import LexicalGrammar +from jsparagus.ordered import OrderedSet, OrderedFrozenSet + + +ESGrammarLexer = LexicalGrammar( + # the operators and keywords: + "[ ] { } , ~ + ? <! = == != => ( ) @ < > ' ; " + "but empty here lookahead no not of one or returns through Some None impl for let", + + NL="\n", + + # any number of colons together + EQ=r':+', + + # terminals of the ES grammar, quoted with backticks + T=r'`[^` \n]+`|```', + + # also terminals, denoting control characters + CHR=r'<[A-Z ]+>|U\+[0-9A-f]{4}', + + # nonterminals/types that will be followed by parameters + NTCALL=r'[A-Za-z]\w*(?=[\[<])', + + # nonterminals (also, boolean parameters and type names) + NT=r'[A-Za-z]\w*', + + # nonterminals wrapped in vertical bars for no apparent reason + NTALT=r'\|[A-Z]\w+\|', + + # the spec also gives a few productions names + PRODID=r'#[A-Za-z]\w*', + + # prose not wrapped in square brackets + # To avoid conflict with the `>` token, this is recognized only after a space. + PROSE=r'(?<= )>[^\n]*', + + # prose wrapped in square brackets + WPROSE=r'\[>[^]]*\]', + + # expression denoting a matched terminal or nonterminal + MATCH_REF=r'\$(?:0|[1-9][0-9]*)', + + # the spec also gives a few productions names + RUSTCOMMENT=r'//.*\n', +) + + +ESGrammarParser = gen.compile( + parse_pgen.load_grammar( + os.path.join(os.path.dirname(__file__), "esgrammar.pgen"))) + + +SIGIL_FALSE = '~' +SIGIL_TRUE = '+' + +# Abbreviations for single-character terminals, used in the lexical grammar. +ECMASCRIPT_CODE_POINTS = { + # From <https://tc39.es/ecma262/#table-31> + '<ZWNJ>': grammar.Literal('\u200c'), + '<ZWJ>': grammar.Literal('\u200d'), + '<ZWNBSP>': grammar.Literal('\ufeff'), + + # From <https://tc39.es/ecma262/#table-32> + '<TAB>': grammar.Literal('\t'), + '<VT>': grammar.Literal('\u000b'), + '<FF>': grammar.Literal('\u000c'), + '<SP>': grammar.Literal(' '), + '<NBSP>': grammar.Literal('\u00a0'), + # <ZWNBSP> already defined above + '<USP>': grammar.UnicodeCategory('Zs'), + + # From <https://tc39.es/ecma262/#table-33> + '<LF>': grammar.Literal('\u000a'), + '<CR>': grammar.Literal('\u000d'), + '<LS>': grammar.Literal('\u2028'), + '<PS>': grammar.Literal('\u2028'), +} + + +class ESGrammarBuilder: + def __init__(self, terminal_names): + # Names of terminals that are written as nonterminals in the grammar. + # For example, "BooleanLiteral" is a terminal name when parsing the + # syntactic grammar. + if terminal_names is None: + terminal_names = frozenset() + self.terminal_names = frozenset(terminal_names) + self.reset() + + def reset(self): + self.lexer = None + # This is how full-parsing and lazy-parsing are implemented, using + # different traits. + # + # This field contains the Rust's trait used for calling the method. + # When a CallMethod is generated, it is assumed to be a function of + # this trait. The trait is used by the Rust backend to generate + # multiple backends which are implementing different set of traits. + # Having the trait on the function call is useful as a way to filter + # functions calls at code-generation time. + # + # This field is updated by the `rust_param_impl`, which is used in + # grammar extensions, and visited before producing any CallMethod. + self.method_trait = "AstBuilder" + + def rust_edsl(self, impl, grammar): + return extension.GrammarExtension(impl, grammar, self.lexer.filename) + + def rust_param_impl(self, trait, for_type, param): + self.method_trait = trait + return extension.ImplFor(param, trait, for_type) + + def rust_impl(self, trait, impl_type): + return self.rust_param_impl(trait, impl_type, []) + + def rust_nt_def(self, lhs, rhs_line): + # Right now, only focus on the syntactic grammar, and assume that all + # rules are patching existing grammar production by adding code. + return extension.ExtPatch(self.nt_def(None, lhs, ':', [rhs_line])) + + def rust_rhs_line(self, symbols): + return self.rhs_line(None, symbols, None, None) + + def rust_expr(self, expr): + assert isinstance(expr, grammar.CallMethod) + return expr + + def empty(self): + return [] + + def single(self, x): + return [x] + + def append(self, x, y): + return x + [y] + + def concat(self, x, y): + return x + y + + def blank_line(self): + return [] + + def nt_def_to_list(self, nt_def): + return [nt_def] + + def to_production(self, lhs, i, rhs, is_sole_production): + """Wrap a list of grammar symbols `rhs` in a Production object.""" + body, reducer, condition = rhs + if reducer is None: + reducer = self.default_reducer(lhs, i, body, is_sole_production) + return grammar.Production(body, reducer, condition=condition) + + def default_reducer(self, lhs, i, body, is_sole_production): + assert isinstance(lhs, grammar.Nt) + nt_name = lhs.name + + nargs = sum(1 for e in body if grammar.is_concrete_element(e)) + if is_sole_production: + method_name = nt_name + else: + method_name = '{} {}'.format(nt_name, i) + return self.expr_call(method_name, tuple(range(nargs)), None) + + def needs_asi(self, lhs, p): + """True if p is a production in which ASI can happen.""" + # The purpose of the fake ForLexicalDeclaration production is to have a + # copy of LexicalDeclaration that does not trigger ASI. + # + # Two productions have body == [";"] -- one for EmptyStatement and one + # for ClassMember. Neither should trigger ASI. + # + # The only other semicolons that should not trigger ASI are the ones in + # `for` statement productions, which happen to be exactly those + # semicolons that are not at the end of a production. + return (not (isinstance(lhs, grammar.Nt) + and lhs.name == 'ForLexicalDeclaration') + and len(p.body) > 1 + and p.body[-1] == ';') + + def apply_asi(self, p, reducer_was_autogenerated): + """Return two rules based on p, so that ASI can be applied.""" + assert isinstance(p.reducer, grammar.CallMethod) + + if reducer_was_autogenerated: + # Don't pass the semicolon to the method. + reducer = self.expr_call(p.reducer.method, + p.reducer.args[:-1], + None) + else: + reducer = p.reducer + + # Except for do-while loops, check at runtime that ASI occurs only at + # the end of a line. + if (len(p.body) == 7 + and p.body[0] == 'do' + and p.body[2] == 'while' + and p.body[3] == '(' + and p.body[5] == ')' + and p.body[6] == ';'): + code = "do_while_asi" + else: + code = "asi" + + return [ + # The preferred production, with the semicolon in. + p.copy_with(body=p.body[:], + reducer=reducer), + # The fallback production, performing ASI. + p.copy_with(body=p.body[:-1] + [grammar.ErrorSymbol(code)], + reducer=reducer), + ] + + def expand_lexical_rhs(self, rhs): + body, reducer, condition = rhs + out = [] + for e in body: + if isinstance(e, str): + # The terminal symbols of the lexical grammar are characters, so + # add each character of this string as a separate element. + out += [grammar.Literal(ch) for ch in e] + else: + out.append(e) + return [out, reducer, condition] + + def nt_def(self, nt_type, lhs, eq, rhs_list): + has_sole_production = (len(rhs_list) == 1) + production_list = [] + for i, rhs in enumerate(rhs_list): + if eq == ':': + # Syntactic grammar. A hack is needed for ASI. + reducer_was_autogenerated = rhs[1] is None + p = self.to_production(lhs, i, rhs, has_sole_production) + if self.needs_asi(lhs, p): + production_list += self.apply_asi(p, reducer_was_autogenerated) + else: + production_list.append(p) + elif eq == '::': + # Lexical grammar. A hack is needed to replace multicharacter + # terminals like `!==` into sequences of character terminals. + rhs = self.expand_lexical_rhs(rhs) + p = self.to_production(lhs, i, rhs, has_sole_production) + production_list.append(p) + return (lhs.name, eq, grammar.NtDef(lhs.args, production_list, nt_type)) + + def nt_def_one_of(self, nt_type, nt_lhs, eq, terminals): + return self.nt_def(nt_type, nt_lhs, eq, [([t], None, None) for t in terminals]) + + def nt_lhs_no_params(self, name): + return grammar.Nt(name, ()) + + def nt_lhs_with_params(self, name, params): + return grammar.Nt(name, tuple(params)) + + def simple_type(self, name): + return types.Type(name) + + def lifetime_type(self, name): + return types.Lifetime(name) + + def parameterized_type(self, name, args): + return types.Type(name, tuple(args)) + + def t_list_line(self, terminals): + return terminals + + def terminal(self, t): + assert t[0] == "`" + assert t[-1] == "`" + return t[1:-1] + + def terminal_chr(self, chr): + raise ValueError("FAILED: %r" % chr) + + def rhs_line(self, ifdef, rhs, reducer, _prodid): + return (rhs, reducer, ifdef) + + def rhs_line_prose(self, prose): + return ([prose], None, None) + + def empty_rhs(self): + return [] + + def expr_match_ref(self, token): + assert token.startswith('$') + return int(token[1:]) + + def expr_call(self, method, args, fallible): + # NOTE: Currently "AstBuilder" functions are made fallible using the + # fallible_methods taken from some Rust code which extract this + # information to produce a JSON file. + if self.method_trait == "AstBuilder": + fallible = None + return grammar.CallMethod(method, args or (), types.Type(self.method_trait), + fallible is not None) + + def expr_some(self, expr): + return grammar.Some(expr) + + def expr_none(self): + return None + + def ifdef(self, value, nt): + return nt, value + + def optional(self, nt): + return grammar.Optional(nt) + + def but_not(self, nt, exclusion): + _, exclusion = exclusion + return grammar.Exclude(nt, [exclusion]) + # return ('-', nt, exclusion) + + def but_not_one_of(self, nt, exclusion_list): + exclusion_list = [exclusion for _, exclusion in exclusion_list] + return grammar.Exclude(nt, exclusion_list) + # return ('-', nt, exclusion_list) + + def no_line_terminator_here(self, lt): + if lt not in ('LineTerminator', '|LineTerminator|'): + raise ValueError("unrecognized directive " + repr("[no " + lt + " here]")) + return grammar.NoLineTerminatorHere + + def nonterminal(self, name): + if name in self.terminal_names: + return name + return grammar.Nt(name, ()) + + def nonterminal_apply(self, name, args): + if name in self.terminal_names: + raise ValueError("parameters applied to terminal {!r}".format(name)) + if len(set(k for k, expr in args)) != len(args): + raise ValueError("parameter passed multiple times") + return grammar.Nt(name, tuple(args)) + + def arg_expr(self, sigil, argname): + if sigil == '?': + return (argname, grammar.Var(argname)) + else: + return (argname, sigil) + + def sigil_false(self): + return False + + def sigil_true(self): + return True + + def exclusion_terminal(self, t): + return ("t", t) + + def exclusion_nonterminal(self, nt): + return ("nt", nt) + + def exclusion_chr_range(self, c1, c2): + return ("range", c1, c2) + + def la_eq(self, t): + return grammar.LookaheadRule(OrderedFrozenSet([t]), True) + + def la_ne(self, t): + return grammar.LookaheadRule(OrderedFrozenSet([t]), False) + + def la_not_in_nonterminal(self, nt): + return grammar.LookaheadRule(OrderedFrozenSet([nt]), False) + + def la_not_in_set(self, lookahead_exclusions): + if all(len(excl) == 1 for excl in lookahead_exclusions): + return grammar.LookaheadRule( + OrderedFrozenSet(excl[0] for excl in lookahead_exclusions), + False) + raise ValueError("unsupported: lookahead > 1 token, {!r}" + .format(lookahead_exclusions)) + + def chr(self, t): + assert t[0] == "<" or t[0] == 'U' + if t[0] == "<": + assert t[-1] == ">" + if t not in ECMASCRIPT_CODE_POINTS: + raise ValueError("unrecognized character abbreviation {!r}".format(t)) + return ECMASCRIPT_CODE_POINTS[t] + else: + assert t[1] == "+" + return grammar.Literal(chr(int(t[2:], base=16))) + + +def finish_grammar(nt_defs, goals, variable_terminals, synthetic_terminals, + single_grammar=True, extensions=[]): + nt_grammars = {} + for nt_name, eq, _ in nt_defs: + if nt_name in nt_grammars: + raise ValueError( + "duplicate definitions for nonterminal {!r}" + .format(nt_name)) + nt_grammars[nt_name] = eq + + # Figure out which grammar we were trying to get (":" for syntactic, + # "::" for lexical) based on the goal symbols. + goals = list(goals) + if len(goals) == 0: + raise ValueError("no goal nonterminals specified") + if single_grammar: + selected_grammars = set(nt_grammars[goal] for goal in goals) + assert len(selected_grammars) != 0 + if len(selected_grammars) > 1: + raise ValueError( + "all goal nonterminals must be part of the same grammar; " + "got {!r} (matching these grammars: {!r})" + .format(set(goals), set(selected_grammars))) + [selected_grammar] = selected_grammars + + terminal_set = set() + + def hack_production(p): + for i, e in enumerate(p.body): + if isinstance(e, str) and e[:1] == "`": + if len(e) < 3 or e[-1:] != "`": + raise ValueError( + "Unrecognized grammar symbol: {!r} (in {!r})" + .format(e, p)) + p[i] = token = e[1:-1] + terminal_set.add(token) + + nonterminals = {} + for nt_name, eq, rhs_list_or_lambda in nt_defs: + if single_grammar and eq != selected_grammar: + continue + + if isinstance(rhs_list_or_lambda, grammar.NtDef): + nonterminals[nt_name] = rhs_list_or_lambda + else: + rhs_list = rhs_list_or_lambda + for p in rhs_list: + if not isinstance(p, grammar.Production): + raise ValueError( + "invalid grammar: ifdef in non-function-call context") + hack_production(p) + if nt_name in nonterminals: + raise ValueError( + "unsupported: multiple definitions for nt " + nt_name) + nonterminals[nt_name] = rhs_list + + for t in terminal_set: + if t in nonterminals: + raise ValueError( + "grammar contains both a terminal `{}` and nonterminal {}" + .format(t, t)) + + # Add execution modes to generate the various functions needed to handle + # syntax parsing and full parsing execution modes. + exec_modes = collections.defaultdict(OrderedSet) + noop_parser = types.Type("ParserTrait", (types.Lifetime("alloc"), types.UnitType)) + token_parser = types.Type("ParserTrait", ( + types.Lifetime("alloc"), types.Type("StackValue", (types.Lifetime("alloc"),)))) + ast_builder = types.Type("AstBuilderDelegate", (types.Lifetime("alloc"),)) + + # Full parsing takes token as input and build an AST. + exec_modes["full_actions"].extend([token_parser, ast_builder]) + + # Syntax parsing takes token as input but skip building the AST. + # TODO: The syntax parser is commented out for now, as we need something to + # be produced when we cannot call the AstBuilder for producing the values. + + # No-op parsing is used for the simulator, which is so far used for + # querying whether we can end the incremental input and lookup if a state + # can accept some kind of tokens. + exec_modes["noop_actions"].add(noop_parser) + + # Extensions are using an equivalent of Rust types to define the kind of + # parsers to be used, this map is used to convert these type names to the + # various execution modes. + full_parser = types.Type("FullParser") + syntax_parser = types.Type("SyntaxParser") + noop_parser = types.Type("NoopParser") + type_to_modes = { + noop_parser: ["noop_actions", "full_actions"], + syntax_parser: ["full_actions"], + full_parser: ["full_actions"], + } + + result = grammar.Grammar( + nonterminals, + goal_nts=goals, + variable_terminals=variable_terminals, + synthetic_terminals=synthetic_terminals, + exec_modes=exec_modes, + type_to_modes=type_to_modes) + result.patch(extensions) + return result + + +def parse_esgrammar( + text: str, + *, + filename: Optional[str] = None, + extensions: Iterable[Tuple[os.PathLike, int, str]] = (), + goals: Optional[Iterable[str]] = None, + terminal_names: Iterable[str] = (), + synthetic_terminals: Optional[Dict[str, OrderedSet[str]]] = None, + single_grammar: bool = True +) -> grammar.Grammar: + if not text.endswith("\n\n"): + # Horrible hack: add a blank line at the end of the document so that + # the esgrammar grammar can use newlines as delimiters. :-P + text += "\n" + + terminal_names = frozenset(terminal_names) + if synthetic_terminals is None: + synthetic_terminals = {} + + builder = ESGrammarBuilder(terminal_names) + parser = ESGrammarParser(builder=builder, goal="grammar") + lexer = ESGrammarLexer(parser, filename=filename) + lexer.write(text) + nt_defs = lexer.close() + grammar_extensions = [] + for ext_filename, start_lineno, content in extensions: + builder.reset() + parser = ESGrammarParser(builder=builder, goal="rust_edsl") + lexer = ESGrammarLexer(parser, filename=ext_filename) + builder.lexer = lexer + lexer.start_lineno = start_lineno + lexer.write(content) + result = lexer.close() + grammar_extensions.append(result) + + if goals is None: + # Default to the first nonterminal in the input. + goals = [nt_defs[0][0]] + + return finish_grammar( + nt_defs, + goals=goals, + variable_terminals=terminal_names - frozenset(synthetic_terminals), + synthetic_terminals=synthetic_terminals, + single_grammar=single_grammar, + extensions=grammar_extensions) diff --git a/third_party/rust/jsparagus/js_parser/parser.py b/third_party/rust/jsparagus/js_parser/parser.py new file mode 100644 index 0000000000..f67708a9cc --- /dev/null +++ b/third_party/rust/jsparagus/js_parser/parser.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python + +"""parser.py - A JavaScript parser, currently with many bugs. + +See README.md for instructions. +""" + +from . import parser_tables +from .lexer import JSLexer + + +# "type: ignore" because mypy can't see inside js_parser.parser_tables. +class JSParser(parser_tables.Parser): # type: ignore + def __init__(self, goal='Script', builder=None): + super().__init__(goal, builder) + self._goal = goal + + def clone(self): + return JSParser(self._goal, self.methods) + + def on_recover(self, error_code, lexer, stv): + """Check that ASI error recovery is really acceptable.""" + if error_code == 'asi': + # ASI is allowed in three places: + # - at the end of the source text + # - before a close brace `}` + # - after a LineTerminator + # Hence the three-part if-condition below. + # + # The other quirks of ASI are implemented by massaging the syntax, + # in parse_esgrammar.py. + if not self.closed and stv.term != '}' and not lexer.saw_line_terminator(): + lexer.throw("missing semicolon") + else: + # ASI is always allowed in this one state. + assert error_code == 'do_while_asi' + + +def parse_Script(text): + lexer = JSLexer(JSParser('Script')) + lexer.write(text) + return lexer.close() diff --git a/third_party/rust/jsparagus/js_parser/slash.esgrammar b/third_party/rust/jsparagus/js_parser/slash.esgrammar new file mode 100644 index 0000000000..60bad3f660 --- /dev/null +++ b/third_party/rust/jsparagus/js_parser/slash.esgrammar @@ -0,0 +1,1683 @@ + +StringNumericLiteral ::: + StrWhiteSpace? + StrWhiteSpace? StrNumericLiteral StrWhiteSpace? + +StrWhiteSpace ::: + StrWhiteSpaceChar StrWhiteSpace? + +StrWhiteSpaceChar ::: + WhiteSpace + LineTerminator + +StrNumericLiteral ::: + StrDecimalLiteral + BinaryIntegerLiteral + OctalIntegerLiteral + HexIntegerLiteral + +StrDecimalLiteral ::: + StrUnsignedDecimalLiteral + `+` StrUnsignedDecimalLiteral + `-` StrUnsignedDecimalLiteral + +StrUnsignedDecimalLiteral ::: + `Infinity` + DecimalDigits `.` DecimalDigits? ExponentPart? + `.` DecimalDigits ExponentPart? + DecimalDigits ExponentPart? + + +SourceCharacter :: + {} + + +InputElementDiv :: + WhiteSpace + LineTerminator + Comment + CommonToken + DivPunctuator + RightBracePunctuator + +InputElementRegExp :: + WhiteSpace + LineTerminator + Comment + CommonToken + RightBracePunctuator + RegularExpressionLiteral + +InputElementRegExpOrTemplateTail :: + WhiteSpace + LineTerminator + Comment + CommonToken + RegularExpressionLiteral + TemplateSubstitutionTail + +InputElementTemplateTail :: + WhiteSpace + LineTerminator + Comment + CommonToken + DivPunctuator + TemplateSubstitutionTail + + +WhiteSpace :: + <TAB> + <VT> + <FF> + <SP> + <NBSP> + <ZWNBSP> + {Zs} + + +LineTerminator :: + <LF> + <CR> + <LINE SEPARATOR> + <PARAGRAPH SEPARATOR> + +LineTerminatorSequence :: + <LF> + <CR> [lookahead != <LF> ] + <LINE SEPARATOR> + <PARAGRAPH SEPARATOR> + <CR> <LF> + + +Comment :: + MultiLineComment + SingleLineComment + +MultiLineComment :: + `/*` MultiLineCommentChars? `*/` + +MultiLineCommentChars :: + MultiLineNotAsteriskChar MultiLineCommentChars? + `*` PostAsteriskCommentChars? + +PostAsteriskCommentChars :: + MultiLineNotForwardSlashOrAsteriskChar MultiLineCommentChars? + `*` PostAsteriskCommentChars? + +MultiLineNotAsteriskChar :: + SourceCharacter but not `*` + +MultiLineNotForwardSlashOrAsteriskChar :: + SourceCharacter but not one of `/` or `*` + +SingleLineComment :: + `//` SingleLineCommentChars? + +SingleLineCommentChars :: + SingleLineCommentChar SingleLineCommentChars? + +SingleLineCommentChar :: + SourceCharacter but not LineTerminator + + +CommonToken :: + IdentifierName + Punctuator + NumericLiteral + StringLiteral + Template + + +IdentifierName :: + IdentifierStart + IdentifierName IdentifierPart + +IdentifierStart :: + UnicodeIDStart + `$` + `_` + `\` UnicodeEscapeSequence + +IdentifierPart :: + UnicodeIDContinue + `$` + `\` UnicodeEscapeSequence + <ZWNJ> + <ZWJ> + +UnicodeIDStart :: + {L} + {NI} + U+2118 + U+212E + U+309B + U+309C + +UnicodeIDContinue :: + UnicodeIDStart + {Mn} + {Mc} + {Nd} + {Pc} + U+1369 + U+1370 + U+1371 + U+00B7 + U+0387 + U+19DA + + +ReservedWord :: + Keyword + FutureReservedWord + NullLiteral + BooleanLiteral + + +Keyword :: one of + `await` + `break` + `case` `catch` `class` `const` `continue` + `debugger` `default` `delete` `do` + `else` `export` `extends` + `finally` `for` `function` + `if` `import` `in` `instanceof` + `new` + `return` + `super` `switch` + `this` `throw` `try` `typeof` + `var` `void` + `while` `with` + `yield` + + +FutureReservedWord :: + `enum` + + +Punctuator :: one of + `{` `(` `)` `[` `]` + `.` `...` `;` `,` + `<` `>` `<=` `>=` + `==` `!=` `===` `!==` + `+` `-` `*` `%` `**` + `++` `--` + `<<` `>>` `>>>` + `&` `|` `^` + `!` `~` + `&&` `||` + `?` `:` + `=` `+=` `-=` `*=` `%=` `**=` `<<=` `>>=` `>>>=` `&=` `|=` `^=` + `=>` + +DivPunctuator :: + `/` + `/=` + +RightBracePunctuator :: + `}` + + +NullLiteral :: + `null` + + +BooleanLiteral :: + `true` + `false` + + +NumericLiteral :: + DecimalLiteral + BinaryIntegerLiteral + OctalIntegerLiteral + HexIntegerLiteral + +DecimalLiteral :: + DecimalIntegerLiteral `.` DecimalDigits? ExponentPart? + `.` DecimalDigits ExponentPart? + DecimalIntegerLiteral ExponentPart? + +DecimalIntegerLiteral :: + `0` + NonZeroDigit DecimalDigits? + +DecimalDigits :: + DecimalDigit + DecimalDigits DecimalDigit + +DecimalDigit :: one of + `0` `1` `2` `3` `4` `5` `6` `7` `8` `9` + +NonZeroDigit :: one of + `1` `2` `3` `4` `5` `6` `7` `8` `9` + +ExponentPart :: + ExponentIndicator SignedInteger + +ExponentIndicator :: one of + `e` `E` + +SignedInteger :: + DecimalDigits + `+` DecimalDigits + `-` DecimalDigits + +BinaryIntegerLiteral :: + `0b` BinaryDigits + `0B` BinaryDigits + +BinaryDigits :: + BinaryDigit + BinaryDigits BinaryDigit + +BinaryDigit :: one of + `0` `1` + +OctalIntegerLiteral :: + `0o` OctalDigits + `0O` OctalDigits + +OctalDigits :: + OctalDigit + OctalDigits OctalDigit + +OctalDigit :: one of + `0` `1` `2` `3` `4` `5` `6` `7` + +HexIntegerLiteral :: + `0x` HexDigits + `0X` HexDigits + +HexDigits :: + HexDigit + HexDigits HexDigit + +HexDigit :: one of + `0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `a` `b` `c` `d` `e` `f` `A` `B` `C` `D` `E` `F` + + +StringLiteral :: + `"` DoubleStringCharacters? `"` + `'` SingleStringCharacters? `'` + +DoubleStringCharacters :: + DoubleStringCharacter DoubleStringCharacters? + +SingleStringCharacters :: + SingleStringCharacter SingleStringCharacters? + +DoubleStringCharacter :: + SourceCharacter but not one of `"` or `\` or LineTerminator + <LINE SEPARATOR> + <PARAGRAPH SEPARATOR> + `\` EscapeSequence + LineContinuation + +SingleStringCharacter :: + SourceCharacter but not one of `'` or `\` or LineTerminator + <LINE SEPARATOR> + <PARAGRAPH SEPARATOR> + `\` EscapeSequence + LineContinuation + +LineContinuation :: + `\` LineTerminatorSequence + +EscapeSequence :: + CharacterEscapeSequence + `0` [lookahead <! DecimalDigit] + HexEscapeSequence + UnicodeEscapeSequence + + +CharacterEscapeSequence :: + SingleEscapeCharacter + NonEscapeCharacter + +SingleEscapeCharacter :: one of + `'` `"` `\` `b` `f` `n` `r` `t` `v` + +NonEscapeCharacter :: + SourceCharacter but not one of EscapeCharacter or LineTerminator + +EscapeCharacter :: + SingleEscapeCharacter + DecimalDigit + `x` + `u` + +HexEscapeSequence :: + `x` HexDigit HexDigit + +UnicodeEscapeSequence :: + `u` Hex4Digits + `u{` CodePoint `}` + +Hex4Digits :: + HexDigit HexDigit HexDigit HexDigit + + +RegularExpressionLiteral :: + `/` RegularExpressionBody `/` RegularExpressionFlags + +RegularExpressionBody :: + RegularExpressionFirstChar RegularExpressionChars + +RegularExpressionChars :: + [empty] + RegularExpressionChars RegularExpressionChar + +RegularExpressionFirstChar :: + RegularExpressionNonTerminator but not one of `*` or `\` or `/` or `[` + RegularExpressionBackslashSequence + RegularExpressionClass + +RegularExpressionChar :: + RegularExpressionNonTerminator but not one of `\` or `/` or `[` + RegularExpressionBackslashSequence + RegularExpressionClass + +RegularExpressionBackslashSequence :: + `\` RegularExpressionNonTerminator + +RegularExpressionNonTerminator :: + SourceCharacter but not LineTerminator + +RegularExpressionClass :: + `[` RegularExpressionClassChars `]` + +RegularExpressionClassChars :: + [empty] + RegularExpressionClassChars RegularExpressionClassChar + +RegularExpressionClassChar :: + RegularExpressionNonTerminator but not one of `]` or `\` + RegularExpressionBackslashSequence + +RegularExpressionFlags :: + [empty] + RegularExpressionFlags IdentifierPart + + +Template :: + NoSubstitutionTemplate + TemplateHead + +NoSubstitutionTemplate :: + ``` TemplateCharacters? ``` + +TemplateHead :: + ``` TemplateCharacters? `${` + +TemplateSubstitutionTail :: + TemplateMiddle + TemplateTail + +TemplateMiddle :: + `}` TemplateCharacters? `${` + +TemplateTail :: + `}` TemplateCharacters? ``` + +TemplateCharacters :: + TemplateCharacter TemplateCharacters? + +TemplateCharacter :: + `$` [lookahead != `{` ] + `\` EscapeSequence + `\` NotEscapeSequence + LineContinuation + LineTerminatorSequence + SourceCharacter but not one of ``` or `\` or `$` or LineTerminator + +NotEscapeSequence :: + `0` DecimalDigit + DecimalDigit but not `0` + `x` [lookahead <! HexDigit] + `x` HexDigit [lookahead <! HexDigit] + `u` [lookahead <! HexDigit] [lookahead != `{`] + `u` HexDigit [lookahead <! HexDigit] + `u` HexDigit HexDigit [lookahead <! HexDigit] + `u` HexDigit HexDigit HexDigit [lookahead <! HexDigit] + `u` `{` [lookahead <! HexDigit] + `u` `{` NotCodePoint [lookahead <! HexDigit] + `u` `{` CodePoint [lookahead <! HexDigit] [lookahead != `}`] + +NotCodePoint :: + HexDigits [> but only if MV of |HexDigits| > 0x10FFFF ] + +CodePoint :: + HexDigits [> but only if MV of |HexDigits| ≤ 0x10FFFF ] + + +IdentifierReference[Yield, Await] : + Identifier + [~Yield] `yield` + [~Await] `await` + +BindingIdentifier[Yield, Await] : + Identifier + `yield` + `await` + +LabelIdentifier[Yield, Await] : + Identifier + [~Yield] `yield` + [~Await] `await` + +Identifier : + IdentifierName but not ReservedWord + + +PrimaryExpression[Yield, Await] : + `this` + IdentifierReference[?Yield, ?Await] + Literal + ArrayLiteral[?Yield, ?Await] + ObjectLiteral[?Yield, ?Await] + FunctionExpression + ClassExpression[?Yield, ?Await] + GeneratorExpression + AsyncFunctionExpression + AsyncGeneratorExpression + RegularExpressionLiteral + TemplateLiteral[?Yield, ?Await, ~Tagged] + CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await] #parencover + +CoverParenthesizedExpressionAndArrowParameterList[Yield, Await] : + `(` Expression[+In, ?Yield, ?Await] `)` + `(` Expression[+In, ?Yield, ?Await] `,` `)` + `(` `)` + `(` `...` BindingIdentifier[?Yield, ?Await] `)` + `(` `...` BindingPattern[?Yield, ?Await] `)` + `(` Expression[+In, ?Yield, ?Await] `,` `...` BindingIdentifier[?Yield, ?Await] `)` + `(` Expression[+In, ?Yield, ?Await] `,` `...` BindingPattern[?Yield, ?Await] `)` + + +ParenthesizedExpression[Yield, Await] : + `(` Expression[+In, ?Yield, ?Await] `)` + + +Literal : + NullLiteral + BooleanLiteral + NumericLiteral + StringLiteral + + +ArrayLiteral[Yield, Await] : + `[` Elision? `]` + `[` ElementList[?Yield, ?Await] `]` + `[` ElementList[?Yield, ?Await] `,` Elision? `]` + +ElementList[Yield, Await] : + Elision? AssignmentExpression[+In, ?Yield, ?Await] + Elision? SpreadElement[?Yield, ?Await] + ElementList[?Yield, ?Await] `,` Elision? AssignmentExpression[+In, ?Yield, ?Await] + ElementList[?Yield, ?Await] `,` Elision? SpreadElement[?Yield, ?Await] + +Elision : + `,` + Elision `,` + +SpreadElement[Yield, Await] : + `...` AssignmentExpression[+In, ?Yield, ?Await] + + +ObjectLiteral[Yield, Await] : + `{` `}` + `{` PropertyDefinitionList[?Yield, ?Await] `}` + `{` PropertyDefinitionList[?Yield, ?Await] `,` `}` + +PropertyDefinitionList[Yield, Await] : + PropertyDefinition[?Yield, ?Await] + PropertyDefinitionList[?Yield, ?Await] `,` PropertyDefinition[?Yield, ?Await] + +PropertyDefinition[Yield, Await] : + IdentifierReference[?Yield, ?Await] + CoverInitializedName[?Yield, ?Await] + PropertyName[?Yield, ?Await] `:` AssignmentExpression[+In, ?Yield, ?Await] + MethodDefinition[?Yield, ?Await] + `...` AssignmentExpression[+In, ?Yield, ?Await] + +PropertyName[Yield, Await] : + LiteralPropertyName + ComputedPropertyName[?Yield, ?Await] + +LiteralPropertyName : + IdentifierName + StringLiteral + NumericLiteral + +ComputedPropertyName[Yield, Await] : + `[` AssignmentExpression[+In, ?Yield, ?Await] `]` + +CoverInitializedName[Yield, Await] : + IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await] + +Initializer[In, Yield, Await] : + `=` AssignmentExpression[?In, ?Yield, ?Await] + + +TemplateLiteral[Yield, Await, Tagged] : + NoSubstitutionTemplate + SubstitutionTemplate[?Yield, ?Await, ?Tagged] + +SubstitutionTemplate[Yield, Await, Tagged] : + TemplateHead Expression[+In, ?Yield, ?Await] TemplateSpans[?Yield, ?Await, ?Tagged] + +TemplateSpans[Yield, Await, Tagged] : + TemplateTail + TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateTail + +TemplateMiddleList[Yield, Await, Tagged] : + TemplateMiddle Expression[+In, ?Yield, ?Await] + TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateMiddle Expression[+In, ?Yield, ?Await] + + +MemberExpression[Yield, Await] : + PrimaryExpression[?Yield, ?Await] + MemberExpression[?Yield, ?Await] `[` Expression[+In, ?Yield, ?Await] `]` + MemberExpression[?Yield, ?Await] `.` IdentifierName + MemberExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] + SuperProperty[?Yield, ?Await] + MetaProperty + `new` MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await] + +SuperProperty[Yield, Await] : + `super` `[` Expression[+In, ?Yield, ?Await] `]` + `super` `.` IdentifierName + +MetaProperty : + NewTarget + +NewTarget : + `new` `.` `target` + +NewExpression[Yield, Await] : + MemberExpression[?Yield, ?Await] + `new` NewExpression[?Yield, ?Await] + +CallExpression[Yield, Await] : + CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] #callcover + SuperCall[?Yield, ?Await] + ImportCall[?Yield, ?Await] + CallExpression[?Yield, ?Await] Arguments[?Yield, ?Await] + CallExpression[?Yield, ?Await] `[` Expression[+In, ?Yield, ?Await] `]` + CallExpression[?Yield, ?Await] `.` IdentifierName + CallExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] + +SuperCall[Yield, Await] : + `super` Arguments[?Yield, ?Await] + +ImportCall[Yield, Await] : + `import` `(` AssignmentExpression[+In, ?Yield, ?Await] `)` + +Arguments[Yield, Await] : + `(` `)` + `(` ArgumentList[?Yield, ?Await] `)` + `(` ArgumentList[?Yield, ?Await] `,` `)` + +ArgumentList[Yield, Await] : + AssignmentExpression[+In, ?Yield, ?Await] + `...` AssignmentExpression[+In, ?Yield, ?Await] + ArgumentList[?Yield, ?Await] `,` AssignmentExpression[+In, ?Yield, ?Await] + ArgumentList[?Yield, ?Await] `,` `...` AssignmentExpression[+In, ?Yield, ?Await] + +LeftHandSideExpression[Yield, Await] : + NewExpression[?Yield, ?Await] + CallExpression[?Yield, ?Await] + + +CallMemberExpression[Yield, Await] : + MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await] + + +UpdateExpression[Yield, Await] : + LeftHandSideExpression[?Yield, ?Await] + LeftHandSideExpression[?Yield, ?Await] `++` + LeftHandSideExpression[?Yield, ?Await] `--` + `++` UnaryExpression[?Yield, ?Await] + `--` UnaryExpression[?Yield, ?Await] + + +UnaryExpression[Yield, Await] : + UpdateExpression[?Yield, ?Await] + `delete` UnaryExpression[?Yield, ?Await] + `void` UnaryExpression[?Yield, ?Await] + `typeof` UnaryExpression[?Yield, ?Await] + `+` UnaryExpression[?Yield, ?Await] + `-` UnaryExpression[?Yield, ?Await] + `~` UnaryExpression[?Yield, ?Await] + `!` UnaryExpression[?Yield, ?Await] + [+Await] AwaitExpression[?Yield] + + +ExponentiationExpression[Yield, Await] : + UnaryExpression[?Yield, ?Await] + UpdateExpression[?Yield, ?Await] `**` ExponentiationExpression[?Yield, ?Await] + + +MultiplicativeExpression[Yield, Await] : + ExponentiationExpression[?Yield, ?Await] + MultiplicativeExpression[?Yield, ?Await] MultiplicativeOperator ExponentiationExpression[?Yield, ?Await] + +MultiplicativeOperator : one of + `*` `/` `%` + + +AdditiveExpression[Yield, Await] : + MultiplicativeExpression[?Yield, ?Await] + AdditiveExpression[?Yield, ?Await] `+` MultiplicativeExpression[?Yield, ?Await] + AdditiveExpression[?Yield, ?Await] `-` MultiplicativeExpression[?Yield, ?Await] + + +ShiftExpression[Yield, Await] : + AdditiveExpression[?Yield, ?Await] + ShiftExpression[?Yield, ?Await] `<<` AdditiveExpression[?Yield, ?Await] + ShiftExpression[?Yield, ?Await] `>>` AdditiveExpression[?Yield, ?Await] + ShiftExpression[?Yield, ?Await] `>>>` AdditiveExpression[?Yield, ?Await] + + +RelationalExpression[In, Yield, Await] : + ShiftExpression[?Yield, ?Await] + RelationalExpression[?In, ?Yield, ?Await] `<` ShiftExpression[?Yield, ?Await] + RelationalExpression[?In, ?Yield, ?Await] `>` ShiftExpression[?Yield, ?Await] + RelationalExpression[?In, ?Yield, ?Await] `<=` ShiftExpression[?Yield, ?Await] + RelationalExpression[?In, ?Yield, ?Await] `>=` ShiftExpression[?Yield, ?Await] + RelationalExpression[?In, ?Yield, ?Await] `instanceof` ShiftExpression[?Yield, ?Await] + [+In] RelationalExpression[+In, ?Yield, ?Await] `in` ShiftExpression[?Yield, ?Await] + + +EqualityExpression[In, Yield, Await] : + RelationalExpression[?In, ?Yield, ?Await] + EqualityExpression[?In, ?Yield, ?Await] `==` RelationalExpression[?In, ?Yield, ?Await] + EqualityExpression[?In, ?Yield, ?Await] `!=` RelationalExpression[?In, ?Yield, ?Await] + EqualityExpression[?In, ?Yield, ?Await] `===` RelationalExpression[?In, ?Yield, ?Await] + EqualityExpression[?In, ?Yield, ?Await] `!==` RelationalExpression[?In, ?Yield, ?Await] + + +BitwiseANDExpression[In, Yield, Await] : + EqualityExpression[?In, ?Yield, ?Await] + BitwiseANDExpression[?In, ?Yield, ?Await] `&` EqualityExpression[?In, ?Yield, ?Await] + +BitwiseXORExpression[In, Yield, Await] : + BitwiseANDExpression[?In, ?Yield, ?Await] + BitwiseXORExpression[?In, ?Yield, ?Await] `^` BitwiseANDExpression[?In, ?Yield, ?Await] + +BitwiseORExpression[In, Yield, Await] : + BitwiseXORExpression[?In, ?Yield, ?Await] + BitwiseORExpression[?In, ?Yield, ?Await] `|` BitwiseXORExpression[?In, ?Yield, ?Await] + + +LogicalANDExpression[In, Yield, Await] : + BitwiseORExpression[?In, ?Yield, ?Await] + LogicalANDExpression[?In, ?Yield, ?Await] `&&` BitwiseORExpression[?In, ?Yield, ?Await] + +LogicalORExpression[In, Yield, Await] : + LogicalANDExpression[?In, ?Yield, ?Await] + LogicalORExpression[?In, ?Yield, ?Await] `||` LogicalANDExpression[?In, ?Yield, ?Await] + + +ConditionalExpression[In, Yield, Await] : + LogicalORExpression[?In, ?Yield, ?Await] + LogicalORExpression[?In, ?Yield, ?Await] `?` AssignmentExpression[+In, ?Yield, ?Await] `:` AssignmentExpression[?In, ?Yield, ?Await] + + +AssignmentExpression[In, Yield, Await] : + ConditionalExpression[?In, ?Yield, ?Await] + [+Yield] YieldExpression[?In, ?Await] + ArrowFunction[?In, ?Yield, ?Await] + AsyncArrowFunction[?In, ?Yield, ?Await] + LeftHandSideExpression[?Yield, ?Await] `=` AssignmentExpression[?In, ?Yield, ?Await] #assignment + LeftHandSideExpression[?Yield, ?Await] AssignmentOperator AssignmentExpression[?In, ?Yield, ?Await] + +AssignmentOperator : one of + `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `>>>=` `&=` `^=` `|=` `**=` + + +AssignmentPattern[Yield, Await] : + ObjectAssignmentPattern[?Yield, ?Await] + ArrayAssignmentPattern[?Yield, ?Await] + +ObjectAssignmentPattern[Yield, Await] : + `{` `}` + `{` AssignmentRestProperty[?Yield, ?Await] `}` + `{` AssignmentPropertyList[?Yield, ?Await] `}` + `{` AssignmentPropertyList[?Yield, ?Await] `,` AssignmentRestProperty[?Yield, ?Await]? `}` + +ArrayAssignmentPattern[Yield, Await] : + `[` Elision? AssignmentRestElement[?Yield, ?Await]? `]` + `[` AssignmentElementList[?Yield, ?Await] `]` + `[` AssignmentElementList[?Yield, ?Await] `,` Elision? AssignmentRestElement[?Yield, ?Await]? `]` + +AssignmentRestProperty[Yield, Await] : + `...` DestructuringAssignmentTarget[?Yield, ?Await] + +AssignmentPropertyList[Yield, Await] : + AssignmentProperty[?Yield, ?Await] + AssignmentPropertyList[?Yield, ?Await] `,` AssignmentProperty[?Yield, ?Await] + +AssignmentElementList[Yield, Await] : + AssignmentElisionElement[?Yield, ?Await] + AssignmentElementList[?Yield, ?Await] `,` AssignmentElisionElement[?Yield, ?Await] + +AssignmentElisionElement[Yield, Await] : + Elision? AssignmentElement[?Yield, ?Await] + +AssignmentProperty[Yield, Await] : + IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]? + PropertyName[?Yield, ?Await] `:` AssignmentElement[?Yield, ?Await] + +AssignmentElement[Yield, Await] : + DestructuringAssignmentTarget[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]? + +AssignmentRestElement[Yield, Await] : + `...` DestructuringAssignmentTarget[?Yield, ?Await] + +DestructuringAssignmentTarget[Yield, Await] : + LeftHandSideExpression[?Yield, ?Await] + + +Expression[In, Yield, Await] : + AssignmentExpression[?In, ?Yield, ?Await] + Expression[?In, ?Yield, ?Await] `,` AssignmentExpression[?In, ?Yield, ?Await] + + +Statement[Yield, Await, Return] : + BlockStatement[?Yield, ?Await, ?Return] + VariableStatement[?Yield, ?Await] + EmptyStatement + ExpressionStatement[?Yield, ?Await] + IfStatement[?Yield, ?Await, ?Return] + BreakableStatement[?Yield, ?Await, ?Return] + ContinueStatement[?Yield, ?Await] + BreakStatement[?Yield, ?Await] + [+Return] ReturnStatement[?Yield, ?Await] + WithStatement[?Yield, ?Await, ?Return] + LabelledStatement[?Yield, ?Await, ?Return] + ThrowStatement[?Yield, ?Await] + TryStatement[?Yield, ?Await, ?Return] + DebuggerStatement + +Declaration[Yield, Await] : + HoistableDeclaration[?Yield, ?Await, ~Default] + ClassDeclaration[?Yield, ?Await, ~Default] + LexicalDeclaration[+In, ?Yield, ?Await] + +HoistableDeclaration[Yield, Await, Default] : + FunctionDeclaration[?Yield, ?Await, ?Default] + GeneratorDeclaration[?Yield, ?Await, ?Default] + AsyncFunctionDeclaration[?Yield, ?Await, ?Default] + AsyncGeneratorDeclaration[?Yield, ?Await, ?Default] + +BreakableStatement[Yield, Await, Return] : + IterationStatement[?Yield, ?Await, ?Return] + SwitchStatement[?Yield, ?Await, ?Return] + + +BlockStatement[Yield, Await, Return] : + Block[?Yield, ?Await, ?Return] + +Block[Yield, Await, Return] : + `{` StatementList[?Yield, ?Await, ?Return]? `}` + +StatementList[Yield, Await, Return] : + StatementListItem[?Yield, ?Await, ?Return] + StatementList[?Yield, ?Await, ?Return] StatementListItem[?Yield, ?Await, ?Return] + +StatementListItem[Yield, Await, Return] : + Statement[?Yield, ?Await, ?Return] + Declaration[?Yield, ?Await] + + +LexicalDeclaration[In, Yield, Await] : + LetOrConst BindingList[?In, ?Yield, ?Await] `;` + +LetOrConst : + `let` + `const` + +BindingList[In, Yield, Await] : + LexicalBinding[?In, ?Yield, ?Await] + BindingList[?In, ?Yield, ?Await] `,` LexicalBinding[?In, ?Yield, ?Await] + +LexicalBinding[In, Yield, Await] : + BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]? + BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await] + + +VariableStatement[Yield, Await] : + `var` VariableDeclarationList[+In, ?Yield, ?Await] `;` + +VariableDeclarationList[In, Yield, Await] : + VariableDeclaration[?In, ?Yield, ?Await] + VariableDeclarationList[?In, ?Yield, ?Await] `,` VariableDeclaration[?In, ?Yield, ?Await] + +VariableDeclaration[In, Yield, Await] : + BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]? + BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await] + + +BindingPattern[Yield, Await] : + ObjectBindingPattern[?Yield, ?Await] + ArrayBindingPattern[?Yield, ?Await] + +ObjectBindingPattern[Yield, Await] : + `{` `}` + `{` BindingRestProperty[?Yield, ?Await] `}` + `{` BindingPropertyList[?Yield, ?Await] `}` + `{` BindingPropertyList[?Yield, ?Await] `,` BindingRestProperty[?Yield, ?Await]? `}` + +ArrayBindingPattern[Yield, Await] : + `[` Elision? BindingRestElement[?Yield, ?Await]? `]` + `[` BindingElementList[?Yield, ?Await] `]` + `[` BindingElementList[?Yield, ?Await] `,` Elision? BindingRestElement[?Yield, ?Await]? `]` + +BindingRestProperty[Yield, Await] : + `...` BindingIdentifier[?Yield, ?Await] + +BindingPropertyList[Yield, Await] : + BindingProperty[?Yield, ?Await] + BindingPropertyList[?Yield, ?Await] `,` BindingProperty[?Yield, ?Await] + +BindingElementList[Yield, Await] : + BindingElisionElement[?Yield, ?Await] + BindingElementList[?Yield, ?Await] `,` BindingElisionElement[?Yield, ?Await] + +BindingElisionElement[Yield, Await] : + Elision? BindingElement[?Yield, ?Await] + +BindingProperty[Yield, Await] : + SingleNameBinding[?Yield, ?Await] + PropertyName[?Yield, ?Await] `:` BindingElement[?Yield, ?Await] + +BindingElement[Yield, Await] : + SingleNameBinding[?Yield, ?Await] + BindingPattern[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]? + +SingleNameBinding[Yield, Await] : + BindingIdentifier[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]? + +BindingRestElement[Yield, Await] : + `...` BindingIdentifier[?Yield, ?Await] + `...` BindingPattern[?Yield, ?Await] + + +EmptyStatement : + `;` + + +ExpressionStatement[Yield, Await] : + [lookahead <! {`{`, `function`, `async`, `class`, `let`}] Expression[+In, ?Yield, ?Await] `;` + + +IfStatement[Yield, Await, Return] : + `if` `(` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] `else` Statement[?Yield, ?Await, ?Return] + `if` `(` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + + +IterationStatement[Yield, Await, Return] : + `do` Statement[?Yield, ?Await, ?Return] `while` `(` Expression[+In, ?Yield, ?Await] `)` `;` + `while` `(` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + `for` `(` [lookahead != `let`] Expression[~In, ?Yield, ?Await]? `;` Expression[+In, ?Yield, ?Await]? `;` Expression[+In, ?Yield, ?Await]? `)` Statement[?Yield, ?Await, ?Return] + `for` `(` `var` VariableDeclarationList[~In, ?Yield, ?Await] `;` Expression[+In, ?Yield, ?Await]? `;` Expression[+In, ?Yield, ?Await]? `)` Statement[?Yield, ?Await, ?Return] + `for` `(` ForLexicalDeclaration[~In, ?Yield, ?Await] Expression[+In, ?Yield, ?Await]? `;` Expression[+In, ?Yield, ?Await]? `)` Statement[?Yield, ?Await, ?Return] + `for` `(` [lookahead != `let`] LeftHandSideExpression[?Yield, ?Await] `in` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + `for` `(` `var` ForBinding[?Yield, ?Await] `in` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + `for` `(` ForDeclaration[?Yield, ?Await] `in` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + `for` `(` [lookahead <! {`async`, `let`} ] LeftHandSideExpression[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + `for` `(` `var` ForBinding[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + `for` `(` ForDeclaration[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + [+Await] `for` `await` `(` [lookahead <! {`async`, `let`} ] LeftHandSideExpression[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + [+Await] `for` `await` `(` `var` ForBinding[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + [+Await] `for` `await` `(` ForDeclaration[?Yield, ?Await] `of` AssignmentExpression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + +ForDeclaration[Yield, Await] : + LetOrConst ForBinding[?Yield, ?Await] + +ForBinding[Yield, Await] : + BindingIdentifier[?Yield, ?Await] + BindingPattern[?Yield, ?Await] + + +ContinueStatement[Yield, Await] : + `continue` `;` + `continue` LabelIdentifier[?Yield, ?Await] `;` + + +BreakStatement[Yield, Await] : + `break` `;` + `break` LabelIdentifier[?Yield, ?Await] `;` + + +ReturnStatement[Yield, Await] : + `return` `;` + `return` Expression[+In, ?Yield, ?Await] `;` + + +WithStatement[Yield, Await, Return] : + `with` `(` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + + +SwitchStatement[Yield, Await, Return] : + `switch` `(` Expression[+In, ?Yield, ?Await] `)` CaseBlock[?Yield, ?Await, ?Return] + +CaseBlock[Yield, Await, Return] : + `{` CaseClauses[?Yield, ?Await, ?Return]? `}` + `{` CaseClauses[?Yield, ?Await, ?Return]? DefaultClause[?Yield, ?Await, ?Return] CaseClauses[?Yield, ?Await, ?Return]? `}` + +CaseClauses[Yield, Await, Return] : + CaseClause[?Yield, ?Await, ?Return] + CaseClauses[?Yield, ?Await, ?Return] CaseClause[?Yield, ?Await, ?Return] + +CaseClause[Yield, Await, Return] : + `case` Expression[+In, ?Yield, ?Await] `:` StatementList[?Yield, ?Await, ?Return]? + +DefaultClause[Yield, Await, Return] : + `default` `:` StatementList[?Yield, ?Await, ?Return]? + + +LabelledStatement[Yield, Await, Return] : + LabelIdentifier[?Yield, ?Await] `:` LabelledItem[?Yield, ?Await, ?Return] + +LabelledItem[Yield, Await, Return] : + Statement[?Yield, ?Await, ?Return] + FunctionDeclaration[?Yield, ?Await, ~Default] + + +ThrowStatement[Yield, Await] : + `throw` Expression[+In, ?Yield, ?Await] `;` + + +TryStatement[Yield, Await, Return] : + `try` Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] + `try` Block[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] + `try` Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] + +Catch[Yield, Await, Return] : + `catch` `(` CatchParameter[?Yield, ?Await] `)` Block[?Yield, ?Await, ?Return] + `catch` Block[?Yield, ?Await, ?Return] + +Finally[Yield, Await, Return] : + `finally` Block[?Yield, ?Await, ?Return] + +CatchParameter[Yield, Await] : + BindingIdentifier[?Yield, ?Await] + BindingPattern[?Yield, ?Await] + + +DebuggerStatement : + `debugger` `;` + + +FunctionDeclaration[Yield, Await, Default] : + `function` BindingIdentifier[?Yield, ?Await] `(` FormalParameters[~Yield, ~Await] `)` `{` FunctionBody[~Yield, ~Await] `}` + [+Default] `function` `(` FormalParameters[~Yield, ~Await] `)` `{` FunctionBody[~Yield, ~Await] `}` + +FunctionExpression : + `function` BindingIdentifier[~Yield, ~Await]? `(` FormalParameters[~Yield, ~Await] `)` `{` FunctionBody[~Yield, ~Await] `}` + +UniqueFormalParameters[Yield, Await] : + FormalParameters[?Yield, ?Await] + +FormalParameters[Yield, Await] : + [empty] + FunctionRestParameter[?Yield, ?Await] + FormalParameterList[?Yield, ?Await] + FormalParameterList[?Yield, ?Await] `,` + FormalParameterList[?Yield, ?Await] `,` FunctionRestParameter[?Yield, ?Await] + +FormalParameterList[Yield, Await] : + FormalParameter[?Yield, ?Await] + FormalParameterList[?Yield, ?Await] `,` FormalParameter[?Yield, ?Await] + +FunctionRestParameter[Yield, Await] : + BindingRestElement[?Yield, ?Await] + +FormalParameter[Yield, Await] : + BindingElement[?Yield, ?Await] + +FunctionBody[Yield, Await] : + FunctionStatementList[?Yield, ?Await] + +FunctionStatementList[Yield, Await] : + StatementList[?Yield, ?Await, +Return]? + + +ArrowFunction[In, Yield, Await] : + ArrowParameters[?Yield, ?Await] `=>` ConciseBody[?In] + +ArrowParameters[Yield, Await] : + BindingIdentifier[?Yield, ?Await] + CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await] #parencover + +ConciseBody[In] : + [lookahead != `{` ] AssignmentExpression[?In, ~Yield, ~Await] + `{` FunctionBody[~Yield, ~Await] `}` + + +ArrowFormalParameters[Yield, Await] : + `(` UniqueFormalParameters[?Yield, ?Await] `)` + + +MethodDefinition[Yield, Await] : + PropertyName[?Yield, ?Await] `(` UniqueFormalParameters[~Yield, ~Await] `)` `{` FunctionBody[~Yield, ~Await] `}` + GeneratorMethod[?Yield, ?Await] + AsyncMethod[?Yield, ?Await] + AsyncGeneratorMethod[?Yield, ?Await] + `get` PropertyName[?Yield, ?Await] `(` `)` `{` FunctionBody[~Yield, ~Await] `}` + `set` PropertyName[?Yield, ?Await] `(` PropertySetParameterList `)` `{` FunctionBody[~Yield, ~Await] `}` + +PropertySetParameterList : + FormalParameter[~Yield, ~Await] + + +GeneratorMethod[Yield, Await] : + `*` PropertyName[?Yield, ?Await] `(` UniqueFormalParameters[+Yield, ~Await] `)` `{` GeneratorBody `}` + +GeneratorDeclaration[Yield, Await, Default] : + `function` `*` BindingIdentifier[?Yield, ?Await] `(` FormalParameters[+Yield, ~Await] `)` `{` GeneratorBody `}` + [+Default] `function` `*` `(` FormalParameters[+Yield, ~Await] `)` `{` GeneratorBody `}` + +GeneratorExpression : + `function` `*` BindingIdentifier[+Yield, ~Await]? `(` FormalParameters[+Yield, ~Await] `)` `{` GeneratorBody `}` + +GeneratorBody : + FunctionBody[+Yield, ~Await] + +YieldExpression[In, Await] : + `yield` + `yield` AssignmentExpression[?In, +Yield, ?Await] + `yield` `*` AssignmentExpression[?In, +Yield, ?Await] + + +AsyncGeneratorMethod[Yield, Await] : + `async` `*` PropertyName[?Yield, ?Await] `(` UniqueFormalParameters[+Yield, +Await] `)` `{` AsyncGeneratorBody `}` + +AsyncGeneratorDeclaration[Yield, Await, Default] : + `async` `function` `*` BindingIdentifier[?Yield, ?Await] `(` FormalParameters[+Yield, +Await] `)` `{` AsyncGeneratorBody `}` + [+Default] `async` `function` `*` `(` FormalParameters[+Yield, +Await] `)` `{` AsyncGeneratorBody `}` + +AsyncGeneratorExpression : + `async` `function` `*` BindingIdentifier[+Yield, +Await]? `(` FormalParameters[+Yield, +Await] `)` `{` AsyncGeneratorBody `}` + +AsyncGeneratorBody : + FunctionBody[+Yield, +Await] + + +ClassDeclaration[Yield, Await, Default] : + `class` BindingIdentifier[?Yield, ?Await] ClassTail[?Yield, ?Await] + [+Default] `class` ClassTail[?Yield, ?Await] + +ClassExpression[Yield, Await] : + `class` BindingIdentifier[?Yield, ?Await]? ClassTail[?Yield, ?Await] + +ClassTail[Yield, Await] : + ClassHeritage[?Yield, ?Await]? `{` ClassBody[?Yield, ?Await]? `}` + +ClassHeritage[Yield, Await] : + `extends` LeftHandSideExpression[?Yield, ?Await] + +ClassBody[Yield, Await] : + ClassElementList[?Yield, ?Await] + +ClassElementList[Yield, Await] : + ClassElement[?Yield, ?Await] + ClassElementList[?Yield, ?Await] ClassElement[?Yield, ?Await] + +ClassElement[Yield, Await] : + MethodDefinition[?Yield, ?Await] + `static` MethodDefinition[?Yield, ?Await] + `;` + + +AsyncFunctionDeclaration[Yield, Await, Default] : + `async` `function` BindingIdentifier[?Yield, ?Await] `(` FormalParameters[~Yield, +Await] `)` `{` AsyncFunctionBody `}` + [+Default] `async` `function` `(` FormalParameters[~Yield, +Await] `)` `{` AsyncFunctionBody `}` + +AsyncFunctionExpression : + `async` `function` `(` FormalParameters[~Yield, +Await] `)` `{` AsyncFunctionBody `}` + `async` `function` BindingIdentifier[~Yield, +Await] `(` FormalParameters[~Yield, +Await] `)` `{` AsyncFunctionBody `}` + +AsyncMethod[Yield, Await] : + `async` PropertyName[?Yield, ?Await] `(` UniqueFormalParameters[~Yield, +Await] `)` `{` AsyncFunctionBody `}` + +AsyncFunctionBody : + FunctionBody[~Yield, +Await] + +AwaitExpression[Yield] : + `await` UnaryExpression[?Yield, +Await] + + +AsyncArrowFunction[In, Yield, Await] : + `async` AsyncArrowBindingIdentifier[?Yield] `=>` AsyncConciseBody[?In] + CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] `=>` AsyncConciseBody[?In] #callcover + +AsyncConciseBody[In] : + [lookahead != `{`] AssignmentExpression[?In, ~Yield, +Await] + `{` AsyncFunctionBody `}` + +AsyncArrowBindingIdentifier[Yield] : + BindingIdentifier[?Yield, +Await] + +CoverCallExpressionAndAsyncArrowHead[Yield, Await] : + MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await] + + +AsyncArrowHead : + `async` ArrowFormalParameters[~Yield, +Await] + + +Script : + ScriptBody? + +ScriptBody : + StatementList[~Yield, ~Await, ~Return] + + +Module : + ModuleBody? + +ModuleBody : + ModuleItemList + +ModuleItemList : + ModuleItem + ModuleItemList ModuleItem + +ModuleItem : + ImportDeclaration + ExportDeclaration + StatementListItem[~Yield, ~Await, ~Return] + + +ImportDeclaration : + `import` ImportClause FromClause `;` + `import` ModuleSpecifier `;` + +ImportClause : + ImportedDefaultBinding + NameSpaceImport + NamedImports + ImportedDefaultBinding `,` NameSpaceImport + ImportedDefaultBinding `,` NamedImports + +ImportedDefaultBinding : + ImportedBinding + +NameSpaceImport : + `*` `as` ImportedBinding + +NamedImports : + `{` `}` + `{` ImportsList `}` + `{` ImportsList `,` `}` + +FromClause : + `from` ModuleSpecifier + +ImportsList : + ImportSpecifier + ImportsList `,` ImportSpecifier + +ImportSpecifier : + ImportedBinding + IdentifierName `as` ImportedBinding + +ModuleSpecifier : + StringLiteral + +ImportedBinding : + BindingIdentifier[~Yield, ~Await] + + +ExportDeclaration : + `export` `*` FromClause `;` + `export` ExportClause FromClause `;` + `export` ExportClause `;` + `export` VariableStatement[~Yield, ~Await] + `export` Declaration[~Yield, ~Await] + `export` `default` HoistableDeclaration[~Yield, ~Await, +Default] + `export` `default` ClassDeclaration[~Yield, ~Await, +Default] + `export` `default` [lookahead <! {`function`, `async`, `class`}] AssignmentExpression[+In, ~Yield, ~Await] `;` + +ExportClause : + `{` `}` + `{` ExportsList `}` + `{` ExportsList `,` `}` + +ExportsList : + ExportSpecifier + ExportsList `,` ExportSpecifier + +ExportSpecifier : + IdentifierName + IdentifierName `as` IdentifierName + + +uri ::: + uriCharacters? + +uriCharacters ::: + uriCharacter uriCharacters? + +uriCharacter ::: + uriReserved + uriUnescaped + uriEscaped + +uriReserved ::: one of + `;` `/` `?` `:` `@` `&` `=` `+` `$` `,` + +uriUnescaped ::: + uriAlpha + DecimalDigit + uriMark + +uriEscaped ::: + `%` HexDigit HexDigit + +uriAlpha ::: one of + `a` `b` `c` `d` `e` `f` `g` `h` `i` `j` `k` `l` `m` `n` `o` `p` `q` `r` `s` `t` `u` `v` `w` `x` `y` `z` + `A` `B` `C` `D` `E` `F` `G` `H` `I` `J` `K` `L` `M` `N` `O` `P` `Q` `R` `S` `T` `U` `V` `W` `X` `Y` `Z` + +uriMark ::: one of + `-` `_` `.` `!` `~` `*` `'` `(` `)` + + +NativeFunction : + `function` PropertyName[~Yield, ~Await]? `(` FormalParameters[~Yield, ~Await] `)` `{` `[` `native` `code` `]` `}` + + +Pattern[U, N] :: + Disjunction[?U, ?N] + +Disjunction[U, N] :: + Alternative[?U, ?N] + Alternative[?U, ?N] `|` Disjunction[?U, ?N] + +Alternative[U, N] :: + [empty] + Alternative[?U, ?N] Term[?U, ?N] + +Term[U, N] :: + Assertion[?U, ?N] + Atom[?U, ?N] + Atom[?U, ?N] Quantifier + +Assertion[U, N] :: + `^` + `$` + `\` `b` + `\` `B` + `(` `?` `=` Disjunction[?U, ?N] `)` + `(` `?` `!` Disjunction[?U, ?N] `)` + `(` `?` `<=` Disjunction[?U, ?N] `)` + `(` `?` `<!` Disjunction[?U, ?N] `)` + +Quantifier :: + QuantifierPrefix + QuantifierPrefix `?` + +QuantifierPrefix :: + `*` + `+` + `?` + `{` DecimalDigits `}` + `{` DecimalDigits `,` `}` + `{` DecimalDigits `,` DecimalDigits `}` + +Atom[U, N] :: + PatternCharacter + `.` + `\` AtomEscape[?U, ?N] + CharacterClass[?U] + `(` GroupSpecifier[?U] Disjunction[?U, ?N] `)` + `(` `?` `:` Disjunction[?U, ?N] `)` + +SyntaxCharacter :: one of + `^` `$` `\` `.` `*` `+` `?` `(` `)` `[` `]` `{` `}` `|` + +PatternCharacter :: + SourceCharacter but not SyntaxCharacter + +AtomEscape[U, N] :: + DecimalEscape + CharacterClassEscape[?U] + CharacterEscape[?U] + [+N] `k` GroupName[?U] + +CharacterEscape[U] :: + ControlEscape + `c` ControlLetter + `0` [lookahead <! DecimalDigit] + HexEscapeSequence + RegExpUnicodeEscapeSequence[?U] + IdentityEscape[?U] + +ControlEscape :: one of + `f` `n` `r` `t` `v` + +ControlLetter :: one of + `a` `b` `c` `d` `e` `f` `g` `h` `i` `j` `k` `l` `m` `n` `o` `p` `q` `r` `s` `t` `u` `v` `w` `x` `y` `z` + `A` `B` `C` `D` `E` `F` `G` `H` `I` `J` `K` `L` `M` `N` `O` `P` `Q` `R` `S` `T` `U` `V` `W` `X` `Y` `Z` + +GroupSpecifier[U] :: + [empty] + `?` GroupName[?U] + +GroupName[U] :: + `<` RegExpIdentifierName[?U] `>` + +RegExpIdentifierName[U] :: + RegExpIdentifierStart[?U] + RegExpIdentifierName[?U] RegExpIdentifierPart[?U] + +RegExpIdentifierStart[U] :: + UnicodeIDStart + `$` + `_` + `\` RegExpUnicodeEscapeSequence[?U] + +RegExpIdentifierPart[U] :: + UnicodeIDContinue + `$` + `\` RegExpUnicodeEscapeSequence[?U] + <ZWNJ> + <ZWJ> + +RegExpUnicodeEscapeSequence[U] :: + [+U] `u` LeadSurrogate `\u` TrailSurrogate + [+U] `u` LeadSurrogate + [+U] `u` TrailSurrogate + [+U] `u` NonSurrogate + [~U] `u` Hex4Digits + [+U] `u{` CodePoint `}` + + +LeadSurrogate :: + Hex4Digits [> but only if the SV of |Hex4Digits| is in the inclusive range 0xD800 to 0xDBFF] + +TrailSurrogate :: + Hex4Digits [> but only if the SV of |Hex4Digits| is in the inclusive range 0xDC00 to 0xDFFF] + +NonSurrogate :: + Hex4Digits [> but only if the SV of |Hex4Digits| is not in the inclusive range 0xD800 to 0xDFFF] + +IdentityEscape[U] :: + [+U] SyntaxCharacter + [+U] `/` + [~U] SourceCharacter but not UnicodeIDContinue + +DecimalEscape :: + NonZeroDigit DecimalDigits? [lookahead <! DecimalDigit] + +CharacterClassEscape[U] :: + `d` + `D` + `s` + `S` + `w` + `W` + [+U] `p{` UnicodePropertyValueExpression `}` + [+U] `P{` UnicodePropertyValueExpression `}` + +UnicodePropertyValueExpression :: + UnicodePropertyName `=` UnicodePropertyValue + LoneUnicodePropertyNameOrValue + +UnicodePropertyName :: + UnicodePropertyNameCharacters + +UnicodePropertyNameCharacters :: + UnicodePropertyNameCharacter UnicodePropertyNameCharacters? + +UnicodePropertyValue :: + UnicodePropertyValueCharacters + +LoneUnicodePropertyNameOrValue :: + UnicodePropertyValueCharacters + +UnicodePropertyValueCharacters :: + UnicodePropertyValueCharacter UnicodePropertyValueCharacters? + +UnicodePropertyValueCharacter :: + UnicodePropertyNameCharacter + `0` + `1` + `2` + `3` + `4` + `5` + `6` + `7` + `8` + `9` + +UnicodePropertyNameCharacter :: + ControlLetter + `_` + +CharacterClass[U] :: + `[` [lookahead != `^`] ClassRanges[?U] `]` + `[` `^` ClassRanges[?U] `]` + +ClassRanges[U] :: + [empty] + NonemptyClassRanges[?U] + +NonemptyClassRanges[U] :: + ClassAtom[?U] + ClassAtom[?U] NonemptyClassRangesNoDash[?U] + ClassAtom[?U] `-` ClassAtom[?U] ClassRanges[?U] + +NonemptyClassRangesNoDash[U] :: + ClassAtom[?U] + ClassAtomNoDash[?U] NonemptyClassRangesNoDash[?U] + ClassAtomNoDash[?U] `-` ClassAtom[?U] ClassRanges[?U] + +ClassAtom[U] :: + `-` + ClassAtomNoDash[?U] + +ClassAtomNoDash[U] :: + SourceCharacter but not one of `\` or `]` or `-` + `\` ClassEscape[?U] + +ClassEscape[U] :: + `b` + [+U] `-` + CharacterClassEscape[?U] + CharacterEscape[?U] + + +NumericLiteral :: + DecimalLiteral + BinaryIntegerLiteral + OctalIntegerLiteral + HexIntegerLiteral + LegacyOctalIntegerLiteral + +LegacyOctalIntegerLiteral :: + `0` OctalDigit + LegacyOctalIntegerLiteral OctalDigit + +DecimalIntegerLiteral :: + `0` + NonZeroDigit DecimalDigits? + NonOctalDecimalIntegerLiteral + +NonOctalDecimalIntegerLiteral :: + `0` NonOctalDigit + LegacyOctalLikeDecimalIntegerLiteral NonOctalDigit + NonOctalDecimalIntegerLiteral DecimalDigit + +LegacyOctalLikeDecimalIntegerLiteral :: + `0` OctalDigit + LegacyOctalLikeDecimalIntegerLiteral OctalDigit + +NonOctalDigit :: one of + `8` `9` + + +EscapeSequence :: + CharacterEscapeSequence + LegacyOctalEscapeSequence + HexEscapeSequence + UnicodeEscapeSequence + +LegacyOctalEscapeSequence :: + OctalDigit [lookahead <! OctalDigit] + ZeroToThree OctalDigit [lookahead <! OctalDigit] + FourToSeven OctalDigit + ZeroToThree OctalDigit OctalDigit + +ZeroToThree :: one of + `0` `1` `2` `3` + +FourToSeven :: one of + `4` `5` `6` `7` + + +Comment :: + MultiLineComment + SingleLineComment + SingleLineHTMLOpenComment + SingleLineHTMLCloseComment + SingleLineDelimitedComment + +MultiLineComment :: + `/*` FirstCommentLine? LineTerminator MultiLineCommentChars? `*/` HTMLCloseComment? + +FirstCommentLine :: + SingleLineDelimitedCommentChars + +SingleLineHTMLOpenComment :: + `<!--` SingleLineCommentChars? + +SingleLineHTMLCloseComment :: + LineTerminatorSequence HTMLCloseComment + +SingleLineDelimitedComment :: + `/*` SingleLineDelimitedCommentChars? `*/` + +HTMLCloseComment :: + WhiteSpaceSequence? SingleLineDelimitedCommentSequence? `-->` SingleLineCommentChars? + +SingleLineDelimitedCommentChars :: + SingleLineNotAsteriskChar SingleLineDelimitedCommentChars? + `*` SingleLinePostAsteriskCommentChars? + +SingleLineNotAsteriskChar :: + SourceCharacter but not one of `*` or LineTerminator + +SingleLinePostAsteriskCommentChars :: + SingleLineNotForwardSlashOrAsteriskChar SingleLineDelimitedCommentChars? + `*` SingleLinePostAsteriskCommentChars? + +SingleLineNotForwardSlashOrAsteriskChar :: + SourceCharacter but not one of `/` or `*` or LineTerminator + +WhiteSpaceSequence :: + WhiteSpace WhiteSpaceSequence? + +SingleLineDelimitedCommentSequence :: + SingleLineDelimitedComment WhiteSpaceSequence? SingleLineDelimitedCommentSequence? + + +Term[U, N] :: + [+U] Assertion[+U, ?N] + [+U] Atom[+U, ?N] + [+U] Atom[+U, ?N] Quantifier + [~U] QuantifiableAssertion[?N] Quantifier + [~U] Assertion[~U, ?N] + [~U] ExtendedAtom[?N] Quantifier + [~U] ExtendedAtom[?N] + +Assertion[U, N] :: + `^` + `$` + `\` `b` + `\` `B` + [+U] `(` `?` `=` Disjunction[+U, ?N] `)` + [+U] `(` `?` `!` Disjunction[+U, ?N] `)` + [~U] QuantifiableAssertion[?N] + `(` `?` `<=` Disjunction[?U, ?N] `)` + `(` `?` `<!` Disjunction[?U, ?N] `)` + +QuantifiableAssertion[N] :: + `(` `?` `=` Disjunction[~U, ?N] `)` + `(` `?` `!` Disjunction[~U, ?N] `)` + +ExtendedAtom[N] :: + `.` + `\` AtomEscape[~U, ?N] + `\` [lookahead == `c`] + CharacterClass[~U] + `(` Disjunction[~U, ?N] `)` + `(` `?` `:` Disjunction[~U, ?N] `)` + InvalidBracedQuantifier + ExtendedPatternCharacter + +InvalidBracedQuantifier :: + `{` DecimalDigits `}` + `{` DecimalDigits `,` `}` + `{` DecimalDigits `,` DecimalDigits `}` + +ExtendedPatternCharacter :: + SourceCharacter but not one of `^` `$` `\` `.` `*` `+` `?` `(` `)` `[` `|` + +AtomEscape[U, N] :: + [+U] DecimalEscape + [~U] DecimalEscape [> but only if the CapturingGroupNumber of |DecimalEscape| is <= _NcapturingParens_] + CharacterClassEscape[?U] + CharacterEscape[~U, ?N] + [+N] `k` GroupName[?U] + +CharacterEscape[U, N] :: + ControlEscape + `c` ControlLetter + `0` [lookahead <! DecimalDigit] + HexEscapeSequence + RegExpUnicodeEscapeSequence[?U] + [~U] LegacyOctalEscapeSequence + IdentityEscape[?U, ?N] + +IdentityEscape[U, N] :: + [+U] SyntaxCharacter + [+U] `/` + [~U] SourceCharacterIdentityEscape[?N] + +SourceCharacterIdentityEscape[N] :: + [~N] SourceCharacter but not `c` + [+N] SourceCharacter but not one of `c` or `k` + +ClassAtomNoDash[U] :: + SourceCharacter but not one of `\` or `]` or `-` + `\` ClassEscape[?U, ~N] + `\` [lookahead == `c`] + +ClassEscape[U, N] :: + `b` + [+U] `-` + [~U] `c` ClassControlLetter + CharacterClassEscape[?U] + CharacterEscape[?U, ?N] + +ClassControlLetter :: + DecimalDigit + `_` + + +IfStatement[Yield, Await, Return] : + `if` `(` Expression[+In, ?Yield, ?Await] `)` FunctionDeclaration[?Yield, ?Await, ~Default] `else` Statement[?Yield, ?Await, ?Return] + `if` `(` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] `else` FunctionDeclaration[?Yield, ?Await, ~Default] + `if` `(` Expression[+In, ?Yield, ?Await] `)` FunctionDeclaration[?Yield, ?Await, ~Default] `else` FunctionDeclaration[?Yield, ?Await, ~Default] + `if` `(` Expression[+In, ?Yield, ?Await] `)` FunctionDeclaration[?Yield, ?Await, ~Default] + + +IterationStatement[Yield, Await, Return] : + `for` `(` `var` BindingIdentifier[?Yield, ?Await] Initializer[~In, ?Yield, ?Await] `in` Expression[+In, ?Yield, ?Await] `)` Statement[?Yield, ?Await, ?Return] + diff --git a/third_party/rust/jsparagus/js_parser/try_it.py b/third_party/rust/jsparagus/js_parser/try_it.py new file mode 100755 index 0000000000..d8cb89457a --- /dev/null +++ b/third_party/rust/jsparagus/js_parser/try_it.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python + +"""js.py - Repl-like toy to explore parsing of lines of JS. + +See README.md for instructions. +""" + +import argparse +import traceback +from .lexer import JSLexer +from .parser import JSParser +from jsparagus.lexer import SyntaxError + + +def interactive_input(lexer, prompt="js> "): + while True: + line = input(prompt) + lexer.write(line + "\n") + if lexer.can_close(): + return lexer.close() + prompt = "..> " + + +def rpl(): + """Read-print loop.""" + while True: + parser = JSLexer(JSParser(), filename="<stdin>") + try: + result = interactive_input(parser) + except EOFError: + print() + break + except SyntaxError: + traceback.print_exc(limit=0) + continue + print(result) + + +def main(): + parser = argparse.ArgumentParser(description="Try out the JS parser.") + parser.add_argument('input_file', metavar='FILE', nargs='?', + help=".js file to parse") + options = parser.parse_args() + + if options.input_file is not None: + with open(options.input_file) as f: + source = f.readlines() + lexer = JSLexer(JSParser()) + for line in source: + print(line.rstrip()) + lexer.write(line) + ast = lexer.close() + print(ast) + else: + rpl() + + +if __name__ == '__main__': + main() |