/* * The MIT License (MIT) * * Copyright (c) 2014 by Bart Kiers (original author) and Alexandre Vitorelli (contributor -> ported to CSharp) * Copyright (c) 2017-2020 by Ivan Kochurkin (Positive Technologies): added ECMAScript 6 support, cleared and transformed to the universal grammar. * Copyright (c) 2018 by Juan Alvarez (contributor -> ported to Go) * Copyright (c) 2019 by Student Main (contributor -> ES2020) * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ parser grammar JavaScriptParser; options { tokenVocab = JavaScriptLexer; superClass = JavaScriptParserBase; } program : HashBangLine? sourceElements? EOF ; sourceElement : statement ; statement : block | variableStatement | importStatement | exportStatement | emptyStatement | classDeclaration | expressionStatement | ifStatement | iterationStatement | continueStatement | breakStatement | returnStatement | yieldStatement | withStatement | labelledStatement | switchStatement | throwStatement | tryStatement | debuggerStatement | functionDeclaration ; block : '{' statementList? '}' ; statementList : statement+ ; importStatement : Import importFromBlock ; importFromBlock : importDefault? (importNamespace | moduleItems) importFrom eos | StringLiteral eos ; moduleItems : '{' (aliasName ',')* (aliasName ','?)? '}' ; importDefault : aliasName ',' ; importNamespace : ('*' | identifierName) (As identifierName)? ; importFrom : From StringLiteral ; aliasName : identifierName (As identifierName)? ; exportStatement : Export (exportFromBlock | declaration) eos # ExportDeclaration | Export Default singleExpression eos # ExportDefaultDeclaration ; exportFromBlock : importNamespace importFrom eos | moduleItems importFrom? eos ; declaration : variableStatement | classDeclaration | functionDeclaration ; variableStatement : variableDeclarationList eos ; variableDeclarationList : varModifier variableDeclaration (',' variableDeclaration)* ; variableDeclaration : assignable ('=' singleExpression)? // ECMAScript 6: Array & Object Matching ; emptyStatement : SemiColon ; expressionStatement : {self.notOpenBraceAndNotFunction()}? expressionSequence eos ; ifStatement : If '(' expressionSequence ')' statement (Else statement)? ; iterationStatement : Do statement While '(' expressionSequence ')' eos # DoStatement | While '(' expressionSequence ')' statement # WhileStatement | For '(' (expressionSequence | variableDeclarationList)? ';' expressionSequence? ';' expressionSequence? ')' statement # ForStatement | For '(' (singleExpression | variableDeclarationList) In expressionSequence ')' statement # ForInStatement // strange, 'of' is an identifier. and self.p("of") not work in sometime. | For Await? '(' (singleExpression | variableDeclarationList) identifier {self.p("of")}? expressionSequence ')' statement # ForOfStatement ; varModifier // let, const - ECMAScript 6 : Var | let | Const ; continueStatement : Continue ( {self.notLineTerminator()}? identifier)? eos ; breakStatement : Break ( {self.notLineTerminator()}? identifier)? eos ; returnStatement : Return ( {self.notLineTerminator()}? expressionSequence)? eos ; yieldStatement : Yield ( {self.notLineTerminator()}? expressionSequence)? eos ; withStatement : With '(' expressionSequence ')' statement ; switchStatement : Switch '(' expressionSequence ')' caseBlock ; caseBlock : '{' caseClauses? (defaultClause caseClauses?)? '}' ; caseClauses : caseClause+ ; caseClause : Case expressionSequence ':' statementList? ; defaultClause : Default ':' statementList? ; labelledStatement : identifier ':' statement ; throwStatement : Throw {self.notLineTerminator()}? expressionSequence eos ; tryStatement : Try block (catchProduction finallyProduction? | finallyProduction) ; catchProduction : Catch ('(' assignable? ')')? block ; finallyProduction : Finally block ; debuggerStatement : Debugger eos ; functionDeclaration : Async? Function '*'? identifier '(' formalParameterList? ')' '{' functionBody '}' ; classDeclaration : Class identifier classTail ; classTail : (Extends singleExpression)? '{' classElement* '}' ; classElement : (Static | {self.n("static")}? identifier | Async)* (methodDefinition | assignable '=' objectLiteral ';') | emptyStatement | '#'? propertyName '=' singleExpression ; methodDefinition : '*'? '#'? propertyName '(' formalParameterList? ')' '{' functionBody '}' | '*'? '#'? getter '(' ')' '{' functionBody '}' | '*'? '#'? setter '(' formalParameterList? ')' '{' functionBody '}' ; formalParameterList : formalParameterArg (',' formalParameterArg)* (',' lastFormalParameterArg)? | lastFormalParameterArg ; formalParameterArg : assignable ('=' singleExpression)? // ECMAScript 6: Initialization ; lastFormalParameterArg // ECMAScript 6: Rest Parameter : Ellipsis singleExpression ; functionBody : sourceElements? ; sourceElements : sourceElement+ ; arrayLiteral : ('[' elementList ']') ; elementList : ','* arrayElement? (','+ arrayElement)* ','* // Yes, everything is optional ; arrayElement : Ellipsis? singleExpression ; propertyAssignment : propertyName ':' singleExpression # PropertyExpressionAssignment | '[' singleExpression ']' ':' singleExpression # ComputedPropertyExpressionAssignment | Async? '*'? propertyName '(' formalParameterList? ')' '{' functionBody '}' # FunctionProperty | getter '(' ')' '{' functionBody '}' # PropertyGetter | setter '(' formalParameterArg ')' '{' functionBody '}' # PropertySetter | Ellipsis? singleExpression # PropertyShorthand ; propertyName : identifierName | StringLiteral | numericLiteral | '[' singleExpression ']' ; arguments : '(' (argument (',' argument)* ','?)? ')' ; argument : Ellipsis? (singleExpression | identifier) ; expressionSequence : singleExpression (',' singleExpression)* ; singleExpression : anoymousFunction # FunctionExpression | Class identifier? classTail # ClassExpression | singleExpression '[' expressionSequence ']' # MemberIndexExpression | singleExpression '?'? '.' '#'? identifierName # MemberDotExpression | singleExpression arguments # ArgumentsExpression | New singleExpression arguments? # NewExpression | New '.' identifier # MetaExpression // new.target | singleExpression {self.notLineTerminator()}? '++' # PostIncrementExpression | singleExpression {self.notLineTerminator()}? '--' # PostDecreaseExpression | Delete singleExpression # DeleteExpression | Void singleExpression # VoidExpression | Typeof singleExpression # TypeofExpression | '++' singleExpression # PreIncrementExpression | '--' singleExpression # PreDecreaseExpression | '+' singleExpression # UnaryPlusExpression | '-' singleExpression # UnaryMinusExpression | '~' singleExpression # BitNotExpression | '!' singleExpression # NotExpression | Await singleExpression # AwaitExpression | < assoc = right > singleExpression '**' singleExpression # PowerExpression | singleExpression ('*' | '/' | '%') singleExpression # MultiplicativeExpression | singleExpression ('+' | '-') singleExpression # AdditiveExpression | singleExpression '??' singleExpression # CoalesceExpression | singleExpression ('<<' | '>>' | '>>>') singleExpression # BitShiftExpression | singleExpression ('<' | '>' | '<=' | '>=') singleExpression # RelationalExpression | singleExpression Instanceof singleExpression # InstanceofExpression | singleExpression In singleExpression # InExpression | singleExpression ('==' | '!=' | '===' | '!==') singleExpression # EqualityExpression | singleExpression '&' singleExpression # BitAndExpression | singleExpression '^' singleExpression # BitXOrExpression | singleExpression '|' singleExpression # BitOrExpression | singleExpression '&&' singleExpression # LogicalAndExpression | singleExpression '||' singleExpression # LogicalOrExpression | singleExpression '?' singleExpression ':' singleExpression # TernaryExpression | < assoc = right > singleExpression '=' singleExpression # AssignmentExpression | < assoc = right > singleExpression assignmentOperator singleExpression # AssignmentOperatorExpression | Import '(' singleExpression ')' # ImportExpression | singleExpression TemplateStringLiteral # TemplateStringExpression // ECMAScript 6 | yieldStatement # YieldExpression // ECMAScript 6 | This # ThisExpression | identifier # IdentifierExpression | Super # SuperExpression | literal # LiteralExpression | arrayLiteral # ArrayLiteralExpression | objectLiteral # ObjectLiteralExpression | '(' expressionSequence ')' # ParenthesizedExpression ; assignable : identifier | arrayLiteral | objectLiteral ; objectLiteral : '{' (propertyAssignment (',' propertyAssignment)*)? ','? '}' ; anoymousFunction : functionDeclaration # FunctionDecl | Async? Function '*'? '(' formalParameterList? ')' '{' functionBody '}' # AnoymousFunctionDecl | Async? arrowFunctionParameters '=>' arrowFunctionBody # ArrowFunction ; arrowFunctionParameters : identifier | '(' formalParameterList? ')' ; arrowFunctionBody : singleExpression | '{' functionBody '}' ; assignmentOperator : '*=' | '/=' | '%=' | '+=' | '-=' | '<<=' | '>>=' | '>>>=' | '&=' | '^=' | '|=' | '**=' ; literal : NullLiteral | BooleanLiteral | StringLiteral | TemplateStringLiteral | RegularExpressionLiteral | numericLiteral | bigintLiteral ; numericLiteral : DecimalLiteral | HexIntegerLiteral | OctalIntegerLiteral | OctalIntegerLiteral2 | BinaryIntegerLiteral ; bigintLiteral : BigDecimalIntegerLiteral | BigHexIntegerLiteral | BigOctalIntegerLiteral | BigBinaryIntegerLiteral ; getter : {self.n("get")}? identifier propertyName ; setter : {self.n("set")}? identifier propertyName ; identifierName : identifier | reservedWord ; identifier : Identifier | NonStrictLet | Async ; reservedWord : keyword | NullLiteral | BooleanLiteral ; keyword : Break | Do | Instanceof | Typeof | Case | Else | New | Var | Catch | Finally | Return | Void | Continue | For | Switch | While | Debugger | Function | This | With | Default | If | Throw | Delete | In | Try | Class | Enum | Extends | Super | Const | Export | Import | Implements | let | Private | Public | Interface | Package | Protected | Static | Yield | Async | Await | From | As ; let : NonStrictLet | StrictLet ; eos : SemiColon | EOF | {self.lineTerminatorAhead()}? | {self.closeBrace()}? ;