/* * 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=JavaScriptBaseParser; } 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 | 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 | singleExpression '=' singleExpression # AssignmentExpression | 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 : identifier {self.p("get")}? propertyName ; setter : identifier {self.p("set")}? 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()}? ;