{ {-# LANGUAGE BangPatterns #-} module Language.JavaScript.Parser.Grammar7 ( parseProgram , parseModule , parseStatement , parseExpression , parseLiteral ) where import Data.Char import Data.Functor (($>)) import Language.JavaScript.Parser.Lexer import Language.JavaScript.Parser.ParserMonad import Language.JavaScript.Parser.SrcLocation import Language.JavaScript.Parser.Token import qualified Language.JavaScript.Parser.AST as AST } -- The name of the generated function to be exported from the module %name parseProgram Program %name parseModule Module %name parseLiteral LiteralMain %name parseExpression ExpressionMain %name parseStatement StatementMain %tokentype { Token } %error { parseError } %monad { Alex } { >>= } { return } %lexer { lexCont } { EOFToken {} } %token ';' { SemiColonToken {} } ',' { CommaToken {} } '?' { HookToken {} } ':' { ColonToken {} } '||' { OrToken {} } '&&' { AndToken {} } '|' { BitwiseOrToken {} } '^' { BitwiseXorToken {} } '&' { BitwiseAndToken {} } '=>' { ArrowToken {} } '===' { StrictEqToken {} } '==' { EqToken {} } '*=' { TimesAssignToken {} } '/=' { DivideAssignToken {} } '%=' { ModAssignToken {} } '+=' { PlusAssignToken {} } '-=' { MinusAssignToken {} } '<<=' { LshAssignToken {} } '>>=' { RshAssignToken {} } '>>>=' { UrshAssignToken {} } '&=' { AndAssignToken {} } '^=' { XorAssignToken {} } '|=' { OrAssignToken {} } '=' { SimpleAssignToken {} } '!==' { StrictNeToken {} } '!=' { NeToken {} } '<<' { LshToken {} } '<=' { LeToken {} } '<' { LtToken {} } '>>>' { UrshToken {} } '>>' { RshToken {} } '>=' { GeToken {} } '>' { GtToken {} } '++' { IncrementToken {} } '--' { DecrementToken {} } '+' { PlusToken {} } '-' { MinusToken {} } '*' { MulToken {} } '/' { DivToken {} } '%' { ModToken {} } '!' { NotToken {} } '~' { BitwiseNotToken {} } '...' { SpreadToken {} } '.' { DotToken {} } '[' { LeftBracketToken {} } ']' { RightBracketToken {} } '{' { LeftCurlyToken {} } '}' { RightCurlyToken {} } '(' { LeftParenToken {} } ')' { RightParenToken {} } 'as' { AsToken {} } 'autosemi' { AutoSemiToken {} } 'break' { BreakToken {} } 'case' { CaseToken {} } 'catch' { CatchToken {} } 'class' { ClassToken {} } 'const' { ConstToken {} } 'continue' { ContinueToken {} } 'debugger' { DebuggerToken {} } 'default' { DefaultToken {} } 'delete' { DeleteToken {} } 'do' { DoToken {} } 'else' { ElseToken {} } 'enum' { EnumToken {} } 'export' { ExportToken {} } 'extends' { ExtendsToken {} } 'false' { FalseToken {} } 'finally' { FinallyToken {} } 'for' { ForToken {} } 'function' { FunctionToken {} } 'from' { FromToken {} } 'get' { GetToken {} } 'if' { IfToken {} } 'import' { ImportToken {} } 'in' { InToken {} } 'instanceof' { InstanceofToken {} } 'let' { LetToken {} } 'new' { NewToken {} } 'null' { NullToken {} } 'of' { OfToken {} } 'return' { ReturnToken {} } 'set' { SetToken {} } 'static' { StaticToken {} } 'super' { SuperToken {} } 'switch' { SwitchToken {} } 'this' { ThisToken {} } 'throw' { ThrowToken {} } 'true' { TrueToken {} } 'try' { TryToken {} } 'typeof' { TypeofToken {} } 'var' { VarToken {} } 'void' { VoidToken {} } 'while' { WhileToken {} } 'with' { WithToken {} } 'yield' { YieldToken {} } 'ident' { IdentifierToken {} } 'decimal' { DecimalToken {} } 'hexinteger' { HexIntegerToken {} } 'octal' { OctalToken {} } 'string' { StringToken {} } 'regex' { RegExToken {} } 'tmplnosub' { NoSubstitutionTemplateToken {} } 'tmplhead' { TemplateHeadToken {} } 'tmplmiddle' { TemplateMiddleToken {} } 'tmpltail' { TemplateTailToken {} } 'future' { FutureToken {} } 'tail' { TailToken {} } %% -- --------------------------------------------------------------------- -- Sort out automatically inserted semi-colons. -- A MaybeSemi is an actual semi-colon or nothing. -- An AutoSemu is either an actual semi-colon or 'virtual' semi-colon inserted -- by the Alex lexer or nothing. MaybeSemi :: { AST.JSSemi } MaybeSemi : ';' { AST.JSSemi (mkJSAnnot $1) } | { AST.JSSemiAuto } AutoSemi :: { AST.JSSemi } AutoSemi : ';' { AST.JSSemi (mkJSAnnot $1) } | 'autosemi' { AST.JSSemiAuto } | { AST.JSSemiAuto } -- --------------------------------------------------------------------- -- Helpers LParen :: { AST.JSAnnot } LParen : '(' { mkJSAnnot $1 } RParen :: { AST.JSAnnot } RParen : ')' { mkJSAnnot $1 } LBrace :: { AST.JSAnnot } LBrace : '{' { mkJSAnnot $1 } RBrace :: { AST.JSAnnot } RBrace : '}' { mkJSAnnot $1 } LSquare :: { AST.JSAnnot } LSquare : '[' { mkJSAnnot $1 } RSquare :: { AST.JSAnnot } RSquare : ']' { mkJSAnnot $1 } Comma :: { AST.JSAnnot } Comma : ',' { mkJSAnnot $1 } Colon :: { AST.JSAnnot } Colon : ':' { mkJSAnnot $1 } Semi :: { AST.JSAnnot } Semi : ';' { mkJSAnnot $1 } Arrow :: { AST.JSAnnot } Arrow : '=>' { mkJSAnnot $1 } Spread :: { AST.JSAnnot } Spread : '...' { mkJSAnnot $1 } Dot :: { AST.JSAnnot } Dot : '.' { mkJSAnnot $1 } As :: { AST.JSAnnot } As : 'as' { mkJSAnnot $1 } Increment :: { AST.JSUnaryOp } Increment : '++' { AST.JSUnaryOpIncr (mkJSAnnot $1) } Decrement :: { AST.JSUnaryOp } Decrement : '--' { AST.JSUnaryOpDecr (mkJSAnnot $1) } Delete :: { AST.JSUnaryOp } Delete : 'delete' { AST.JSUnaryOpDelete (mkJSAnnot $1) } Void :: { AST.JSUnaryOp } Void : 'void' { AST.JSUnaryOpVoid (mkJSAnnot $1) } Typeof :: { AST.JSUnaryOp } Typeof : 'typeof' { AST.JSUnaryOpTypeof (mkJSAnnot $1) } Plus :: { AST.JSBinOp } Plus : '+' { AST.JSBinOpPlus (mkJSAnnot $1) } Minus :: { AST.JSBinOp } Minus : '-' { AST.JSBinOpMinus (mkJSAnnot $1) } Tilde :: { AST.JSUnaryOp } Tilde : '~' { AST.JSUnaryOpTilde (mkJSAnnot $1) } Not :: { AST.JSUnaryOp } Not : '!' { AST.JSUnaryOpNot (mkJSAnnot $1) } Mul :: { AST.JSBinOp } Mul : '*' { AST.JSBinOpTimes (mkJSAnnot $1) } Div :: { AST.JSBinOp } Div : '/' { AST.JSBinOpDivide (mkJSAnnot $1) } Mod :: { AST.JSBinOp } Mod : '%' { AST.JSBinOpMod (mkJSAnnot $1) } Lsh :: { AST.JSBinOp } Lsh : '<<' { AST.JSBinOpLsh (mkJSAnnot $1) } Rsh :: { AST.JSBinOp } Rsh : '>>' { AST.JSBinOpRsh (mkJSAnnot $1) } Ursh :: { AST.JSBinOp } Ursh : '>>>' { AST.JSBinOpUrsh (mkJSAnnot $1) } Le :: { AST.JSBinOp } Le : '<=' { AST.JSBinOpLe (mkJSAnnot $1) } Lt :: { AST.JSBinOp } Lt : '<' { AST.JSBinOpLt (mkJSAnnot $1) } Ge :: { AST.JSBinOp } Ge : '>=' { AST.JSBinOpGe (mkJSAnnot $1) } Gt :: { AST.JSBinOp } Gt : '>' { AST.JSBinOpGt (mkJSAnnot $1) } In :: { AST.JSBinOp } In : 'in' { AST.JSBinOpIn (mkJSAnnot $1) } Instanceof :: { AST.JSBinOp } Instanceof : 'instanceof' { AST.JSBinOpInstanceOf (mkJSAnnot $1) } StrictEq :: { AST.JSBinOp } StrictEq : '===' { AST.JSBinOpStrictEq (mkJSAnnot $1) } Equal :: { AST.JSBinOp } Equal : '==' { AST.JSBinOpEq (mkJSAnnot $1) } StrictNe :: { AST.JSBinOp } StrictNe : '!==' { AST.JSBinOpStrictNeq (mkJSAnnot $1) } Ne :: { AST.JSBinOp } Ne : '!=' { AST.JSBinOpNeq (mkJSAnnot $1)} Of :: { AST.JSBinOp } Of : 'of' { AST.JSBinOpOf (mkJSAnnot $1) } Or :: { AST.JSBinOp } Or : '||' { AST.JSBinOpOr (mkJSAnnot $1) } And :: { AST.JSBinOp } And : '&&' { AST.JSBinOpAnd (mkJSAnnot $1) } BitOr :: { AST.JSBinOp } BitOr : '|' { AST.JSBinOpBitOr (mkJSAnnot $1) } BitAnd :: { AST.JSBinOp } BitAnd : '&' { AST.JSBinOpBitAnd (mkJSAnnot $1) } BitXor :: { AST.JSBinOp } BitXor : '^' { AST.JSBinOpBitXor (mkJSAnnot $1)} Hook :: { AST.JSAnnot } Hook : '?' { mkJSAnnot $1 } SimpleAssign :: { AST.JSAnnot } SimpleAssign : '=' { mkJSAnnot $1 } OpAssign :: { AST.JSAssignOp } OpAssign : '*=' { AST.JSTimesAssign (mkJSAnnot $1) } | '/=' { AST.JSDivideAssign (mkJSAnnot $1) } | '%=' { AST.JSModAssign (mkJSAnnot $1) } | '+=' { AST.JSPlusAssign (mkJSAnnot $1) } | '-=' { AST.JSMinusAssign (mkJSAnnot $1) } | '<<=' { AST.JSLshAssign (mkJSAnnot $1) } | '>>=' { AST.JSRshAssign (mkJSAnnot $1) } | '>>>=' { AST.JSUrshAssign (mkJSAnnot $1) } | '&=' { AST.JSBwAndAssign (mkJSAnnot $1) } | '^=' { AST.JSBwXorAssign (mkJSAnnot $1) } | '|=' { AST.JSBwOrAssign (mkJSAnnot $1) } -- IdentifierName :: See 7.6 -- IdentifierStart -- IdentifierName IdentifierPart -- Note: This production needs to precede the productions for all keyword -- statements and PrimaryExpression. Contra the Happy documentation, in the -- case of a reduce/reduce conflict, the *later* rule takes precedence, and -- the ambiguity of, for example, `{break}` needs to resolve in favor of -- `break` as a keyword and not as an identifier in property shorthand -- syntax. -- TODO: make this include any reserved word too, including future ones IdentifierName :: { AST.JSExpression } IdentifierName : Identifier {$1} | 'break' { AST.JSIdentifier (mkJSAnnot $1) "break" } | 'case' { AST.JSIdentifier (mkJSAnnot $1) "case" } | 'catch' { AST.JSIdentifier (mkJSAnnot $1) "catch" } | 'class' { AST.JSIdentifier (mkJSAnnot $1) "class" } | 'const' { AST.JSIdentifier (mkJSAnnot $1) "const" } | 'continue' { AST.JSIdentifier (mkJSAnnot $1) "continue" } | 'debugger' { AST.JSIdentifier (mkJSAnnot $1) "debugger" } | 'default' { AST.JSIdentifier (mkJSAnnot $1) "default" } | 'delete' { AST.JSIdentifier (mkJSAnnot $1) "delete" } | 'do' { AST.JSIdentifier (mkJSAnnot $1) "do" } | 'else' { AST.JSIdentifier (mkJSAnnot $1) "else" } | 'enum' { AST.JSIdentifier (mkJSAnnot $1) "enum" } | 'export' { AST.JSIdentifier (mkJSAnnot $1) "export" } | 'extends' { AST.JSIdentifier (mkJSAnnot $1) "extends" } | 'false' { AST.JSIdentifier (mkJSAnnot $1) "false" } | 'finally' { AST.JSIdentifier (mkJSAnnot $1) "finally" } | 'for' { AST.JSIdentifier (mkJSAnnot $1) "for" } | 'function' { AST.JSIdentifier (mkJSAnnot $1) "function" } | 'if' { AST.JSIdentifier (mkJSAnnot $1) "if" } | 'in' { AST.JSIdentifier (mkJSAnnot $1) "in" } | 'instanceof' { AST.JSIdentifier (mkJSAnnot $1) "instanceof" } | 'let' { AST.JSIdentifier (mkJSAnnot $1) "let" } | 'new' { AST.JSIdentifier (mkJSAnnot $1) "new" } | 'null' { AST.JSIdentifier (mkJSAnnot $1) "null" } | 'of' { AST.JSIdentifier (mkJSAnnot $1) "of" } | 'return' { AST.JSIdentifier (mkJSAnnot $1) "return" } | 'static' { AST.JSIdentifier (mkJSAnnot $1) "static" } | 'super' { AST.JSIdentifier (mkJSAnnot $1) "super" } | 'switch' { AST.JSIdentifier (mkJSAnnot $1) "switch" } | 'this' { AST.JSIdentifier (mkJSAnnot $1) "this" } | 'throw' { AST.JSIdentifier (mkJSAnnot $1) "throw" } | 'true' { AST.JSIdentifier (mkJSAnnot $1) "true" } | 'try' { AST.JSIdentifier (mkJSAnnot $1) "try" } | 'typeof' { AST.JSIdentifier (mkJSAnnot $1) "typeof" } | 'var' { AST.JSIdentifier (mkJSAnnot $1) "var" } | 'void' { AST.JSIdentifier (mkJSAnnot $1) "void" } | 'while' { AST.JSIdentifier (mkJSAnnot $1) "while" } | 'with' { AST.JSIdentifier (mkJSAnnot $1) "with" } | 'future' { AST.JSIdentifier (mkJSAnnot $1) (tokenLiteral $1) } Var :: { AST.JSAnnot } Var : 'var' { mkJSAnnot $1 } Let :: { AST.JSAnnot } Let : 'let' { mkJSAnnot $1 } Const :: { AST.JSAnnot } Const : 'const' { mkJSAnnot $1 } Import :: { AST.JSAnnot } Import : 'import' { mkJSAnnot $1 } From :: { AST.JSAnnot } From : 'from' { mkJSAnnot $1 } Export :: { AST.JSAnnot } Export : 'export' { mkJSAnnot $1 } If :: { AST.JSAnnot } If : 'if' { mkJSAnnot $1 } Else :: { AST.JSAnnot } Else : 'else' { mkJSAnnot $1 } Do :: { AST.JSAnnot } Do : 'do' { mkJSAnnot $1 } While :: { AST.JSAnnot } While : 'while' { mkJSAnnot $1 } For :: { AST.JSAnnot } For : 'for' { mkJSAnnot $1 } Continue :: { AST.JSAnnot } Continue : 'continue' { mkJSAnnot $1 } Break :: { AST.JSAnnot } Break : 'break' { mkJSAnnot $1 } Return :: { AST.JSAnnot } Return : 'return' { mkJSAnnot $1 } With :: { AST.JSAnnot } With : 'with' { mkJSAnnot $1 } Switch :: { AST.JSAnnot } Switch : 'switch' { mkJSAnnot $1 } Case :: { AST.JSAnnot } Case : 'case' { mkJSAnnot $1 } Default :: { AST.JSAnnot } Default : 'default' { mkJSAnnot $1 } Throw :: { AST.JSAnnot } Throw : 'throw' { mkJSAnnot $1 {- 'Throw' -} } Try :: { AST.JSAnnot } Try : 'try' { mkJSAnnot $1 } CatchL :: { AST.JSAnnot } CatchL : 'catch' { mkJSAnnot $1 } FinallyL :: { AST.JSAnnot } FinallyL : 'finally' { mkJSAnnot $1 } Function :: { AST.JSAnnot } Function : 'function' { mkJSAnnot $1 {- 'Function' -} } New :: { AST.JSAnnot } New : 'new' { mkJSAnnot $1 } Class :: { AST.JSAnnot } Class : 'class' { mkJSAnnot $1 } Extends :: { AST.JSAnnot } Extends : 'extends' { mkJSAnnot $1 } Static :: { AST.JSAnnot } Static : 'static' { mkJSAnnot $1 } Super :: { AST.JSExpression } Super : 'super' { AST.JSLiteral (mkJSAnnot $1) "super" } Eof :: { AST.JSAnnot } Eof : 'tail' { mkJSAnnot $1 {- 'Eof' -} } -- Literal :: See 7.8 -- NullLiteral -- BooleanLiteral -- NumericLiteral -- StringLiteral Literal :: { AST.JSExpression } Literal : NullLiteral { $1 } | BooleanLiteral { $1 } | NumericLiteral { $1 } | StringLiteral { $1 } | RegularExpressionLiteral { $1 } NullLiteral :: { AST.JSExpression } NullLiteral : 'null' { AST.JSLiteral (mkJSAnnot $1) "null" } BooleanLiteral :: { AST.JSExpression } BooleanLiteral : 'true' { AST.JSLiteral (mkJSAnnot $1) "true" } | 'false' { AST.JSLiteral (mkJSAnnot $1) "false" } -- ::= DecimalLiteral -- | HexIntegerLiteral -- | OctalLiteral NumericLiteral :: { AST.JSExpression } NumericLiteral : 'decimal' { AST.JSDecimal (mkJSAnnot $1) (tokenLiteral $1) } | 'hexinteger' { AST.JSHexInteger (mkJSAnnot $1) (tokenLiteral $1) } | 'octal' { AST.JSOctal (mkJSAnnot $1) (tokenLiteral $1) } StringLiteral :: { AST.JSExpression } StringLiteral : 'string' { AST.JSStringLiteral (mkJSAnnot $1) (tokenLiteral $1) } -- ::= RegExp RegularExpressionLiteral :: { AST.JSExpression } RegularExpressionLiteral : 'regex' { AST.JSRegEx (mkJSAnnot $1) (tokenLiteral $1) } -- PrimaryExpression : See 11.1 -- this -- Identifier -- Literal -- ArrayLiteral -- ObjectLiteral -- ( Expression ) PrimaryExpression :: { AST.JSExpression } PrimaryExpression : 'this' { AST.JSLiteral (mkJSAnnot $1) "this" } | Identifier { $1 {- 'PrimaryExpression1' -} } | Literal { $1 {- 'PrimaryExpression2' -} } | ArrayLiteral { $1 {- 'PrimaryExpression3' -} } | ObjectLiteral { $1 {- 'PrimaryExpression4' -} } | ClassExpression { $1 } | GeneratorExpression { $1 } | TemplateLiteral { mkJSTemplateLiteral Nothing $1 {- 'PrimaryExpression6' -} } | LParen Expression RParen { AST.JSExpressionParen $1 $2 $3 } -- Identifier :: See 7.6 -- IdentifierName but not ReservedWord Identifier :: { AST.JSExpression } Identifier : 'ident' { AST.JSIdentifier (mkJSAnnot $1) (tokenLiteral $1) } | 'as' { AST.JSIdentifier (mkJSAnnot $1) "as" } | 'get' { AST.JSIdentifier (mkJSAnnot $1) "get" } | 'set' { AST.JSIdentifier (mkJSAnnot $1) "set" } | 'from' { AST.JSIdentifier (mkJSAnnot $1) "from" } | 'yield' { AST.JSIdentifier (mkJSAnnot $1) "yield" } -- Must follow Identifier; when ambiguous, `yield` as a keyword should take -- precedence over `yield` as an identifier name. Yield :: { AST.JSAnnot } Yield : 'yield' { mkJSAnnot $1 } SpreadExpression :: { AST.JSExpression } SpreadExpression : Spread AssignmentExpression { AST.JSSpreadExpression $1 $2 {- 'SpreadExpression' -} } TemplateLiteral :: { JSUntaggedTemplate } TemplateLiteral : 'tmplnosub' { JSUntaggedTemplate (mkJSAnnot $1) (tokenLiteral $1) [] } | 'tmplhead' TemplateParts { JSUntaggedTemplate (mkJSAnnot $1) (tokenLiteral $1) $2 } TemplateParts :: { [AST.JSTemplatePart] } TemplateParts : TemplateExpression RBrace 'tmplmiddle' TemplateParts { AST.JSTemplatePart $1 $2 ('}' : tokenLiteral $3) : $4 } | TemplateExpression RBrace 'tmpltail' { AST.JSTemplatePart $1 $2 ('}' : tokenLiteral $3) : [] } -- This production only exists to ensure that inTemplate is set to True before -- a tmplmiddle or tmpltail token is lexed. Since the lexer is always one token -- ahead of the parser, setInTemplate needs to be called during a reduction -- that is *two* tokens behind tmplmiddle/tmpltail. Accordingly, -- TemplateExpression is always followed by an RBrace, which is lexed normally. TemplateExpression :: { AST.JSExpression } TemplateExpression : Expression {% setInTemplate True \$> $1 } -- ArrayLiteral : See 11.1.4 -- [ Elisionopt ] -- [ ElementList ] -- [ ElementList , Elisionopt ] ArrayLiteral :: { AST.JSExpression } ArrayLiteral : LSquare RSquare { AST.JSArrayLiteral $1 [] $2 {- 'ArrayLiteral11' -} } | LSquare Elision RSquare { AST.JSArrayLiteral $1 $2 $3 {- 'ArrayLiteral12' -} } | LSquare ElementList RSquare { AST.JSArrayLiteral $1 $2 $3 {- 'ArrayLiteral13' -} } | LSquare ElementList Elision RSquare { AST.JSArrayLiteral $1 ($2 ++ $3) $4 {- 'ArrayLiteral14' -} } -- ElementList : See 11.1.4 -- Elisionopt AssignmentExpression -- ElementList , Elisionopt AssignmentExpression ElementList :: { [AST.JSArrayElement] } ElementList : Elision AssignmentExpression { $1 ++ [AST.JSArrayElement $2] {- 'ElementList1' -} } | AssignmentExpression { [AST.JSArrayElement $1] {- 'ElementList2' -} } | ElementList Elision AssignmentExpression { (($1)++($2 ++ [AST.JSArrayElement $3])) {- 'ElementList3' -} } -- Elision : See 11.1.4 -- , -- Elision , Elision :: { [AST.JSArrayElement] } Elision : Comma { [AST.JSArrayComma $1] {- 'Elision1' -} } | Comma Elision { (AST.JSArrayComma $1):$2 {- 'Elision2' -} } -- ObjectLiteral : See 11.1.5 -- { } -- { PropertyNameAndValueList } -- { PropertyNameAndValueList , } ObjectLiteral :: { AST.JSExpression } ObjectLiteral : LBrace RBrace { AST.JSObjectLiteral $1 (AST.JSCTLNone AST.JSLNil) $2 {- 'ObjectLiteral1' -} } | LBrace PropertyNameandValueList RBrace { AST.JSObjectLiteral $1 (AST.JSCTLNone $2) $3 {- 'ObjectLiteral2' -} } | LBrace PropertyNameandValueList Comma RBrace { AST.JSObjectLiteral $1 (AST.JSCTLComma $2 $3) $4 {- 'ObjectLiteral3' -} } -- ::= ':' -- | ',' ':' -- Seems we can have function declarations in the value part too -- PropertyNameAndValueList : See 11.1.5 -- PropertyAssignment -- PropertyNameAndValueList , PropertyAssignment PropertyNameandValueList :: { AST.JSCommaList AST.JSObjectProperty } PropertyNameandValueList : PropertyAssignment { AST.JSLOne $1 {- 'PropertyNameandValueList1' -} } | PropertyNameandValueList Comma PropertyAssignment { AST.JSLCons $1 $2 $3 {- 'PropertyNameandValueList2' -} } -- PropertyAssignment : See 11.1.5 -- PropertyName : AssignmentExpression -- get PropertyName() { FunctionBody } -- set PropertyName( PropertySetParameterList ) { FunctionBody } PropertyAssignment :: { AST.JSObjectProperty } PropertyAssignment : PropertyName Colon AssignmentExpression { AST.JSPropertyNameandValue $1 $2 [$3] } | IdentifierName { identifierToProperty $1 } | MethodDefinition { AST.JSObjectMethod $1 } -- TODO: not clear if get/set are keywords, or just used in a specific context. Puzzling. MethodDefinition :: { AST.JSMethodDefinition } MethodDefinition : PropertyName LParen RParen FunctionBody { AST.JSMethodDefinition $1 $2 AST.JSLNil $3 $4 } | PropertyName LParen FormalParameterList RParen FunctionBody { AST.JSMethodDefinition $1 $2 $3 $4 $5 } | '*' PropertyName LParen RParen FunctionBody { AST.JSGeneratorMethodDefinition (mkJSAnnot $1) $2 $3 AST.JSLNil $4 $5 } | '*' PropertyName LParen FormalParameterList RParen FunctionBody { AST.JSGeneratorMethodDefinition (mkJSAnnot $1) $2 $3 $4 $5 $6 } -- Should be "get" in next, but is not a Token | 'get' PropertyName LParen RParen FunctionBody { AST.JSPropertyAccessor (AST.JSAccessorGet (mkJSAnnot $1)) $2 $3 AST.JSLNil $4 $5 } -- Should be "set" in next, but is not a Token | 'set' PropertyName LParen PropertySetParameterList RParen FunctionBody { AST.JSPropertyAccessor (AST.JSAccessorSet (mkJSAnnot $1)) $2 $3 (AST.JSLOne $4) $5 $6 } -- PropertyName : See 11.1.5 -- IdentifierName -- StringLiteral -- NumericLiteral PropertyName :: { AST.JSPropertyName } PropertyName : IdentifierName { propName $1 {- 'PropertyName1' -} } | StringLiteral { propName $1 {- 'PropertyName2' -} } | NumericLiteral { propName $1 {- 'PropertyName3' -} } | LSquare AssignmentExpression RSquare { AST.JSPropertyComputed $1 $2 $3 {- 'PropertyName4' -} } -- PropertySetParameterList : See 11.1.5 -- Identifier PropertySetParameterList :: { AST.JSExpression } PropertySetParameterList : AssignmentExpression { $1 {- 'PropertySetParameterList' -} } -- MemberExpression : See 11.2 -- PrimaryExpression -- FunctionExpression -- MemberExpression [ Expression ] -- MemberExpression . IdentifierName -- new MemberExpression Arguments MemberExpression :: { AST.JSExpression } MemberExpression : PrimaryExpression { $1 {- 'MemberExpression1' -} } | FunctionExpression { $1 {- 'MemberExpression2' -} } | MemberExpression LSquare Expression RSquare { AST.JSMemberSquare $1 $2 $3 $4 {- 'MemberExpression3' -} } | MemberExpression Dot IdentifierName { AST.JSMemberDot $1 $2 $3 {- 'MemberExpression4' -} } | MemberExpression TemplateLiteral { mkJSTemplateLiteral (Just $1) $2 } | Super LSquare Expression RSquare { AST.JSMemberSquare $1 $2 $3 $4 } | Super Dot IdentifierName { AST.JSMemberDot $1 $2 $3 } | New MemberExpression Arguments { mkJSMemberNew $1 $2 $3 {- 'MemberExpression5' -} } -- NewExpression : See 11.2 -- MemberExpression -- new NewExpression NewExpression :: { AST.JSExpression } NewExpression : MemberExpression { $1 {- 'NewExpression1' -} } | New NewExpression { AST.JSNewExpression $1 $2 {- 'NewExpression2' -} } -- CallExpression : See 11.2 -- MemberExpression Arguments -- CallExpression Arguments -- CallExpression [ Expression ] -- CallExpression . IdentifierName CallExpression :: { AST.JSExpression } CallExpression : MemberExpression Arguments { mkJSMemberExpression $1 $2 {- 'CallExpression1' -} } | Super Arguments { mkJSCallExpression $1 $2 } | CallExpression Arguments { mkJSCallExpression $1 $2 {- 'CallExpression2' -} } | CallExpression LSquare Expression RSquare { AST.JSCallExpressionSquare $1 $2 $3 $4 {- 'CallExpression3' -} } | CallExpression Dot IdentifierName { AST.JSCallExpressionDot $1 $2 $3 {- 'CallExpression4' -} } | CallExpression TemplateLiteral { mkJSTemplateLiteral (Just $1) $2 {- 'CallExpression5' -} } -- Arguments : See 11.2 -- () -- ( ArgumentList ) Arguments :: { JSArguments } Arguments : LParen RParen { JSArguments $1 AST.JSLNil $2 {- 'Arguments1' -} } | LParen ArgumentList RParen { JSArguments $1 $2 $3 {- 'Arguments2' -} } -- ArgumentList : See 11.2 -- AssignmentExpression -- ArgumentList , AssignmentExpression ArgumentList :: { AST.JSCommaList AST.JSExpression } ArgumentList : AssignmentExpression { AST.JSLOne $1 {- 'ArgumentList1' -} } | ArgumentList Comma AssignmentExpression { AST.JSLCons $1 $2 $3 {- 'ArgumentList2' -} } -- LeftHandSideExpression : See 11.2 -- NewExpression -- CallExpression LeftHandSideExpression :: { AST.JSExpression } LeftHandSideExpression : NewExpression { $1 {- 'LeftHandSideExpression1' -} } | CallExpression { $1 {- 'LeftHandSideExpression12' -} } -- PostfixExpression : See 11.3 -- LeftHandSideExpression -- [no LineTerminator here] -- LeftHandSideExpression ++ -- [no LineTerminator here] -- LeftHandSideExpression -- PostfixExpression :: { AST.JSExpression } PostfixExpression : LeftHandSideExpression { $1 {- 'PostfixExpression' -} } | PostfixExpression Increment { AST.JSExpressionPostfix $1 $2 } | PostfixExpression Decrement { AST.JSExpressionPostfix $1 $2 } -- UnaryExpression : See 11.4 -- PostfixExpression -- delete UnaryExpression -- void UnaryExpression -- typeof UnaryExpression -- ++ UnaryExpression -- -- UnaryExpression -- + UnaryExpression -- - UnaryExpression -- ~ UnaryExpression -- ! UnaryExpression UnaryExpression :: { AST.JSExpression } UnaryExpression : PostfixExpression { $1 {- 'UnaryExpression' -} } | Delete UnaryExpression { AST.JSUnaryExpression $1 $2 } | Void UnaryExpression { AST.JSUnaryExpression $1 $2 } | Typeof UnaryExpression { AST.JSUnaryExpression $1 $2 } | Increment UnaryExpression { AST.JSUnaryExpression $1 $2 } | Decrement UnaryExpression { AST.JSUnaryExpression $1 $2 } | Plus UnaryExpression { AST.JSUnaryExpression (mkUnary $1) $2 } | Minus UnaryExpression { AST.JSUnaryExpression (mkUnary $1) $2 } | Tilde UnaryExpression { AST.JSUnaryExpression $1 $2 } | Not UnaryExpression { AST.JSUnaryExpression $1 $2 } -- MultiplicativeExpression : See 11.5 -- UnaryExpression -- MultiplicativeExpression * UnaryExpression -- MultiplicativeExpression / UnaryExpression -- MultiplicativeExpression % UnaryExpression MultiplicativeExpression :: { AST.JSExpression } MultiplicativeExpression : UnaryExpression { $1 {- 'MultiplicativeExpression' -} } | MultiplicativeExpression Mul UnaryExpression { AST.JSExpressionBinary {- '*' -} $1 $2 $3 } | MultiplicativeExpression Div UnaryExpression { AST.JSExpressionBinary {- '/' -} $1 $2 $3 } | MultiplicativeExpression Mod UnaryExpression { AST.JSExpressionBinary {- '%' -} $1 $2 $3 } -- AdditiveExpression : See 11.6 -- MultiplicativeExpression -- AdditiveExpression + MultiplicativeExpression -- AdditiveExpression - MultiplicativeExpression AdditiveExpression :: { AST.JSExpression } AdditiveExpression : AdditiveExpression Plus MultiplicativeExpression { AST.JSExpressionBinary {- '+' -} $1 $2 $3 } | AdditiveExpression Minus MultiplicativeExpression { AST.JSExpressionBinary {- '-' -} $1 $2 $3 } | MultiplicativeExpression { $1 {- 'AdditiveExpression' -} } -- ShiftExpression : See 11.7 -- AdditiveExpression -- ShiftExpression << AdditiveExpression -- ShiftExpression >> AdditiveExpression -- ShiftExpression >>> AdditiveExpression ShiftExpression :: { AST.JSExpression } ShiftExpression : ShiftExpression Lsh AdditiveExpression { AST.JSExpressionBinary {- '<<' -} $1 $2 $3 } | ShiftExpression Rsh AdditiveExpression { AST.JSExpressionBinary {- '>>' -} $1 $2 $3 } | ShiftExpression Ursh AdditiveExpression { AST.JSExpressionBinary {- '>>>' -} $1 $2 $3 } | AdditiveExpression { $1 {- 'ShiftExpression' -} } -- RelationalExpression : See 11.8 -- ShiftExpression -- RelationalExpression < ShiftExpression -- RelationalExpression > ShiftExpression -- RelationalExpression <= ShiftExpression -- RelationalExpression >= ShiftExpression -- RelationalExpression instanceof ShiftExpression -- RelationalExpression in ShiftExpression RelationalExpression :: { AST.JSExpression } RelationalExpression : ShiftExpression { $1 {- 'RelationalExpression' -} } | RelationalExpression Lt ShiftExpression { AST.JSExpressionBinary {- '<' -} $1 $2 $3 } | RelationalExpression Gt ShiftExpression { AST.JSExpressionBinary {- '>' -} $1 $2 $3 } | RelationalExpression Le ShiftExpression { AST.JSExpressionBinary {- '<=' -} $1 $2 $3 } | RelationalExpression Ge ShiftExpression { AST.JSExpressionBinary {- '>=' -} $1 $2 $3 } | RelationalExpression Instanceof ShiftExpression { AST.JSExpressionBinary {- ' instanceof' -} $1 $2 $3 } | RelationalExpression In ShiftExpression { AST.JSExpressionBinary {- ' in ' -} $1 $2 $3 } -- RelationalExpressionNoIn : See 11.8 -- ShiftExpression -- RelationalExpressionNoIn < ShiftExpression -- RelationalExpressionNoIn > ShiftExpression -- RelationalExpressionNoIn <= ShiftExpression -- RelationalExpressionNoIn >= ShiftExpression -- RelationalExpressionNoIn instanceof ShiftExpression RelationalExpressionNoIn :: { AST.JSExpression } RelationalExpressionNoIn : ShiftExpression { $1 {- 'RelationalExpressionNoIn' -} } | RelationalExpressionNoIn Lt ShiftExpression { AST.JSExpressionBinary {- '<' -} $1 $2 $3 } | RelationalExpressionNoIn Gt ShiftExpression { AST.JSExpressionBinary {- '>' -} $1 $2 $3 } | RelationalExpressionNoIn Le ShiftExpression { AST.JSExpressionBinary {- '<=' -} $1 $2 $3 } | RelationalExpressionNoIn Ge ShiftExpression { AST.JSExpressionBinary {- '>=' -} $1 $2 $3 } | RelationalExpressionNoIn Instanceof ShiftExpression { AST.JSExpressionBinary {- ' instanceof ' -} $1 $2 $3 } -- EqualityExpression : See 11.9 -- RelationalExpression -- EqualityExpression == RelationalExpression -- EqualityExpression != RelationalExpression -- EqualityExpression === RelationalExpression -- EqualityExpression !== RelationalExpression EqualityExpression :: { AST.JSExpression } EqualityExpression : RelationalExpression { $1 {- 'EqualityExpression' -} } | EqualityExpression Equal RelationalExpression { AST.JSExpressionBinary {- '==' -} $1 $2 $3 } | EqualityExpression Ne RelationalExpression { AST.JSExpressionBinary {- '!=' -} $1 $2 $3 } | EqualityExpression StrictEq RelationalExpression { AST.JSExpressionBinary {- '===' -} $1 $2 $3 } | EqualityExpression StrictNe RelationalExpression { AST.JSExpressionBinary {- '!==' -} $1 $2 $3 } -- EqualityExpressionNoIn : See 11.9 -- RelationalExpressionNoIn -- EqualityExpressionNoIn == RelationalExpressionNoIn -- EqualityExpressionNoIn != RelationalExpressionNoIn -- EqualityExpressionNoIn === RelationalExpressionNoIn -- EqualityExpressionNoIn !== RelationalExpressionNoIn EqualityExpressionNoIn :: { AST.JSExpression } EqualityExpressionNoIn : RelationalExpressionNoIn { $1 {- 'EqualityExpressionNoIn' -} } | EqualityExpressionNoIn Equal RelationalExpression { AST.JSExpressionBinary {- '==' -} $1 $2 $3 } | EqualityExpressionNoIn Ne RelationalExpression { AST.JSExpressionBinary {- '!=' -} $1 $2 $3 } | EqualityExpressionNoIn StrictEq RelationalExpression { AST.JSExpressionBinary {- '===' -} $1 $2 $3 } | EqualityExpressionNoIn StrictNe RelationalExpression { AST.JSExpressionBinary {- '!==' -} $1 $2 $3 } -- BitwiseANDExpression : See 11.10 -- EqualityExpression -- BitwiseANDExpression & EqualityExpression BitwiseAndExpression :: { AST.JSExpression } BitwiseAndExpression : EqualityExpression { $1 {- 'BitwiseAndExpression' -} } | BitwiseAndExpression BitAnd EqualityExpression { AST.JSExpressionBinary {- '&' -} $1 $2 $3 } -- BitwiseANDExpressionNoIn : See 11.10 -- EqualityExpressionNoIn -- BitwiseANDExpressionNoIn & EqualityExpressionNoIn BitwiseAndExpressionNoIn :: { AST.JSExpression } BitwiseAndExpressionNoIn : EqualityExpressionNoIn { $1 {- 'BitwiseAndExpression' -} } | BitwiseAndExpressionNoIn BitAnd EqualityExpressionNoIn { AST.JSExpressionBinary {- '&' -} $1 $2 $3 } -- BitwiseXORExpression : See 11.10 -- BitwiseANDExpression -- BitwiseXORExpression ^ BitwiseANDExpression BitwiseXOrExpression :: { AST.JSExpression } BitwiseXOrExpression : BitwiseAndExpression { $1 {- 'BitwiseXOrExpression' -} } | BitwiseXOrExpression BitXor BitwiseAndExpression { AST.JSExpressionBinary {- '^' -} $1 $2 $3 } -- BitwiseXORExpressionNoIn : See 11.10 -- BitwiseANDExpressionNoIn -- BitwiseXORExpressionNoIn ^ BitwiseANDExpressionNoIn BitwiseXOrExpressionNoIn :: { AST.JSExpression } BitwiseXOrExpressionNoIn : BitwiseAndExpressionNoIn { $1 {- 'BitwiseXOrExpression' -} } | BitwiseXOrExpressionNoIn BitXor BitwiseAndExpressionNoIn { AST.JSExpressionBinary {- '^' -} $1 $2 $3 } -- BitwiseORExpression : See 11.10 -- BitwiseXORExpression -- BitwiseORExpression | BitwiseXORExpression BitwiseOrExpression :: { AST.JSExpression } BitwiseOrExpression : BitwiseXOrExpression { $1 {- 'BitwiseOrExpression' -} } | BitwiseOrExpression BitOr BitwiseXOrExpression { AST.JSExpressionBinary {- '|' -} $1 $2 $3 } -- BitwiseORExpressionNoIn : See 11.10 -- BitwiseXORExpressionNoIn -- BitwiseORExpressionNoIn | BitwiseXORExpressionNoIn BitwiseOrExpressionNoIn :: { AST.JSExpression } BitwiseOrExpressionNoIn : BitwiseXOrExpressionNoIn { $1 {- 'BitwiseOrExpression' -} } | BitwiseOrExpressionNoIn BitOr BitwiseXOrExpressionNoIn { AST.JSExpressionBinary {- '|' -} $1 $2 $3 } -- LogicalANDExpression : See 11.11 -- BitwiseORExpression -- LogicalANDExpression && BitwiseORExpression LogicalAndExpression :: { AST.JSExpression } LogicalAndExpression : BitwiseOrExpression { $1 {- 'LogicalAndExpression' -} } | LogicalAndExpression And BitwiseOrExpression { AST.JSExpressionBinary {- '&&' -} $1 $2 $3 } -- LogicalANDExpressionNoIn : See 11.11 -- BitwiseORExpressionNoIn -- LogicalANDExpressionNoIn && BitwiseORExpressionNoIn LogicalAndExpressionNoIn :: { AST.JSExpression } LogicalAndExpressionNoIn : BitwiseOrExpressionNoIn { $1 {- 'LogicalAndExpression' -} } | LogicalAndExpressionNoIn And BitwiseOrExpressionNoIn { AST.JSExpressionBinary {- '&&' -} $1 $2 $3 } -- LogicalORExpression : See 11.11 -- LogicalANDExpression -- LogicalORExpression || LogicalANDExpression LogicalOrExpression :: { AST.JSExpression } LogicalOrExpression : LogicalAndExpression { $1 {- 'LogicalOrExpression' -} } | LogicalOrExpression Or LogicalAndExpression { AST.JSExpressionBinary {- '||' -} $1 $2 $3 } -- LogicalORExpressionNoIn : See 11.11 -- LogicalANDExpressionNoIn -- LogicalORExpressionNoIn || LogicalANDExpressionNoIn LogicalOrExpressionNoIn :: { AST.JSExpression } LogicalOrExpressionNoIn : LogicalAndExpressionNoIn { $1 {- 'LogicalOrExpression' -} } | LogicalOrExpressionNoIn Or LogicalAndExpressionNoIn { AST.JSExpressionBinary {- '||' -} $1 $2 $3 } -- ConditionalExpression : See 11.12 -- LogicalORExpression -- LogicalORExpression ? AssignmentExpression : AssignmentExpression ConditionalExpression :: { AST.JSExpression } ConditionalExpression : LogicalOrExpression { $1 {- 'ConditionalExpression1' -} } | LogicalOrExpression Hook AssignmentExpression Colon AssignmentExpression { AST.JSExpressionTernary $1 $2 $3 $4 $5 {- 'ConditionalExpression2' -} } -- ConditionalExpressionNoIn : See 11.12 -- LogicalORExpressionNoIn -- LogicalORExpressionNoIn ? AssignmentExpressionNoIn : AssignmentExpressionNoIn ConditionalExpressionNoIn :: { AST.JSExpression } ConditionalExpressionNoIn : LogicalOrExpressionNoIn { $1 {- 'ConditionalExpressionNoIn1' -} } | LogicalOrExpressionNoIn Hook AssignmentExpressionNoIn Colon AssignmentExpressionNoIn { AST.JSExpressionTernary $1 $2 $3 $4 $5 {- 'ConditionalExpressionNoIn2' -} } -- AssignmentExpression : See 11.13 -- ConditionalExpression -- LeftHandSideExpression AssignmentOperator AssignmentExpression AssignmentExpression :: { AST.JSExpression } AssignmentExpression : ConditionalExpression { $1 {- 'AssignmentExpression1' -} } | YieldExpression { $1 } | LeftHandSideExpression AssignmentOperator AssignmentExpression { AST.JSAssignExpression $1 $2 $3 {- 'AssignmentExpression2' -} } | SpreadExpression { $1 } -- AssignmentExpressionNoIn : See 11.13 -- ConditionalExpressionNoIn -- LeftHandSideExpression AssignmentOperator AssignmentExpressionNoIn AssignmentExpressionNoIn :: { AST.JSExpression } AssignmentExpressionNoIn : ConditionalExpressionNoIn { $1 {- 'AssignmentExpressionNoIn1' -} } | YieldExpression { $1 } | LeftHandSideExpression AssignmentOperator AssignmentExpressionNoIn { AST.JSAssignExpression $1 $2 $3 {- 'AssignmentExpressionNoIn1' -} } -- AssignmentOperator : one of See 11.13 -- '=' | '*=' | '/=' | '%=' | '+=' | '-=' | '<<=' | '>>=' | '>>>=' | '&=' | '^=' | '|=' AssignmentOperator :: { AST.JSAssignOp } AssignmentOperator : OpAssign { $1 } | SimpleAssign { AST.JSAssign $1 {- 'SimpleAssign' -} } -- Expression : See 11.14 -- AssignmentExpression -- Expression , AssignmentExpression Expression :: { AST.JSExpression } Expression : AssignmentExpression { $1 {- 'Expression' -} } | Expression Comma AssignmentExpression { AST.JSCommaExpression $1 $2 $3 {- 'Expression2' -} } -- ExpressionNoIn : See 11.14 -- AssignmentExpressionNoIn -- ExpressionNoIn , AssignmentExpressionNoIn ExpressionNoIn :: { AST.JSExpression } ExpressionNoIn : AssignmentExpressionNoIn { $1 {- 'ExpressionNoIn' -} } | ExpressionNoIn Comma AssignmentExpressionNoIn { AST.JSCommaExpression $1 $2 $3 {- 'ExpressionNoIn2' -} } -- TODO: still required? ExpressionOpt :: { AST.JSCommaList AST.JSExpression } ExpressionOpt : Expression { AST.JSLOne $1 {- 'ExpressionOpt1' -} } | { AST.JSLNil {- 'ExpressionOpt2' -} } ExpressionNoInOpt :: { AST.JSCommaList AST.JSExpression } ExpressionNoInOpt : ExpressionNoIn { AST.JSLOne $1 {- 'ExpressionOpt1' -} } | { AST.JSLNil {- 'ExpressionOpt2' -} } -- Statement : See clause 12 -- Block -- VariableStatement -- EmptyStatement -- ExpressionStatement -- IfStatement -- IterationStatement -- ContinueStatement -- BreakStatement -- ReturnStatement -- WithStatement -- LabelledStatement -- SwitchStatement -- ThrowStatement -- TryStatement -- DebuggerStatement Statement :: { AST.JSStatement } Statement : StatementNoEmpty { $1 {- 'Statement1' -} } | EmptyStatement { $1 {- 'Statement2' -} } StatementNoEmpty :: { AST.JSStatement } StatementNoEmpty : StatementBlock { $1 {- 'StatementNoEmpty1' -} } | VariableStatement { $1 {- 'StatementNoEmpty2' -} } | ExpressionStatement { $1 {- 'StatementNoEmpty4' -} } | IfStatement { $1 {- 'StatementNoEmpty5' -} } | IterationStatement { $1 {- 'StatementNoEmpty6' -} } | ContinueStatement { $1 {- 'StatementNoEmpty7' -} } | BreakStatement { $1 {- 'StatementNoEmpty8' -} } | ReturnStatement { $1 {- 'StatementNoEmpty9' -} } | WithStatement { $1 {- 'StatementNoEmpty10' -} } | LabelledStatement { $1 {- 'StatementNoEmpty11' -} } | SwitchStatement { $1 {- 'StatementNoEmpty12' -} } | ThrowStatement { $1 {- 'StatementNoEmpty13' -} } | TryStatement { $1 {- 'StatementNoEmpty14' -} } | DebuggerStatement { $1 {- 'StatementNoEmpty15' -} } StatementBlock :: { AST.JSStatement } StatementBlock : Block MaybeSemi { blockToStatement $1 $2 {- 'StatementBlock1' -} } -- Block : See 12.1 -- { StatementListopt } Block :: { AST.JSBlock } Block : LBrace RBrace { AST.JSBlock $1 [] $2 {- 'Block1' -} } | LBrace StatementList RBrace { AST.JSBlock $1 $2 $3 {- 'Block2' -} } -- StatementList : See 12.1 -- Statement -- StatementList Statement StatementList :: { [AST.JSStatement] } StatementList : Statement { [$1] {- 'StatementList1' -} } | StatementList Statement { ($1++[$2]) {- 'StatementList2' -} } -- VariableStatement : See 12.2 -- var VariableDeclarationList ; VariableStatement :: { AST.JSStatement } VariableStatement : Var VariableDeclarationList MaybeSemi { AST.JSVariable $1 $2 $3 {- 'VariableStatement1' -} } | Let VariableDeclarationList MaybeSemi { AST.JSLet $1 $2 $3 {- 'VariableStatement2' -} } | Const VariableDeclarationList MaybeSemi { AST.JSConstant $1 $2 $3 {- 'VariableStatement3' -} } -- VariableDeclarationList : See 12.2 -- VariableDeclaration -- VariableDeclarationList , VariableDeclaration VariableDeclarationList :: { AST.JSCommaList AST.JSExpression } VariableDeclarationList : VariableDeclaration { AST.JSLOne $1 {- 'VariableDeclarationList1' -} } | VariableDeclarationList Comma VariableDeclaration { AST.JSLCons $1 $2 $3 {- 'VariableDeclarationList2' -} } -- VariableDeclarationListNoIn : See 12.2 -- VariableDeclarationNoIn -- VariableDeclarationListNoIn , VariableDeclarationNoIn VariableDeclarationListNoIn :: { AST.JSCommaList AST.JSExpression } VariableDeclarationListNoIn : VariableDeclarationNoIn { AST.JSLOne $1 {- 'VariableDeclarationListNoIn1' -} } | VariableDeclarationListNoIn Comma VariableDeclarationNoIn { AST.JSLCons $1 $2 $3 {- 'VariableDeclarationListNoIn2' -} } -- VariableDeclaration : See 12.2 -- Identifier Initialiseropt VariableDeclaration :: { AST.JSExpression } VariableDeclaration : PrimaryExpression SimpleAssign AssignmentExpression { AST.JSVarInitExpression $1 (AST.JSVarInit $2 $3) {- 'JSVarInitExpression1' -} } | Identifier { AST.JSVarInitExpression $1 AST.JSVarInitNone {- 'JSVarInitExpression2' -} } -- VariableDeclarationNoIn : See 12.2 -- Identifier InitialiserNoInopt VariableDeclarationNoIn :: { AST.JSExpression } VariableDeclarationNoIn : PrimaryExpression SimpleAssign AssignmentExpression { AST.JSVarInitExpression $1 (AST.JSVarInit $2 $3) {- 'JSVarInitExpressionInit2' -} } | Identifier { AST.JSVarInitExpression $1 AST.JSVarInitNone {- 'JSVarInitExpression2' -} } -- EmptyStatement : See 12.3 -- ; EmptyStatement :: { AST.JSStatement } EmptyStatement : Semi { AST.JSEmptyStatement $1 {- 'EmptyStatement' -} } -- ExpressionStatement : See 12.4 -- [lookahead not in {{, function}] Expression ; -- TODO: Sort out lookahead issue. Maybe by just putting production lower to set reduce/reduce conflict -- According to http://sideshowbarker.github.com/es5-spec/#x12.4, the ambiguity is with -- Block or FunctionDeclaration ExpressionStatement :: { AST.JSStatement } ExpressionStatement : Expression MaybeSemi { expressionToStatement $1 $2 {- 'ExpressionStatement' -} } -- IfStatement : See 12.5 -- if ( Expression ) Statement else Statement -- if ( Expression ) Statement IfStatement :: { AST.JSStatement } -- +++XXXX++ IfStatement : If LParen Expression RParen EmptyStatement { AST.JSIf $1 $2 $3 $4 $5 {- 'IfStatement1' -} } | If LParen Expression RParen StatementNoEmpty Else Statement { AST.JSIfElse $1 $2 $3 $4 $5 $6 $7 {- 'IfStatement3' -} } | If LParen Expression RParen StatementNoEmpty { AST.JSIf $1 $2 $3 $4 $5 {- 'IfStatement3' -} } | If LParen Expression RParen EmptyStatement Else Statement { AST.JSIfElse $1 $2 $3 $4 $5 $6 $7 {- 'IfStatement4' -} } -- IterationStatement : See 12.6 -- do Statement while ( Expression ); -- while ( Expression ) Statement -- for (ExpressionNoInopt; Expressionopt ; Expressionopt ) Statement -- for ( var VariableDeclarationListNoIn; Expressionopt ; Expressionopt ) Statement -- for ( LeftHandSideExpression in Expression ) Statement -- for ( var VariableDeclarationNoIn in Expression ) Statement IterationStatement :: { AST.JSStatement } IterationStatement : Do StatementNoEmpty While LParen Expression RParen MaybeSemi { AST.JSDoWhile $1 $2 $3 $4 $5 $6 $7 {- 'IterationStatement1' -} } | While LParen Expression RParen Statement { AST.JSWhile $1 $2 $3 $4 $5 {- 'IterationStatement2' -} } | For LParen ExpressionNoInOpt Semi ExpressionOpt Semi ExpressionOpt RParen Statement { AST.JSFor $1 $2 $3 $4 $5 $6 $7 $8 $9 {- 'IterationStatement3' -} } | For LParen Var VariableDeclarationListNoIn Semi ExpressionOpt Semi ExpressionOpt RParen Statement { AST.JSForVar $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 {- 'IterationStatement4' -} } | For LParen LeftHandSideExpression In Expression RParen Statement { AST.JSForIn $1 $2 $3 $4 $5 $6 $7 {- 'IterationStatement 5' -} } | For LParen Var VariableDeclarationNoIn In Expression RParen Statement { AST.JSForVarIn $1 $2 $3 $4 $5 $6 $7 $8 {- 'IterationStatement6' -} } | For LParen Let VariableDeclarationListNoIn Semi ExpressionOpt Semi ExpressionOpt RParen Statement { AST.JSForLet $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 {- 'IterationStatement 7' -} } | For LParen Let VariableDeclarationNoIn In Expression RParen Statement { AST.JSForLetIn $1 $2 $3 $4 $5 $6 $7 $8 {- 'IterationStatement 8' -} } | For LParen Let VariableDeclarationNoIn Of Expression RParen Statement { AST.JSForLetOf $1 $2 $3 $4 $5 $6 $7 $8 {- 'IterationStatement 9' -} } | For LParen LeftHandSideExpression Of Expression RParen Statement { AST.JSForOf $1 $2 $3 $4 $5 $6 $7 {- 'IterationStatement 10'-} } | For LParen Var VariableDeclarationNoIn Of Expression RParen Statement { AST.JSForVarOf $1 $2 $3 $4 $5 $6 $7 $8 {- 'IterationStatement 11' -} } | For LParen Const VariableDeclarationListNoIn Semi ExpressionOpt Semi ExpressionOpt RParen Statement { AST.JSForConst $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 {- 'IterationStatement 12' -} } | For LParen Const VariableDeclarationNoIn In Expression RParen Statement { AST.JSForConstIn $1 $2 $3 $4 $5 $6 $7 $8 {- 'IterationStatement 13' -} } | For LParen Const VariableDeclarationNoIn Of Expression RParen Statement { AST.JSForConstOf $1 $2 $3 $4 $5 $6 $7 $8 {- 'IterationStatement 14' -} } -- ContinueStatement : See 12.7 -- continue [no LineTerminator here] Identifieropt ; ContinueStatement :: { AST.JSStatement } ContinueStatement : Continue AutoSemi { AST.JSContinue $1 AST.JSIdentNone $2 {- 'ContinueStatement1' -} } | Continue Identifier MaybeSemi { AST.JSContinue $1 (identName $2) $3 {- 'ContinueStatement2' -} } -- BreakStatement : See 12.8 -- break [no LineTerminator here] Identifieropt ; BreakStatement :: { AST.JSStatement } BreakStatement : Break AutoSemi { AST.JSBreak $1 AST.JSIdentNone $2 {- 'BreakStatement1' -} } | Break Identifier MaybeSemi { AST.JSBreak $1 (identName $2) $3 {- 'BreakStatement2' -} } -- ReturnStatement : See 12.9 -- return [no LineTerminator here] Expressionopt ; ReturnStatement :: { AST.JSStatement } ReturnStatement : Return AutoSemi { AST.JSReturn $1 Nothing $2 } | Return Expression MaybeSemi { AST.JSReturn $1 (Just $2) $3 } -- WithStatement : See 12.10 -- with ( Expression ) Statement WithStatement :: { AST.JSStatement } WithStatement : With LParen Expression RParen Statement MaybeSemi { AST.JSWith $1 $2 $3 $4 $5 $6 } -- SwitchStatement : See 12.11 -- switch ( Expression ) CaseBlock SwitchStatement :: { AST.JSStatement } SwitchStatement : Switch LParen Expression RParen LBrace CaseBlock RBrace MaybeSemi { AST.JSSwitch $1 $2 $3 $4 $5 $6 $7 $8 } -- CaseBlock : See 12.11 -- { CaseClausesopt } -- { CaseClausesopt DefaultClause CaseClausesopt } CaseBlock :: { [AST.JSSwitchParts] } CaseBlock : CaseClausesOpt { $1 {- 'CaseBlock1' -} } | CaseClausesOpt DefaultClause CaseClausesOpt { $1++[$2]++$3 {- 'CaseBlock2' -} } -- CaseClauses : See 12.11 -- CaseClause -- CaseClauses CaseClause CaseClausesOpt :: { [AST.JSSwitchParts] } CaseClausesOpt : CaseClause { [$1] {- 'CaseClausesOpt1' -} } | CaseClausesOpt CaseClause { ($1++[$2]) {- 'CaseClausesOpt2' -} } | { [] {- 'CaseClausesOpt3' -} } -- CaseClause : See 12.11 -- case Expression : StatementListopt CaseClause :: { AST.JSSwitchParts } CaseClause : Case Expression Colon StatementList { AST.JSCase $1 $2 $3 $4 {- 'CaseClause1' -} } | Case Expression Colon { AST.JSCase $1 $2 $3 [] {- 'CaseClause2' -} } -- DefaultClause : See 12.11 -- default : StatementListopt DefaultClause :: { AST.JSSwitchParts } DefaultClause : Default Colon { AST.JSDefault $1 $2 [] {- 'DefaultClause1' -} } | Default Colon StatementList { AST.JSDefault $1 $2 $3 {- 'DefaultClause2' -} } -- LabelledStatement : See 12.12 -- Identifier : Statement LabelledStatement :: { AST.JSStatement } LabelledStatement : Identifier Colon Statement { AST.JSLabelled (identName $1) $2 $3 {- 'LabelledStatement' -} } -- ThrowStatement : See 12.13 -- throw [no LineTerminator here] Expression ; ThrowStatement :: { AST.JSStatement } ThrowStatement : Throw Expression MaybeSemi { AST.JSThrow $1 $2 $3 {- 'ThrowStatement' -} } -- Note: worked in updated syntax as per https://developer.mozilla.org/en/JavaScript/Reference/Statements/try...catch -- i.e., 0 or more catches, then an optional finally -- TryStatement : See 12.14 -- try Block Catch -- try Block Finally -- try Block Catch Finally TryStatement :: { AST.JSStatement } TryStatement : Try Block Catches { AST.JSTry $1 $2 $3 AST.JSNoFinally {- 'TryStatement1' -} } | Try Block Finally { AST.JSTry $1 $2 [] $3 {- 'TryStatement2' -} } | Try Block Catches Finally { AST.JSTry $1 $2 $3 $4 {- 'TryStatement3' -} } Catches :: { [AST.JSTryCatch] } Catches : Catch { [$1] {- 'Catches1' -} } | Catches Catch { ($1++[$2]) {- 'Catches2' -} } -- Note: worked in updated syntax as per https://developer.mozilla.org/en/JavaScript/Reference/Statements/try...catch -- ::= 'catch' '(' Identifier ')' -- becomes -- ::= 'catch' '(' Identifier ')' -- | 'catch' '(' Identifier 'if' ConditionalExpression ')' Catch :: { AST.JSTryCatch } Catch : CatchL LParen Identifier RParen Block { AST.JSCatch $1 $2 $3 $4 $5 {- 'Catch1' -} } | CatchL LParen Identifier If ConditionalExpression RParen Block { AST.JSCatchIf $1 $2 $3 $4 $5 $6 $7 {- 'Catch2' -} } -- Finally : See 12.14 -- finally Block Finally :: { AST.JSTryFinally } Finally : FinallyL Block { AST.JSFinally $1 $2 {- 'Finally' -} } -- DebuggerStatement : See 12.15 -- debugger ; DebuggerStatement :: { AST.JSStatement } DebuggerStatement : 'debugger' MaybeSemi { AST.JSExpressionStatement (AST.JSLiteral (mkJSAnnot $1) "debugger") $2 {- 'DebuggerStatement' -} } -- FunctionDeclaration : See clause 13 -- function Identifier ( FormalParameterListopt ) { FunctionBody } FunctionDeclaration :: { AST.JSStatement } FunctionDeclaration : NamedFunctionExpression MaybeSemi { expressionToStatement $1 $2 {- 'FunctionDeclaration1' -} } -- FunctionExpression : See clause 13 -- function Identifieropt ( FormalParameterListopt ) { FunctionBody } FunctionExpression :: { AST.JSExpression } FunctionExpression : ArrowFunctionExpression { $1 {- 'ArrowFunctionExpression' -} } | LambdaExpression { $1 {- 'FunctionExpression1' -} } | NamedFunctionExpression { $1 {- 'FunctionExpression2' -} } ArrowFunctionExpression :: { AST.JSExpression } ArrowFunctionExpression : ArrowParameterList Arrow StatementOrBlock { AST.JSArrowExpression $1 $2 $3 } ArrowParameterList :: { AST.JSArrowParameterList } ArrowParameterList : PrimaryExpression {%^ toArrowParameterList $1 } | LParen RParen { AST.JSParenthesizedArrowParameterList $1 AST.JSLNil $2 } StatementOrBlock :: { AST.JSStatement } StatementOrBlock : Block MaybeSemi { blockToStatement $1 $2 } | Expression MaybeSemi { expressionToStatement $1 $2 } -- StatementListItem : -- Statement -- Declaration StatementListItem :: { AST.JSStatement } StatementListItem : Statement { $1 } NamedFunctionExpression :: { AST.JSExpression } NamedFunctionExpression : Function Identifier LParen RParen FunctionBody { AST.JSFunctionExpression $1 (identName $2) $3 AST.JSLNil $4 $5 {- 'NamedFunctionExpression1' -} } | Function Identifier LParen FormalParameterList RParen FunctionBody { AST.JSFunctionExpression $1 (identName $2) $3 $4 $5 $6 {- 'NamedFunctionExpression2' -} } LambdaExpression :: { AST.JSExpression } LambdaExpression : Function LParen RParen FunctionBody { AST.JSFunctionExpression $1 AST.JSIdentNone $2 AST.JSLNil $3 $4 {- 'LambdaExpression1' -} } | Function LParen FormalParameterList RParen FunctionBody { AST.JSFunctionExpression $1 AST.JSIdentNone $2 $3 $4 $5 {- 'LambdaExpression2' -} } -- GeneratorDeclaration : -- function * BindingIdentifier ( FormalParameters ) { GeneratorBody } -- function * ( FormalParameters ) { GeneratorBody } GeneratorDeclaration :: { AST.JSStatement } GeneratorDeclaration : NamedGeneratorExpression MaybeSemi { expressionToStatement $1 $2 } -- GeneratorExpression : -- function * BindingIdentifieropt ( FormalParameters ) { GeneratorBody } -- GeneratorBody : -- FunctionBody GeneratorExpression :: { AST.JSExpression } GeneratorExpression : NamedGeneratorExpression { $1 } | Function '*' LParen RParen FunctionBody { AST.JSGeneratorExpression $1 (mkJSAnnot $2) AST.JSIdentNone $3 AST.JSLNil $4 $5 } | Function '*' LParen FormalParameterList RParen FunctionBody { AST.JSGeneratorExpression $1 (mkJSAnnot $2) AST.JSIdentNone $3 $4 $5 $6 } NamedGeneratorExpression :: { AST.JSExpression } NamedGeneratorExpression : Function '*' Identifier LParen RParen FunctionBody { AST.JSGeneratorExpression $1 (mkJSAnnot $2) (identName $3) $4 AST.JSLNil $5 $6 } | Function '*' Identifier LParen FormalParameterList RParen FunctionBody { AST.JSGeneratorExpression $1 (mkJSAnnot $2) (identName $3) $4 $5 $6 $7 } -- YieldExpression : -- yield -- yield [no LineTerminator here] AssignmentExpression -- yield [no LineTerminator here] * AssignmentExpression YieldExpression :: { AST.JSExpression } YieldExpression : Yield { AST.JSYieldExpression $1 Nothing } | Yield AssignmentExpression { AST.JSYieldExpression $1 (Just $2) } | Yield '*' AssignmentExpression { AST.JSYieldFromExpression $1 (mkJSAnnot $2) $3 } IdentifierOpt :: { AST.JSIdent } IdentifierOpt : Identifier { identName $1 {- 'IdentifierOpt1' -} } | { AST.JSIdentNone {- 'IdentifierOpt2' -} } -- FormalParameterList : See clause 13 -- Identifier -- FormalParameterList , Identifier FormalParameterList :: { AST.JSCommaList AST.JSExpression } FormalParameterList : AssignmentExpression { AST.JSLOne $1 {- 'FormalParameterList1' -} } | FormalParameterList Comma AssignmentExpression { AST.JSLCons $1 $2 $3 {- 'FormalParameterList2' -} } -- FunctionBody : See clause 13 -- SourceElementsopt FunctionBody :: { AST.JSBlock } FunctionBody : Block { $1 {- 'FunctionBody1' -} } -- ClassDeclaration : -- class BindingIdentifier ClassTail -- class ClassTail -- ClassExpression : -- class BindingIdentifieropt ClassTail -- ClassTail : -- ClassHeritageopt { ClassBodyopt } ClassDeclaration :: { AST.JSStatement } ClassDeclaration : Class Identifier ClassHeritage LBrace ClassBody RBrace { AST.JSClass $1 (identName $2) $3 $4 $5 $6 AST.JSSemiAuto } ClassExpression :: { AST.JSExpression } ClassExpression : Class Identifier ClassHeritage LBrace ClassBody RBrace { AST.JSClassExpression $1 (identName $2) $3 $4 $5 $6 } | Class ClassHeritage LBrace ClassBody RBrace { AST.JSClassExpression $1 AST.JSIdentNone $2 $3 $4 $5 } -- ClassHeritage : -- extends LeftHandSideExpression ClassHeritage :: { AST.JSClassHeritage } ClassHeritage : Extends LeftHandSideExpression { AST.JSExtends $1 $2 } | { AST.JSExtendsNone } -- ClassBody : -- ClassElementList -- ClassElementList : -- ClassElement -- ClassElementList ClassElement ClassBody :: { [AST.JSClassElement] } ClassBody : { [] } | ClassBody ClassElement { $1 ++ [$2] } -- ClassElement : -- MethodDefinition -- static MethodDefinition -- ; ClassElement :: { AST.JSClassElement } ClassElement : MethodDefinition { AST.JSClassInstanceMethod $1 } | Static MethodDefinition { AST.JSClassStaticMethod $1 $2 } | Semi { AST.JSClassSemi $1 } -- Program : See clause 14 -- SourceElementsopt Program :: { AST.JSAST } Program : StatementList Eof { AST.JSAstProgram $1 $2 {- 'Program1' -} } | Eof { AST.JSAstProgram [] $1 {- 'Program2' -} } -- Module : See 15.2 -- ModuleBody[opt] -- -- ModuleBody : -- ModuleItemList Module :: { AST.JSAST } Module : ModuleItemList Eof { AST.JSAstModule $1 $2 {- 'Module1' -} } | Eof { AST.JSAstModule [] $1 {- 'Module2' -} } -- ModuleItemList : -- ModuleItem -- ModuleItemList ModuleItem ModuleItemList :: { [AST.JSModuleItem] } ModuleItemList : ModuleItem { [$1] {- 'ModuleItemList1' -} } | ModuleItemList ModuleItem { ($1++[$2]) {- 'ModuleItemList2' -} } -- ModuleItem : -- ImportDeclaration -- ExportDeclaration -- StatementListItem ModuleItem :: { AST.JSModuleItem } ModuleItem : Import ImportDeclaration { AST.JSModuleImportDeclaration $1 $2 {- 'ModuleItem1' -} } | Export ExportDeclaration { AST.JSModuleExportDeclaration $1 $2 {- 'ModuleItem1' -} } | StatementListItem { AST.JSModuleStatementListItem $1 {- 'ModuleItem2' -} } ImportDeclaration :: { AST.JSImportDeclaration } ImportDeclaration : ImportClause FromClause AutoSemi { AST.JSImportDeclaration $1 $2 $3 } | 'string' AutoSemi { AST.JSImportDeclarationBare (mkJSAnnot $1) (tokenLiteral $1) $2 } ImportClause :: { AST.JSImportClause } ImportClause : IdentifierName { AST.JSImportClauseDefault (identName $1) } | NameSpaceImport { AST.JSImportClauseNameSpace $1 } | NamedImports { AST.JSImportClauseNamed $1 } | IdentifierName ',' NameSpaceImport { AST.JSImportClauseDefaultNameSpace (identName $1) (mkJSAnnot $2) $3 } | IdentifierName ',' NamedImports { AST.JSImportClauseDefaultNamed (identName $1) (mkJSAnnot $2) $3 } FromClause :: { AST.JSFromClause } FromClause : From 'string' { AST.JSFromClause $1 (mkJSAnnot $2) (tokenLiteral $2) } NameSpaceImport :: { AST.JSImportNameSpace } NameSpaceImport : Mul As IdentifierName { AST.JSImportNameSpace $1 $2 (identName $3) } NamedImports :: { AST.JSImportsNamed } NamedImports : LBrace ImportsList RBrace { AST.JSImportsNamed $1 $2 $3 } ImportsList :: { AST.JSCommaList AST.JSImportSpecifier } ImportsList : ImportSpecifier { AST.JSLOne $1 } | ImportsList Comma ImportSpecifier { AST.JSLCons $1 $2 $3 } ImportSpecifier :: { AST.JSImportSpecifier } ImportSpecifier : IdentifierName { AST.JSImportSpecifier (identName $1) } | IdentifierName As IdentifierName { AST.JSImportSpecifierAs (identName $1) $2 (identName $3) } -- ExportDeclaration : See 15.2.3 -- [ ] export * FromClause ; -- [x] export ExportClause FromClause ; -- [x] export ExportClause ; -- [x] export VariableStatement -- [ ] export Declaration -- [ ] Declaration : -- [ ] HoistableDeclaration -- [x] ClassDeclaration -- [x] LexicalDeclaration -- [ ] HoistableDeclaration : -- [x] FunctionDeclaration -- [x] GeneratorDeclaration -- [ ] AsyncFunctionDeclaration -- [ ] AsyncGeneratorDeclaration -- [ ] export default HoistableDeclaration[Default] -- [ ] export default ClassDeclaration[Default] -- [ ] export default [lookahead ∉ { function, class }] AssignmentExpression[In] ; ExportDeclaration :: { AST.JSExportDeclaration } ExportDeclaration : ExportClause FromClause AutoSemi { AST.JSExportFrom $1 $2 $3 {- 'ExportDeclaration1' -} } | ExportClause AutoSemi { AST.JSExportLocals $1 $2 {- 'ExportDeclaration2' -} } | VariableStatement AutoSemi { AST.JSExport $1 $2 {- 'ExportDeclaration3' -} } | FunctionDeclaration AutoSemi { AST.JSExport $1 $2 {- 'ExportDeclaration4' -} } | GeneratorDeclaration AutoSemi { AST.JSExport $1 $2 {- 'ExportDeclaration5' -} } | ClassDeclaration AutoSemi { AST.JSExport $1 $2 {- 'ExportDeclaration6' -} } -- ExportClause : -- { } -- { ExportsList } -- { ExportsList , } ExportClause :: { AST.JSExportClause } ExportClause : LBrace RBrace { AST.JSExportClause $1 AST.JSLNil $2 {- 'ExportClause1' -} } | LBrace ExportsList RBrace { AST.JSExportClause $1 $2 $3 {- 'ExportClause2' -} } -- ExportsList : -- ExportSpecifier -- ExportsList , ExportSpecifier ExportsList :: { AST.JSCommaList AST.JSExportSpecifier } ExportsList : ExportSpecifier { AST.JSLOne $1 {- 'ExportsList1' -} } | ExportsList Comma ExportSpecifier { AST.JSLCons $1 $2 $3 {- 'ExportsList2' -} } -- ExportSpecifier : -- IdentifierName -- IdentifierName as IdentifierName ExportSpecifier :: { AST.JSExportSpecifier } ExportSpecifier : IdentifierName { AST.JSExportSpecifier (identName $1) {- 'ExportSpecifier1' -} } | IdentifierName As IdentifierName { AST.JSExportSpecifierAs (identName $1) $2 (identName $3) {- 'ExportSpecifier2' -} } -- For debugging/other entry points LiteralMain :: { AST.JSAST } LiteralMain : Literal Eof { AST.JSAstLiteral $1 $2 {- 'LiteralMain' -} } ExpressionMain :: { AST.JSAST } ExpressionMain : Expression Eof { AST.JSAstExpression $1 $2 {- 'ExpressionMain' -} } StatementMain :: { AST.JSAST } StatementMain : StatementNoEmpty Eof { AST.JSAstStatement $1 $2 {- 'StatementMain' -} } { -- Need this type while build the AST, but is not actually part of the AST. data JSArguments = JSArguments AST.JSAnnot (AST.JSCommaList AST.JSExpression) AST.JSAnnot -- ^lb, args, rb data JSUntaggedTemplate = JSUntaggedTemplate !AST.JSAnnot !String ![AST.JSTemplatePart] -- lquot, head, parts blockToStatement :: AST.JSBlock -> AST.JSSemi -> AST.JSStatement blockToStatement (AST.JSBlock a b c) s = AST.JSStatementBlock a b c s expressionToStatement :: AST.JSExpression -> AST.JSSemi -> AST.JSStatement expressionToStatement (AST.JSFunctionExpression a b@(AST.JSIdentName{}) c d e f) s = AST.JSFunction a b c d e f s expressionToStatement (AST.JSGeneratorExpression a b c@(AST.JSIdentName{}) d e f g) s = AST.JSGenerator a b c d e f g s expressionToStatement (AST.JSAssignExpression lhs op rhs) s = AST.JSAssignStatement lhs op rhs s expressionToStatement (AST.JSMemberExpression e l a r) s = AST.JSMethodCall e l a r s expressionToStatement (AST.JSClassExpression a b@(AST.JSIdentName{}) c d e f) s = AST.JSClass a b c d e f s expressionToStatement exp s = AST.JSExpressionStatement exp s mkJSCallExpression :: AST.JSExpression -> JSArguments -> AST.JSExpression mkJSCallExpression e (JSArguments l arglist r) = AST.JSCallExpression e l arglist r mkJSMemberExpression :: AST.JSExpression -> JSArguments -> AST.JSExpression mkJSMemberExpression e (JSArguments l arglist r) = AST.JSMemberExpression e l arglist r mkJSMemberNew :: AST.JSAnnot -> AST.JSExpression -> JSArguments -> AST.JSExpression mkJSMemberNew a e (JSArguments l arglist r) = AST.JSMemberNew a e l arglist r parseError :: Token -> Alex a parseError = alexError . show mkJSAnnot :: Token -> AST.JSAnnot mkJSAnnot a = AST.JSAnnot (tokenSpan a) (tokenComment a) mkJSTemplateLiteral :: Maybe AST.JSExpression -> JSUntaggedTemplate -> AST.JSExpression mkJSTemplateLiteral tag (JSUntaggedTemplate a h ps) = AST.JSTemplateLiteral tag a h ps -- --------------------------------------------------------------------- -- | mkUnary : The parser detects '+' and '-' as the binary version of these -- operator. This function converts from the binary version to the unary -- version. mkUnary :: AST.JSBinOp -> AST.JSUnaryOp mkUnary (AST.JSBinOpMinus annot) = AST.JSUnaryOpMinus annot mkUnary (AST.JSBinOpPlus annot) = AST.JSUnaryOpPlus annot mkUnary x = error $ "Invalid unary op : " ++ show x identName :: AST.JSExpression -> AST.JSIdent identName (AST.JSIdentifier a s) = AST.JSIdentName a s identName x = error $ "Cannot convert '" ++ show x ++ "' to a JSIdentName." propName :: AST.JSExpression -> AST.JSPropertyName propName (AST.JSIdentifier a s) = AST.JSPropertyIdent a s propName (AST.JSDecimal a s) = AST.JSPropertyNumber a s propName (AST.JSHexInteger a s) = AST.JSPropertyNumber a s propName (AST.JSOctal a s) = AST.JSPropertyNumber a s propName (AST.JSStringLiteral a s) = AST.JSPropertyString a s propName x = error $ "Cannot convert '" ++ show x ++ "' to a JSPropertyName." identifierToProperty :: AST.JSExpression -> AST.JSObjectProperty identifierToProperty (AST.JSIdentifier a s) = AST.JSPropertyIdentRef a s identifierToProperty x = error $ "Cannot convert '" ++ show x ++ "' to a JSObjectProperty." toArrowParameterList :: AST.JSExpression -> Token -> Alex AST.JSArrowParameterList toArrowParameterList (AST.JSIdentifier a s) = const . return $ AST.JSUnparenthesizedArrowParameter (AST.JSIdentName a s) toArrowParameterList (AST.JSExpressionParen lb x rb) = const . return $ AST.JSParenthesizedArrowParameterList lb (commasToCommaList x) rb toArrowParameterList _ = parseError commasToCommaList :: AST.JSExpression -> AST.JSCommaList AST.JSExpression commasToCommaList (AST.JSCommaExpression l c r) = AST.JSLCons (commasToCommaList l) c r commasToCommaList x = AST.JSLOne x }