{ {-# LANGUAGE BangPatterns #-} module Language.JavaScript.Parser.Grammar5 ( parseProgram , parseLiteral , parsePrimaryExpression , parseStatement -- debug , fp ) where -- import Control.Monad.Error.Class (throwError) import Data.Char import Language.JavaScript.Parser.Lexer import Language.JavaScript.Parser.ParseError 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 parseLiteral LiteralMain %name parsePrimaryExpression PrimaryExpressionMain %name parseStatement StatementMain %tokentype { Token } %error { parseError } %monad { Alex } { >>= } { return } %lexer { lexCont } { EOFToken {} } %token ';' { SemiColonToken {} } ',' { CommaToken {} } '?' { HookToken {} } ':' { ColonToken {} } '||' { OrToken {} } '&&' { AndToken {} } '|' { BitwiseOrToken {} } '^' { BitwiseXorToken {} } '&' { BitwiseAndToken {} } '===' { StrictEqToken {} } '==' { EqToken {} } '=' { SimpleAssignToken {} } '!==' { StrictNeToken {} } '!=' { NeToken {} } '<<' { LshToken {} } '<=' { LeToken {} } '<' { LtToken {} } '>>>' { UrshToken {} } '>>' { RshToken {} } '>=' { GeToken {} } '>' { GtToken {} } '++' { IncrementToken {} } '--' { DecrementToken {} } '+' { PlusToken {} } '-' { MinusToken {} } '*' { MulToken {} } '/' { DivToken {} } '%' { ModToken {} } '!' { NotToken {} } '~' { BitwiseNotToken {} } '.' { DotToken {} } '[' { LeftBracketToken {} } ']' { RightBracketToken {} } '{' { LeftCurlyToken {} } '}' { RightCurlyToken {} } '(' { LeftParenToken {} } ')' { RightParenToken {} } '@*/' { CondcommentEndToken {} } 'break' { BreakToken {} } 'case' { CaseToken {} } 'catch' { CatchToken {} } 'const' { ConstToken {} } 'continue' { ContinueToken {} } 'debugger' { DebuggerToken {} } 'default' { DefaultToken {} } 'delete' { DeleteToken {} } 'do' { DoToken {} } 'else' { ElseToken {} } 'enum' { EnumToken {} } 'false' { FalseToken {} } 'finally' { FinallyToken {} } 'for' { ForToken {} } 'function' { FunctionToken {} } 'get' { GetToken {} } 'if' { IfToken {} } 'in' { InToken {} } 'instanceof' { InstanceofToken {} } 'new' { NewToken {} } 'null' { NullToken {} } 'return' { ReturnToken {} } 'set' { SetToken {} } 'switch' { SwitchToken {} } 'this' { ThisToken {} } 'throw' { ThrowToken {} } 'true' { TrueToken {} } 'try' { TryToken {} } 'typeof' { TypeofToken {} } 'var' { VarToken {} } 'void' { VoidToken {} } 'while' { WhileToken {} } 'with' { WithToken {} } 'ident' { IdentifierToken {} } 'decimal' { DecimalToken {} } 'hexinteger' { HexIntegerToken {} } 'octal' { OctalToken {} } 'string' { StringToken {} } 'regex' { RegExToken {} } 'assign' { AssignToken {} } 'future' { FutureToken {} } 'tail' { TailToken {} } 'eof' { EOFToken {} } %% -- --------------------------------------------------------------------- -- Sort out automatically inserted semi-colons AutoSemi :: { AST.JSNode } AutoSemi : ';' { AST.NT (AST.JSLiteral ";") (ss $1) (gc $1)} | { AST.NT (AST.JSLiteral "") tokenPosnEmpty []} -- --------------------------------------------------------------------- -- Helpers LParen :: { AST.JSNode } LParen : '(' { fp (AST.NT (AST.JSLiteral "(") (ss $1) (gc $1))} RParen :: { AST.JSNode } RParen : ')' { fp (AST.NT (AST.JSLiteral ")") (ss $1) (gc $1))} LBrace :: { AST.JSNode } LBrace : '{' { fp (AST.NT (AST.JSLiteral "{") (ss $1) (gc $1))} RBrace :: { AST.JSNode } RBrace : '}' { fp (AST.NT (AST.JSLiteral "}") (ss $1) (gc $1))} LSquare :: { AST.JSNode } LSquare : '[' { fp (AST.NT (AST.JSLiteral "[") (ss $1) (gc $1))} RSquare :: { AST.JSNode } RSquare : ']' { fp (AST.NT (AST.JSLiteral "]") (ss $1) (gc $1))} Comma :: { AST.JSNode } Comma : ',' { fp (AST.NT (AST.JSLiteral ",") (ss $1) (gc $1))} Colon :: { AST.JSNode } Colon : ':' { fp (AST.NT (AST.JSLiteral ":") (ss $1) (gc $1))} Semi :: { AST.JSNode } Semi : ';' { fp (AST.NT (AST.JSLiteral ";") (ss $1) (gc $1))} Dot :: { AST.JSNode } Dot : '.' { fp (AST.NT (AST.JSLiteral ".") (ss $1) (gc $1))} Increment :: { AST.JSNode } Increment : '++' { fp (AST.NT (AST.JSLiteral "++") (ss $1) (gc $1))} Decrement :: { AST.JSNode } Decrement : '--' { fp (AST.NT (AST.JSLiteral "--") (ss $1) (gc $1))} Delete :: { AST.JSNode } Delete : 'delete' { fp (AST.NT (AST.JSLiteral "delete") (ss $1) (gc $1))} Void :: { AST.JSNode } Void : 'void' { fp (AST.NT (AST.JSLiteral "void") (ss $1) (gc $1))} Typeof :: { AST.JSNode } Typeof : 'typeof' { fp (AST.NT (AST.JSLiteral "typeof") (ss $1) (gc $1))} Plus :: { AST.JSNode } Plus : '+' { fp (AST.NT (AST.JSLiteral "+") (ss $1) (gc $1))} Minus :: { AST.JSNode } Minus : '-' { fp (AST.NT (AST.JSLiteral "-") (ss $1) (gc $1))} Tilde :: { AST.JSNode } Tilde : '~' { fp (AST.NT (AST.JSLiteral "~") (ss $1) (gc $1))} Not :: { AST.JSNode } Not : '!' { fp (AST.NT (AST.JSLiteral "!") (ss $1) (gc $1))} Mul :: { AST.JSNode } Mul : '*' { fp (AST.NT (AST.JSLiteral "*") (ss $1) (gc $1))} Div :: { AST.JSNode } Div : '/' { fp (AST.NT (AST.JSLiteral "/") (ss $1) (gc $1))} Mod :: { AST.JSNode } Mod : '%' { fp (AST.NT (AST.JSLiteral "%") (ss $1) (gc $1))} Lsh :: { AST.JSNode } Lsh : '<<' { fp (AST.NT (AST.JSLiteral "<<") (ss $1) (gc $1))} Rsh :: { AST.JSNode } Rsh : '>>' { fp (AST.NT (AST.JSLiteral ">>") (ss $1) (gc $1))} Ursh :: { AST.JSNode } Ursh : '>>>' { fp (AST.NT (AST.JSLiteral ">>>") (ss $1) (gc $1))} Le :: { AST.JSNode } Le : '<=' { fp (AST.NT (AST.JSLiteral "<=") (ss $1) (gc $1))} Lt :: { AST.JSNode } Lt : '<' { fp (AST.NT (AST.JSLiteral "<") (ss $1) (gc $1))} Ge :: { AST.JSNode } Ge : '>=' { fp (AST.NT (AST.JSLiteral ">=") (ss $1) (gc $1))} Gt :: { AST.JSNode } Gt : '>' { fp (AST.NT (AST.JSLiteral ">") (ss $1) (gc $1))} In :: { AST.JSNode } In : 'in' { fp (AST.NT (AST.JSLiteral "in") (ss $1) (gc $1))} Instanceof :: { AST.JSNode } Instanceof : 'instanceof' { fp (AST.NT (AST.JSLiteral "instanceof") (ss $1) (gc $1))} StrictEq :: { AST.JSNode } StrictEq : '===' { fp (AST.NT (AST.JSLiteral "===") (ss $1) (gc $1))} Equal :: { AST.JSNode } Equal : '==' { fp (AST.NT (AST.JSLiteral "==") (ss $1) (gc $1))} StrictNe :: { AST.JSNode } StrictNe : '!==' { fp (AST.NT (AST.JSLiteral "!==") (ss $1) (gc $1))} Ne :: { AST.JSNode } Ne : '!=' { fp (AST.NT (AST.JSLiteral "!=") (ss $1) (gc $1))} Or :: { AST.JSNode } Or : '||' { fp (AST.NT (AST.JSLiteral "||") (ss $1) (gc $1))} And :: { AST.JSNode } And : '&&' { fp (AST.NT (AST.JSLiteral "&&") (ss $1) (gc $1))} BitOr :: { AST.JSNode } BitOr : '|' { fp (AST.NT (AST.JSLiteral "|") (ss $1) (gc $1))} BitAnd :: { AST.JSNode } BitAnd : '&' { fp (AST.NT (AST.JSLiteral "&") (ss $1) (gc $1))} BitXor :: { AST.JSNode } BitXor : '^' { fp (AST.NT (AST.JSLiteral "^") (ss $1) (gc $1))} Hook :: { AST.JSNode } Hook : '?' { fp (AST.NT (AST.JSLiteral "?") (ss $1) (gc $1))} SimpleAssign :: { AST.JSNode } SimpleAssign : '=' { fp (AST.NT (AST.JSLiteral "=") (ss $1) (gc $1))} Assign :: { AST.JSNode } Assign : 'assign' { fp (AST.NT (AST.JSLiteral (token_literal $1)) (ss $1) (gc $1))} Var :: { AST.JSNode } Var : 'var' { fp (AST.NT (AST.JSLiteral "var") (ss $1) (gc $1))} Const :: { AST.JSNode } Const : 'const' { fp (AST.NT (AST.JSLiteral "const") (ss $1) (gc $1))} If :: { AST.JSNode } If : 'if' { fp (AST.NT (AST.JSLiteral "if") (ss $1) (gc $1))} Else :: { AST.JSNode } Else : 'else' { fp (AST.NT (AST.JSLiteral "else") (ss $1) (gc $1))} Do :: { AST.JSNode } Do : 'do' { fp (AST.NT (AST.JSLiteral "do") (ss $1) (gc $1))} While :: { AST.JSNode } While : 'while' { fp (AST.NT (AST.JSLiteral "while") (ss $1) (gc $1))} For :: { AST.JSNode } For : 'for' { fp (AST.NT (AST.JSLiteral "for") (ss $1) (gc $1))} Continue :: { AST.JSNode } Continue : 'continue' { fp (AST.NT (AST.JSLiteral "continue") (ss $1) (gc $1))} Break :: { AST.JSNode } Break : 'break' { fp (AST.NT (AST.JSLiteral "break") (ss $1) (gc $1))} Return :: { AST.JSNode } Return : 'return' { fp (AST.NT (AST.JSLiteral "return") (ss $1) (gc $1))} With :: { AST.JSNode } With : 'with' { fp (AST.NT (AST.JSLiteral "with") (ss $1) (gc $1))} Switch :: { AST.JSNode } Switch : 'switch' { fp (AST.NT (AST.JSLiteral "switch") (ss $1) (gc $1))} Case :: { AST.JSNode } Case : 'case' { fp (AST.NT (AST.JSLiteral "case") (ss $1) (gc $1))} Default :: { AST.JSNode } Default : 'default' { fp (AST.NT (AST.JSLiteral "default") (ss $1) (gc $1))} Throw :: { AST.JSNode } Throw : 'throw' { fp (AST.NT (AST.JSLiteral "throw") (ss $1) (gc $1))} Try :: { AST.JSNode } Try : 'try' { fp (AST.NT (AST.JSLiteral "try") (ss $1) (gc $1))} CatchL :: { AST.JSNode } CatchL : 'catch' { fp (AST.NT (AST.JSLiteral "catch") (ss $1) (gc $1))} FinallyL :: { AST.JSNode } FinallyL : 'finally' { fp (AST.NT (AST.JSLiteral "finally") (ss $1) (gc $1))} Function :: { AST.JSNode } Function : 'function' { fp (AST.NT (AST.JSLiteral "function") (ss $1) (gc $1))} Eof :: { AST.JSNode } Eof : 'tail' { fp (AST.NT (AST.JSLiteral "") (ss $1) (gc $1))} -- Literal :: See 7.8 -- NullLiteral -- BooleanLiteral -- NumericLiteral -- StringLiteral Literal :: { AST.JSNode } Literal : NullLiteral {$1} | BooleanLiteral {$1} | NumericLiteral {$1} | StringLiteral {$1} | RegularExpressionLiteral {$1} NullLiteral :: { AST.JSNode } NullLiteral : 'null' { fp (AST.NT (AST.JSLiteral "null") (ss $1) (gc $1))} BooleanLiteral :: { AST.JSNode } BooleanLiteral : 'true' { fp (AST.NT (AST.JSLiteral "true") (ss $1) (gc $1)) } | 'false' { fp (AST.NT (AST.JSLiteral "false") (ss $1) (gc $1)) } -- ::= DecimalLiteral -- | HexIntegerLiteral -- | OctalLiteral NumericLiteral :: { AST.JSNode } NumericLiteral : 'decimal' { fp (AST.NT (AST.JSDecimal (token_literal $1)) (ss $1) (gc $1))} | 'hexinteger' { fp (AST.NT (AST.JSHexInteger (token_literal $1)) (ss $1) (gc $1)) } | 'octal' { fp (AST.NT (AST.JSOctal (token_literal $1)) (ss $1) (gc $1)) } StringLiteral :: { AST.JSNode } StringLiteral : 'string' { fp (AST.NT (AST.JSStringLiteral (token_delimiter $1) (token_literal $1)) (ss $1) (gc $1)) } -- ::= RegExp RegularExpressionLiteral :: { AST.JSNode } RegularExpressionLiteral : 'regex' { fp (AST.NT (AST.JSRegEx (token_literal $1)) (ss $1) (gc $1)) } -- PrimaryExpression : See 11.1 -- this -- Identifier -- Literal -- ArrayLiteral -- ObjectLiteral -- ( Expression ) PrimaryExpression :: { AST.JSNode } PrimaryExpression : 'this' { fp (AST.NT (AST.JSLiteral "this") (ss $1) (gc $1))} | Identifier { $1 {- PrimaryExpression1 -}} | Literal { $1 {- PrimaryExpression2 -}} | ArrayLiteral { $1 {- PrimaryExpression3 -}} | ObjectLiteral { $1 {- PrimaryExpression4 -}} | LParen Expression RParen { fp (AST.NN (AST.JSExpressionParen $1 $2 $3)) } -- Identifier :: See 7.6 -- IdentifierName but not ReservedWord -- IdentifierName :: See 7.6 -- IdentifierStart -- IdentifierName IdentifierPart Identifier :: { AST.JSNode } Identifier : 'ident' { (AST.NT (AST.JSIdentifier (token_literal $1)) (ss $1) (gc $1))} | 'get' { (AST.NT (AST.JSIdentifier "get") (ss $1) (gc $1))} | 'set' { (AST.NT (AST.JSIdentifier "set") (ss $1) (gc $1))} -- TODO: make this include any reserved word too, including future ones IdentifierName :: { AST.JSNode } IdentifierName : Identifier {$1} | 'break' { fp (AST.NT (AST.JSIdentifier "break") (ss $1) (gc $1))} | 'case' { fp (AST.NT (AST.JSIdentifier "case") (ss $1) (gc $1))} | 'catch' { fp (AST.NT (AST.JSIdentifier "catch") (ss $1) (gc $1))} | 'const' { fp (AST.NT (AST.JSIdentifier "const") (ss $1) (gc $1))} | 'continue' { fp (AST.NT (AST.JSIdentifier "continue") (ss $1) (gc $1))} | 'debugger' { fp (AST.NT (AST.JSIdentifier "debugger") (ss $1) (gc $1))} | 'default' { fp (AST.NT (AST.JSIdentifier "default") (ss $1) (gc $1))} | 'delete' { fp (AST.NT (AST.JSIdentifier "delete") (ss $1) (gc $1))} | 'do' { fp (AST.NT (AST.JSIdentifier "do") (ss $1) (gc $1))} | 'else' { fp (AST.NT (AST.JSIdentifier "else") (ss $1) (gc $1))} | 'enum' { fp (AST.NT (AST.JSIdentifier "enum") (ss $1) (gc $1))} | 'false' { fp (AST.NT (AST.JSIdentifier "false") (ss $1) (gc $1))} | 'finally' { fp (AST.NT (AST.JSIdentifier "finally") (ss $1) (gc $1))} | 'for' { fp (AST.NT (AST.JSIdentifier "for") (ss $1) (gc $1))} | 'function' { fp (AST.NT (AST.JSIdentifier "function") (ss $1) (gc $1))} | 'get' { fp (AST.NT (AST.JSIdentifier "get") (ss $1) (gc $1))} | 'if' { fp (AST.NT (AST.JSIdentifier "if") (ss $1) (gc $1))} | 'in' { fp (AST.NT (AST.JSIdentifier "in") (ss $1) (gc $1))} | 'instanceof' { fp (AST.NT (AST.JSIdentifier "instanceof") (ss $1) (gc $1))} | 'new' { fp (AST.NT (AST.JSIdentifier "new") (ss $1) (gc $1))} | 'null' { fp (AST.NT (AST.JSIdentifier "null") (ss $1) (gc $1))} | 'return' { fp (AST.NT (AST.JSIdentifier "return") (ss $1) (gc $1))} | 'set' { fp (AST.NT (AST.JSIdentifier "set") (ss $1) (gc $1))} | 'switch' { fp (AST.NT (AST.JSIdentifier "switch") (ss $1) (gc $1))} | 'this' { fp (AST.NT (AST.JSIdentifier "this") (ss $1) (gc $1))} | 'throw' { fp (AST.NT (AST.JSIdentifier "throw") (ss $1) (gc $1))} | 'true' { fp (AST.NT (AST.JSIdentifier "true") (ss $1) (gc $1))} | 'try' { fp (AST.NT (AST.JSIdentifier "try") (ss $1) (gc $1))} | 'typeof' { fp (AST.NT (AST.JSIdentifier "typeof") (ss $1) (gc $1))} | 'var' { fp (AST.NT (AST.JSIdentifier "var") (ss $1) (gc $1))} | 'void' { fp (AST.NT (AST.JSIdentifier "void") (ss $1) (gc $1))} | 'while' { fp (AST.NT (AST.JSIdentifier "while") (ss $1) (gc $1))} | 'with' { fp (AST.NT (AST.JSIdentifier "with") (ss $1) (gc $1))} | 'future' { fp (AST.NT (AST.JSIdentifier (token_literal $1)) (ss $1) (gc $1))} -- ArrayLiteral : See 11.1.4 -- [ Elisionopt ] -- [ ElementList ] -- [ ElementList , Elisionopt ] ArrayLiteral :: { AST.JSNode } ArrayLiteral : LSquare RSquare { fp (AST.NN (AST.JSArrayLiteral $1 [] $2))} | LSquare Elision RSquare { fp (AST.NN (AST.JSArrayLiteral $1 $2 $3))} | LSquare ElementList RSquare { fp (AST.NN (AST.JSArrayLiteral $1 $2 $3))} | LSquare ElementList Comma Elision RSquare { fp (AST.NN (AST.JSArrayLiteral $1 ($2++[$3]++$4) $5))} | LSquare ElementList Comma RSquare { fp (AST.NN (AST.JSArrayLiteral $1 ($2++[$3]) $4))} -- ElementList : See 11.1.4 -- Elisionopt AssignmentExpression -- ElementList , Elisionopt AssignmentExpression ElementList :: { [AST.JSNode] } ElementList : Elision AssignmentExpression { (($1)++($2)) {- ElementList -}} | AssignmentExpression { $1 {- ElementList -}} | ElementList Comma Elision AssignmentExpression { (($1)++[fp (AST.NN (AST.JSElision $2))]++($3)++($4)) {- ElementList -}} | ElementList Comma AssignmentExpression { (($1)++[fp (AST.NN (AST.JSElision $2))]++($3)) {- ElementList -}} -- Elision : See 11.1.4 -- , -- Elision , Elision :: { [AST.JSNode] } Elision : Comma { [ fp (AST.NN (AST.JSElision $1))] } | Elision Comma { ($1 ++ [fp (AST.NN (AST.JSElision $2))]) } -- ObjectLiteral : See 11.1.5 -- { } -- { PropertyNameAndValueList } -- { PropertyNameAndValueList , } ObjectLiteral :: { AST.JSNode } ObjectLiteral : LBrace RBrace { fp (AST.NN (AST.JSObjectLiteral $1 [] $2) )} | LBrace PropertyNameandValueList RBrace { fp (AST.NN (AST.JSObjectLiteral $1 $2 $3) )} | LBrace PropertyNameandValueList Comma RBrace { fp (AST.NN (AST.JSObjectLiteral $1 ($2++[$3]) $4) )} -- ::= ':' -- | ',' ':' -- Seems we can have function declarations in the value part too -- PropertyNameAndValueList : See 11.1.5 -- PropertyAssignment -- PropertyNameAndValueList , PropertyAssignment PropertyNameandValueList :: { [ AST.JSNode ] } PropertyNameandValueList : PropertyAssignment { [$1] {- PropertyNameandValueList1 -} } | PropertyNameandValueList Comma PropertyAssignment { ($1++[$2]++[$3]) {- PropertyNameandValueList2 -} } -- PropertyAssignment : See 11.1.5 -- PropertyName : AssignmentExpression -- get PropertyName() { FunctionBody } -- set PropertyName( PropertySetParameterList ) { FunctionBody } -- TODO: not clear if get/set are keywords, or just used in a specific context. Puzzling. PropertyAssignment :: { AST.JSNode } PropertyAssignment : PropertyName Colon AssignmentExpression { fp (AST.NN (AST.JSPropertyNameandValue $1 $2 $3)) } -- Should be "get" in next, but is not a Token | 'get' PropertyName LParen RParen FunctionBody { fp (AST.NN (AST.JSPropertyAccessor (AST.NT (AST.JSLiteral "get") (ss $1) (gc $1)) $2 $3 [] $4 $5)) } -- Should be "set" in next, but is not a Token | 'set' PropertyName LParen PropertySetParameterList RParen FunctionBody { fp (AST.NN (AST.JSPropertyAccessor (AST.NT (AST.JSLiteral "set") (ss $1) (gc $1)) $2 $3 [$4] $5 $6)) } -- PropertyName : See 11.1.5 -- IdentifierName -- StringLiteral -- NumericLiteral PropertyName :: { AST.JSNode } PropertyName : IdentifierName { $1 {- PropertyName1 -}} | StringLiteral { $1 {- PropertyName2 -}} | NumericLiteral { $1 {- PropertyName3 -}} -- PropertySetParameterList : See 11.1.5 -- Identifier PropertySetParameterList :: { AST.JSNode } PropertySetParameterList : Identifier { $1 {- PropertySetParameterList -}} -- MemberExpression : See 11.2 -- PrimaryExpression -- FunctionExpression -- MemberExpression [ Expression ] -- MemberExpression . IdentifierName -- new MemberExpression Arguments MemberExpression :: { [AST.JSNode] } MemberExpression : PrimaryExpression { [$1] {- MemberExpression -}} | FunctionExpression { [$1] {- MemberExpression -}} | MemberExpression LSquare Expression RSquare { [fp (AST.NN (AST.JSMemberSquare $1 $2 $3 $4))] } | MemberExpression Dot IdentifierName { [fp (AST.NN (AST.JSMemberDot $1 $2 $3))] } | 'new' MemberExpression Arguments { (((fp (AST.NT (AST.JSLiteral "new") (ss $1) (gc $1))):$2)++[$3])} -- NewExpression : See 11.2 -- MemberExpression -- new NewExpression NewExpression :: { [AST.JSNode] } NewExpression : MemberExpression { $1 {- NewExpression -}} | 'new' NewExpression { (fp (AST.NT (AST.JSLiteral "new") (ss $1) (gc $1))):$2 } -- CallExpression : See 11.2 -- MemberExpression Arguments -- CallExpression Arguments -- CallExpression [ Expression ] -- CallExpression . IdentifierName CallExpression :: { [AST.JSNode] } CallExpression : MemberExpression Arguments { $1++[$2] {- CallExpression -} } | CallExpression Arguments { ($1++[fp (AST.NN (AST.JSCallExpression "()" [] [$2] []))]) } | CallExpression LSquare Expression RSquare { ($1++[fp (AST.NN (AST.JSCallExpression "[]" [$2] [$3] [$4]))]) } | CallExpression Dot IdentifierName { ($1++[fp (AST.NN (AST.JSCallExpression "." [$2] [$3] []))]) } -- Arguments : See 11.2 -- () -- ( ArgumentList ) Arguments :: { AST.JSNode } Arguments : LParen RParen { fp (AST.NN (AST.JSArguments $1 [] $2)) } | LParen ArgumentList RParen { fp (AST.NN (AST.JSArguments $1 $2 $3)) } -- ArgumentList : See 11.2 -- AssignmentExpression -- ArgumentList , AssignmentExpression ArgumentList :: { [AST.JSNode] } ArgumentList : AssignmentExpression { $1 {- ArgumentList -}} | ArgumentList Comma AssignmentExpression { $1++[$2]++$3 {- ArgumentList2 -} } -- LeftHandSideExpression : See 11.2 -- NewExpression -- CallExpression LeftHandSideExpression :: { [AST.JSNode] } LeftHandSideExpression : NewExpression { $1 {- LeftHandSideExpression1 -}} | CallExpression { $1 {- LeftHandSideExpression12 -}} -- PostfixExpression : See 11.3 -- LeftHandSideExpression -- [no LineTerminator here] -- LeftHandSideExpression ++ -- [no LineTerminator here] -- LeftHandSideExpression -- PostfixExpression :: { [AST.JSNode] } PostfixExpression : LeftHandSideExpression { $1 {- PostfixExpression -} } | PostfixExpression Increment {[fp (AST.NN (AST.JSExpressionPostfix "++" $1 $2))]} | PostfixExpression Decrement {[fp (AST.NN (AST.JSExpressionPostfix "--" $1 $2))]} -- UnaryExpression : See 11.4 -- PostfixExpression -- delete UnaryExpression -- void UnaryExpression -- typeof UnaryExpression -- ++ UnaryExpression -- -- UnaryExpression -- + UnaryExpression -- - UnaryExpression -- ~ UnaryExpression -- ! UnaryExpression UnaryExpression :: { [AST.JSNode] } UnaryExpression : PostfixExpression { $1 {- UnaryExpression -} } | Delete UnaryExpression { ((fp (AST.NN (AST.JSUnary "delete " $1))):$2)} | Void UnaryExpression { ((fp (AST.NN (AST.JSUnary "void " $1))):$2)} | Typeof UnaryExpression { ((fp (AST.NN (AST.JSUnary "typeof " $1))):$2)} | Increment UnaryExpression { ((fp (AST.NN (AST.JSUnary "++" $1))):$2) } | Decrement UnaryExpression { ((fp (AST.NN (AST.JSUnary "--" $1))):$2)} | Plus UnaryExpression { ((fp (AST.NN (AST.JSUnary "+" $1))):$2)} | Minus UnaryExpression { ((fp (AST.NN (AST.JSUnary "-" $1))):$2)} | Tilde UnaryExpression { ((fp (AST.NN (AST.JSUnary "~" $1))):$2)} | Not UnaryExpression { ((fp (AST.NN (AST.JSUnary "!" $1))):$2)} -- MultiplicativeExpression : See 11.5 -- UnaryExpression -- MultiplicativeExpression * UnaryExpression -- MultiplicativeExpression / UnaryExpression -- MultiplicativeExpression % UnaryExpression MultiplicativeExpression :: { [AST.JSNode] } MultiplicativeExpression : UnaryExpression { $1 {- MultiplicativeExpression -}} | MultiplicativeExpression Mul UnaryExpression { [fp (AST.NN (AST.JSExpressionBinary "*" $1 $2 $3))]} | MultiplicativeExpression Div UnaryExpression { [fp (AST.NN (AST.JSExpressionBinary "/" $1 $2 $3))]} | MultiplicativeExpression Mod UnaryExpression { [fp (AST.NN (AST.JSExpressionBinary "%" $1 $2 $3))]} -- AdditiveExpression : See 11.6 -- MultiplicativeExpression -- AdditiveExpression + MultiplicativeExpression -- AdditiveExpression - MultiplicativeExpression AdditiveExpression :: { [AST.JSNode] } AdditiveExpression : AdditiveExpression Plus MultiplicativeExpression { [fp (AST.NN (AST.JSExpressionBinary "+" $1 $2 $3))]} | AdditiveExpression Minus MultiplicativeExpression { [fp (AST.NN (AST.JSExpressionBinary "-" $1 $2 $3))]} | MultiplicativeExpression { $1 {- (goRegExp $1)-} {- AdditiveExpression -} } -- ShiftExpression : See 11.7 -- AdditiveExpression -- ShiftExpression << AdditiveExpression -- ShiftExpression >> AdditiveExpression -- ShiftExpression >>> AdditiveExpression ShiftExpression :: { [AST.JSNode] } ShiftExpression : ShiftExpression Lsh AdditiveExpression { [fp (AST.NN (AST.JSExpressionBinary "<<" $1 $2 $3))]} | ShiftExpression Rsh AdditiveExpression { [fp (AST.NN (AST.JSExpressionBinary ">>" $1 $2 $3))]} | ShiftExpression Ursh AdditiveExpression { [fp (AST.NN (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.JSNode] } RelationalExpression : ShiftExpression { $1 {- RelationalExpression -}} | RelationalExpression Lt ShiftExpression { [fp (AST.NN (AST.JSExpressionBinary "<" $1 $2 $3))]} | RelationalExpression Gt ShiftExpression { [fp (AST.NN (AST.JSExpressionBinary ">" $1 $2 $3))]} | RelationalExpression Le ShiftExpression { [fp (AST.NN (AST.JSExpressionBinary "<=" $1 $2 $3))]} | RelationalExpression Ge ShiftExpression { [fp (AST.NN (AST.JSExpressionBinary ">=" $1 $2 $3))]} | RelationalExpression Instanceof ShiftExpression { [fp (AST.NN (AST.JSExpressionBinary " instanceof " $1 $2 $3))]} | RelationalExpression In ShiftExpression { [fp (AST.NN (AST.JSExpressionBinary " in " $1 $2 $3))]} -- RelationalExpressionNoIn : See 11.8 -- ShiftExpression -- RelationalExpressionNoIn < ShiftExpression -- RelationalExpressionNoIn > ShiftExpression -- RelationalExpressionNoIn <= ShiftExpression -- RelationalExpressionNoIn >= ShiftExpression -- RelationalExpressionNoIn instanceof ShiftExpression RelationalExpressionNoIn :: { [AST.JSNode] } RelationalExpressionNoIn : ShiftExpression { $1 {- RelationalExpressionNoIn -}} | RelationalExpressionNoIn Lt ShiftExpression { [fp (AST.NN (AST.JSExpressionBinary "<" $1 $2 $3))]} | RelationalExpressionNoIn Gt ShiftExpression { [fp (AST.NN (AST.JSExpressionBinary ">" $1 $2 $3))]} | RelationalExpressionNoIn Le ShiftExpression { [fp (AST.NN (AST.JSExpressionBinary "<=" $1 $2 $3))]} | RelationalExpressionNoIn Ge ShiftExpression { [fp (AST.NN (AST.JSExpressionBinary ">=" $1 $2 $3))]} | RelationalExpressionNoIn Instanceof ShiftExpression { [fp (AST.NN (AST.JSExpressionBinary " instanceof " $1 $2 $3))]} -- EqualityExpression : See 11.9 -- RelationalExpression -- EqualityExpression == RelationalExpression -- EqualityExpression != RelationalExpression -- EqualityExpression === RelationalExpression -- EqualityExpression !== RelationalExpression EqualityExpression :: { [AST.JSNode] } EqualityExpression : RelationalExpression { $1 {- EqualityExpression -} } | EqualityExpression Equal RelationalExpression { [fp (AST.NN (AST.JSExpressionBinary "==" $1 $2 $3))]} | EqualityExpression Ne RelationalExpression { [fp (AST.NN (AST.JSExpressionBinary "!=" $1 $2 $3))]} | EqualityExpression StrictEq RelationalExpression { [fp (AST.NN (AST.JSExpressionBinary "===" $1 $2 $3))]} | EqualityExpression StrictNe RelationalExpression { [fp (AST.NN (AST.JSExpressionBinary "!==" $1 $2 $3))]} -- EqualityExpressionNoIn : See 11.9 -- RelationalExpressionNoIn -- EqualityExpressionNoIn == RelationalExpressionNoIn -- EqualityExpressionNoIn != RelationalExpressionNoIn -- EqualityExpressionNoIn === RelationalExpressionNoIn -- EqualityExpressionNoIn !== RelationalExpressionNoIn EqualityExpressionNoIn :: { [AST.JSNode] } EqualityExpressionNoIn : RelationalExpressionNoIn { $1 {- EqualityExpressionNoIn -} } | EqualityExpressionNoIn Equal RelationalExpression { [fp (AST.NN (AST.JSExpressionBinary "==" $1 $2 $3))]} | EqualityExpressionNoIn Ne RelationalExpression { [fp (AST.NN (AST.JSExpressionBinary "!=" $1 $2 $3))]} | EqualityExpressionNoIn StrictEq RelationalExpression { [fp (AST.NN (AST.JSExpressionBinary "===" $1 $2 $3))]} | EqualityExpressionNoIn StrictNe RelationalExpression { [fp (AST.NN (AST.JSExpressionBinary "!==" $1 $2 $3))]} -- BitwiseANDExpression : See 11.10 -- EqualityExpression -- BitwiseANDExpression & EqualityExpression BitwiseAndExpression :: { [AST.JSNode] } BitwiseAndExpression : EqualityExpression { $1 {- BitwiseAndExpression -} } | BitwiseAndExpression BitAnd EqualityExpression { [fp (AST.NN (AST.JSExpressionBinary "&" $1 $2 $3))]} -- BitwiseANDExpressionNoIn : See 11.10 -- EqualityExpressionNoIn -- BitwiseANDExpressionNoIn & EqualityExpressionNoIn BitwiseAndExpressionNoIn :: { [AST.JSNode] } BitwiseAndExpressionNoIn : EqualityExpressionNoIn { $1 {- BitwiseAndExpression -} } | BitwiseAndExpressionNoIn BitAnd EqualityExpressionNoIn { [fp (AST.NN (AST.JSExpressionBinary "&" $1 $2 $3))]} -- BitwiseXORExpression : See 11.10 -- BitwiseANDExpression -- BitwiseXORExpression ^ BitwiseANDExpression BitwiseXOrExpression :: { [AST.JSNode] } BitwiseXOrExpression : BitwiseAndExpression { $1 {- BitwiseXOrExpression -} } | BitwiseXOrExpression BitXor BitwiseAndExpression { [fp (AST.NN (AST.JSExpressionBinary "^" $1 $2 $3))]} -- BitwiseXORExpressionNoIn : See 11.10 -- BitwiseANDExpressionNoIn -- BitwiseXORExpressionNoIn ^ BitwiseANDExpressionNoIn BitwiseXOrExpressionNoIn :: { [AST.JSNode] } BitwiseXOrExpressionNoIn : BitwiseAndExpressionNoIn { $1 {- BitwiseXOrExpression -} } | BitwiseXOrExpressionNoIn BitXor BitwiseAndExpressionNoIn { [fp (AST.NN (AST.JSExpressionBinary "^" $1 $2 $3))]} -- BitwiseORExpression : See 11.10 -- BitwiseXORExpression -- BitwiseORExpression | BitwiseXORExpression BitwiseOrExpression :: { [AST.JSNode] } BitwiseOrExpression : BitwiseXOrExpression { $1 {- BitwiseOrExpression -} } | BitwiseOrExpression BitOr BitwiseXOrExpression { [fp (AST.NN (AST.JSExpressionBinary "|" $1 $2 $3))]} -- BitwiseORExpressionNoIn : See 11.10 -- BitwiseXORExpressionNoIn -- BitwiseORExpressionNoIn | BitwiseXORExpressionNoIn BitwiseOrExpressionNoIn :: { [AST.JSNode] } BitwiseOrExpressionNoIn : BitwiseXOrExpressionNoIn { $1 {- BitwiseOrExpression -} } | BitwiseOrExpressionNoIn BitOr BitwiseXOrExpressionNoIn { [fp (AST.NN (AST.JSExpressionBinary "|" $1 $2 $3))]} -- LogicalANDExpression : See 11.11 -- BitwiseORExpression -- LogicalANDExpression && BitwiseORExpression LogicalAndExpression :: { [AST.JSNode] } LogicalAndExpression : BitwiseOrExpression { $1 {- LogicalAndExpression -} } | LogicalAndExpression And BitwiseOrExpression { [fp (AST.NN (AST.JSExpressionBinary "&&" $1 $2 $3))]} -- LogicalANDExpressionNoIn : See 11.11 -- BitwiseORExpressionNoIn -- LogicalANDExpressionNoIn && BitwiseORExpressionNoIn LogicalAndExpressionNoIn :: { [AST.JSNode] } LogicalAndExpressionNoIn : BitwiseOrExpressionNoIn { $1 {- LogicalAndExpression -} } | LogicalAndExpressionNoIn And BitwiseOrExpressionNoIn { [fp (AST.NN (AST.JSExpressionBinary "&&" $1 $2 $3))]} -- LogicalORExpression : See 11.11 -- LogicalANDExpression -- LogicalORExpression || LogicalANDExpression LogicalOrExpression :: { [AST.JSNode] } LogicalOrExpression : LogicalAndExpression { $1 {- LogicalOrExpression -} } | LogicalOrExpression Or LogicalAndExpression { [fp (AST.NN (AST.JSExpressionBinary "||" $1 $2 $3))]} -- LogicalORExpressionNoIn : See 11.11 -- LogicalANDExpressionNoIn -- LogicalORExpressionNoIn || LogicalANDExpressionNoIn LogicalOrExpressionNoIn :: { [AST.JSNode] } LogicalOrExpressionNoIn : LogicalAndExpressionNoIn { $1 {- LogicalOrExpression -} } | LogicalOrExpressionNoIn Or LogicalAndExpressionNoIn { [fp (AST.NN (AST.JSExpressionBinary "||" $1 $2 $3))]} -- ConditionalExpression : See 11.12 -- LogicalORExpression -- LogicalORExpression ? AssignmentExpression : AssignmentExpression ConditionalExpression :: { [AST.JSNode] } ConditionalExpression : LogicalOrExpression { $1 {- ConditionalExpression -} } | LogicalOrExpression Hook AssignmentExpression Colon AssignmentExpression { [fp (AST.NN (AST.JSExpressionTernary $1 $2 $3 $4 $5))] } -- ConditionalExpressionNoIn : See 11.12 -- LogicalORExpressionNoIn -- LogicalORExpressionNoIn ? AssignmentExpressionNoIn : AssignmentExpressionNoIn ConditionalExpressionNoIn :: { [AST.JSNode] } ConditionalExpressionNoIn : LogicalOrExpressionNoIn { $1 {- ConditionalExpression -} } | LogicalOrExpressionNoIn Hook AssignmentExpressionNoIn Colon AssignmentExpressionNoIn { [fp (AST.NN (AST.JSExpressionTernary $1 $2 $3 $4 $5))] } -- AssignmentExpression : See 11.13 -- ConditionalExpression -- LeftHandSideExpression AssignmentOperator AssignmentExpression AssignmentExpression :: { [AST.JSNode] } AssignmentExpression : ConditionalExpression { $1 {- AssignmentExpression -}} | LeftHandSideExpression AssignmentOperator AssignmentExpression { ($1++[$2]++$3) } -- AssignmentExpressionNoIn : See 11.13 -- ConditionalExpressionNoIn -- LeftHandSideExpression AssignmentOperator AssignmentExpressionNoIn AssignmentExpressionNoIn :: { [AST.JSNode] } AssignmentExpressionNoIn : ConditionalExpressionNoIn { $1 {- AssignmentExpression -}} | LeftHandSideExpression AssignmentOperator AssignmentExpressionNoIn { ($1++[$2]++$3) } -- AssignmentOperator : one of See 11.13 -- '=' | '*=' | '/=' | '%=' | '+=' | '-=' | '<<=' | '>>=' | '>>>=' | '&=' | '^=' | '|=' AssignmentOperator :: { AST.JSNode } AssignmentOperator : Assign { fp (AST.NN (AST.JSOperator $1))} | SimpleAssign { fp (AST.NN (AST.JSOperator $1))} -- Expression : See 11.14 -- AssignmentExpression -- Expression , AssignmentExpression Expression :: { AST.JSNode } Expression : AssignmentExpression { fp (AST.NN (AST.JSExpression $1)) {- Expression -} } | Expression Comma AssignmentExpression { fp (AST.NN (AST.JSExpression ($1:[$2]++$3))) {- Expression2 -} } -- ExpressionNoIn : See 11.14 -- AssignmentExpressionNoIn -- ExpressionNoIn , AssignmentExpressionNoIn ExpressionNoIn :: { AST.JSNode } ExpressionNoIn : AssignmentExpressionNoIn { fp (AST.NN (AST.JSExpression $1)) {- ExpressionNoIn -} } | ExpressionNoIn Comma AssignmentExpressionNoIn { fp (AST.NN (AST.JSExpression ($1:[$2]++$3))) {- ExpressionNoIn2 -} } -- TODO: still required? ExpressionOpt :: { [AST.JSNode] } ExpressionOpt : Expression { [$1] {- ExpressionOpt -}} | { [] {- ExpressionOpt -}} ExpressionNoInOpt :: { [AST.JSNode] } ExpressionNoInOpt : ExpressionNoIn { [$1] {- ExpressionOpt -}} | { [] {- ExpressionOpt -}} -- Statement : See clause 12 -- Block -- VariableStatement -- EmptyStatement -- ExpressionStatement -- IfStatement -- IterationStatement -- ContinueStatement -- BreakStatement -- ReturnStatement -- WithStatement -- LabelledStatement -- SwitchStatement -- ThrowStatement -- TryStatement -- DebuggerStatement Statement :: { AST.JSNode } Statement : StatementNoEmpty { $1 {- Statement1 -}} | EmptyStatement { $1 {- Statement3 -}} StatementNoEmpty :: { AST.JSNode } 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.JSNode } StatementBlock : LBrace RBrace { fp (AST.NN (AST.JSBlock [$1] [] [$2])) } | LBrace StatementList RBrace { fp (AST.NN (AST.JSBlock [$1] $2 [$3])) } -- Block : See 12.1 -- { StatementListopt } Block :: { AST.JSNode } Block : LBrace RBrace { fp (AST.NN (AST.JSBlock [$1] [] [$2])) } | LBrace StatementList RBrace { fp (AST.NN (AST.JSBlock [$1] $2 [$3])) } -- StatementList : See 12.1 -- Statement -- StatementList Statement StatementList :: { [AST.JSNode] } StatementList : Statement { [$1] {- StatementList1 -} } | StatementList Statement { ($1++[$2]) {- StatementList2 -} } -- VariableStatement : See 12.2 -- var VariableDeclarationList ; VariableStatement :: { AST.JSNode } VariableStatement : Var VariableDeclarationList AutoSemi { fp (AST.NN (AST.JSVariables $1 $2 $3))} | Const VariableDeclarationList AutoSemi { fp (AST.NN (AST.JSVariables $1 $2 $3))} -- VariableDeclarationList : See 12.2 -- VariableDeclaration -- VariableDeclarationList , VariableDeclaration VariableDeclarationList :: { [AST.JSNode] } VariableDeclarationList : VariableDeclaration { [$1] {- VariableDeclarationList -}} | VariableDeclarationList Comma VariableDeclaration { ($1++[$2]++[$3]) {- VariableDeclarationList -}} -- VariableDeclarationListNoIn : See 12.2 -- VariableDeclarationNoIn -- VariableDeclarationListNoIn , VariableDeclarationNoIn VariableDeclarationListNoIn :: { [AST.JSNode] } VariableDeclarationListNoIn : VariableDeclarationNoIn { [$1] {- VariableDeclarationList -}} | VariableDeclarationListNoIn Comma VariableDeclarationNoIn { ($1++[$2]++[$3]) {- VariableDeclarationListNoIn -}} -- VariableDeclaration : See 12.2 -- Identifier Initialiseropt VariableDeclaration :: { AST.JSNode } VariableDeclaration : Identifier { fp (AST.NN (AST.JSVarDecl $1 []))} | Identifier Initializer { fp (AST.NN (AST.JSVarDecl $1 $2))} -- VariableDeclarationNoIn : See 12.2 -- Identifier InitialiserNoInopt VariableDeclarationNoIn :: { AST.JSNode } VariableDeclarationNoIn : Identifier InitializerNoIn { fp (AST.NN (AST.JSVarDecl $1 $2)) } | Identifier { fp (AST.NN (AST.JSVarDecl $1 [])) } -- Initialiser : See 12.2 -- = AssignmentExpression Initializer :: { [AST.JSNode] } Initializer : SimpleAssign AssignmentExpression { $1:$2 {- Initializer -} } -- InitialiserNoIn : See 12.2 -- = AssignmentExpressionNoIn InitializerNoIn :: { [AST.JSNode] } InitializerNoIn : SimpleAssign AssignmentExpressionNoIn { $1:$2 {- InitializerNoIn -}} -- EmptyStatement : See 12.3 -- ; EmptyStatement :: { AST.JSNode } EmptyStatement : Semi { $1 } -- 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.JSNode } ExpressionStatement : Expression { $1 {- ExpressionStatement -} } -- IfStatement : See 12.5 -- if ( Expression ) Statement else Statement -- if ( Expression ) Statement IfStatement :: { AST.JSNode } -- +++XXXX++ IfStatement : If LParen Expression RParen StatementSemi IfElseRest { (fp (AST.NN (AST.JSIf $1 $2 $3 $4 $5 $6)) ) } IfElseRest :: { [AST.JSNode] } IfElseRest : Else Statement { [$1,$2] } | { [] } StatementSemi :: { [AST.JSNode] } StatementSemi : StatementNoEmpty Semi { [$1,$2] {- StatementSemi1 -}} | StatementNoEmpty { [$1] {- StatementSemi2 -}} | Semi { [$1] {- StatementSemi3 -}} -- 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.JSNode } IterationStatement : Do Statement While LParen Expression RParen AutoSemi { fp (AST.NN (AST.JSDoWhile $1 $2 $3 $4 $5 $6 $7)) } | While LParen Expression RParen Statement { fp (AST.NN (AST.JSWhile $1 $2 $3 $4 $5)) } | For LParen ExpressionNoInOpt Semi ExpressionOpt Semi ExpressionOpt RParen Statement { fp (AST.NN (AST.JSFor $1 $2 $3 $4 $5 $6 $7 $8 $9)) } | For LParen Var VariableDeclarationListNoIn Semi ExpressionOpt Semi ExpressionOpt RParen Statement { fp (AST.NN (AST.JSForVar $1 $2 $3 $4 $5 $6 $7 $8 $9 $10)) } | For LParen LeftHandSideExpression In Expression RParen Statement { fp (AST.NN (AST.JSForIn $1 $2 $3 $4 $5 $6 $7)) } | For LParen Var VariableDeclarationNoIn In Expression RParen Statement { fp (AST.NN (AST.JSForVarIn $1 $2 $3 $4 $5 $6 $7 $8)) } -- ContinueStatement : See 12.7 -- continue [no LineTerminator here] Identifieropt ; -- TODO: deal with [no LineTerminator here] ContinueStatement :: { AST.JSNode } ContinueStatement : Continue AutoSemi { fp (AST.NN (AST.JSContinue $1 [] $2)) } | Continue Identifier AutoSemi { fp (AST.NN (AST.JSContinue $1 [$2] $3)) } -- BreakStatement : See 12.8 -- break [no LineTerminator here] Identifieropt ; -- TODO: deal with [no LineTerminator here] BreakStatement :: { AST.JSNode } BreakStatement : Break AutoSemi { fp (AST.NN (AST.JSBreak $1 [] $2)) } | Break Identifier AutoSemi { fp (AST.NN (AST.JSBreak $1 [$2] $3)) } -- ReturnStatement : See 12.9 -- return [no LineTerminator here] Expressionopt ; -- TODO: deal with [no LineTerminator here] ReturnStatement :: { AST.JSNode } ReturnStatement : Return AutoSemi { fp (AST.NN (AST.JSReturn $1 [] $2)) } | Return Expression AutoSemi { fp (AST.NN (AST.JSReturn $1 [$2] $3)) } -- WithStatement : See 12.10 -- with ( Expression ) Statement WithStatement :: { AST.JSNode } WithStatement : With LParen Expression RParen Statement AutoSemi { fp (AST.NN (AST.JSWith $1 $2 $3 $4 [$5,$6])) } -- SwitchStatement : See 12.11 -- switch ( Expression ) CaseBlock SwitchStatement :: { AST.JSNode } SwitchStatement : Switch LParen Expression RParen CaseBlock { (AST.NN (AST.JSSwitch $1 $2 $3 $4 $5)) } -- CaseBlock : See 12.11 -- { CaseClausesopt } -- { CaseClausesopt DefaultClause CaseClausesopt } CaseBlock :: { AST.JSNode } CaseBlock : LBrace CaseClausesOpt RBrace { fp (AST.NN (AST.JSBlock [$1] $2 [$3])){- CaseBlock1 -}} | LBrace CaseClausesOpt DefaultClause CaseClausesOpt RBrace { fp (AST.NN (AST.JSBlock [$1] ($2++[$3]++$4) [$5])){- CaseBlock2 -}} -- CaseClauses : See 12.11 -- CaseClause -- CaseClauses CaseClause CaseClausesOpt :: { [AST.JSNode] } CaseClausesOpt : CaseClause { [$1] {- CaseClauses1 -}} | CaseClausesOpt CaseClause { ($1++[$2]) {- CaseClauses2 -}} | { [fp (AST.NT (AST.JSLiteral "") tokenPosnEmpty []) ] } -- { [] } -- CaseClause : See 12.11 -- case Expression : StatementListopt CaseClause :: { AST.JSNode } CaseClause : Case Expression Colon StatementList { fp (AST.NN (AST.JSCase $1 $2 $3 $4)) } | Case Expression Colon { fp (AST.NN (AST.JSCase $1 $2 $3 [])) } -- DefaultClause : See 12.11 -- default : StatementListopt DefaultClause :: { AST.JSNode } DefaultClause : Default Colon { fp (AST.NN (AST.JSDefault $1 $2 [])) } | Default Colon StatementList { fp (AST.NN (AST.JSDefault $1 $2 $3)) } -- LabelledStatement : See 12.12 -- Identifier : Statement LabelledStatement :: { AST.JSNode } LabelledStatement : Identifier Colon Statement { fp (AST.NN (AST.JSLabelled $1 $2 $3)) } -- ThrowStatement : See 12.13 -- throw [no LineTerminator here] Expression ; -- TODO : sort out no LineTerminator here -- Does it need a semi at the end? ThrowStatement :: { AST.JSNode } ThrowStatement : Throw Expression { fp (AST.NN (AST.JSThrow $1 $2)) } -- 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.JSNode } TryStatement : Try Block Catches { fp (AST.NN (AST.JSTry $1 $2 $3) ) {- TryStatement1 -} } | Try Block Finally { fp (AST.NN (AST.JSTry $1 $2 [$3]) ) {- TryStatement2 -} } | Try Block Catches Finally { fp (AST.NN (AST.JSTry $1 $2 ($3++[$4])) ) {- TryStatement3 -} } Catches :: { [AST.JSNode] } Catches : Catch { [$1] {- Catches 1 -} } | Catches Catch { ($1++[$2]) {- Catches 2 -} } -- 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.JSNode } Catch : CatchL LParen Identifier RParen Block { fp (AST.NN (AST.JSCatch $1 $2 $3 [ ] $4 $5)) } | CatchL LParen Identifier If ConditionalExpression RParen Block { fp (AST.NN (AST.JSCatch $1 $2 $3 ($4:$5) $6 $7)) } -- Finally : See 12.14 -- finally Block Finally :: { AST.JSNode } Finally : FinallyL Block { fp (AST.NN (AST.JSFinally $1 $2)) } -- DebuggerStatement : See 12.15 -- debugger ; DebuggerStatement :: { AST.JSNode } DebuggerStatement : 'debugger' AutoSemi { fp (AST.NT (AST.JSLiteral "debugger") (ss $1) (gc $1)) } -- FunctionDeclaration : See clause 13 -- function Identifier ( FormalParameterListopt ) { FunctionBody } FunctionDeclaration :: { AST.JSNode } FunctionDeclaration : Function Identifier LParen FormalParameterList RParen FunctionBody { fp (AST.NN (AST.JSFunction $1 $2 $3 $4 $5 $6) ) } | Function Identifier LParen RParen FunctionBody { fp (AST.NN (AST.JSFunction $1 $2 $3 [] $4 $5) ) } -- FunctionExpression : See clause 13 -- function Identifieropt ( FormalParameterListopt ) { FunctionBody } FunctionExpression :: { AST.JSNode } FunctionExpression : Function IdentifierOpt LParen RParen FunctionBody { fp (AST.NN (AST.JSFunctionExpression $1 $2 $3 [] $4 $5) ) } | Function IdentifierOpt LParen FormalParameterList RParen FunctionBody { fp (AST.NN (AST.JSFunctionExpression $1 $2 $3 $4 $5 $6) ) } IdentifierOpt :: { [AST.JSNode] } IdentifierOpt : Identifier { [$1] {- IdentifierOpt -}} | { [] {- IdentifierOpt -}} -- FormalParameterList : See clause 13 -- Identifier -- FormalParameterList , Identifier FormalParameterList :: { [AST.JSNode] } FormalParameterList : Identifier { [$1] {- FormalParameterList -}} | FormalParameterList Comma Identifier { ($1++[$2]++[$3]) } -- FunctionBody : See clause 13 -- SourceElementsopt FunctionBody :: { AST.JSNode } FunctionBody : LBrace SourceElements RBrace { (AST.NN (AST.JSBlock [$1] $2 [$3]) ) } | LBrace RBrace { (AST.NN (AST.JSBlock [$1] [] [$2]) ) } -- Program : See clause 14 -- SourceElementsopt Program :: { AST.JSNode } Program : SourceElementsTop Eof { (combineTop $1 $2) {- Program -}} | Eof { fp (AST.NN (AST.JSSourceElementsTop [$1])) } -- For debugging/other entry points LiteralMain :: { AST.JSNode } LiteralMain : Literal Eof { $1 } PrimaryExpressionMain :: { AST.JSNode } PrimaryExpressionMain : PrimaryExpression Eof { $1 } StatementMain :: { AST.JSNode } StatementMain : Statement Eof { $1 } -- SourceElements : See clause 14 -- SourceElement -- SourceElements SourceElement SourceElements :: { [AST.JSNode] } SourceElements : SourceElement { [$1] {- SourceElements -} } | SourceElements SourceElement { $1++[$2] {- SourceElements -} } SourceElementsTop :: { AST.JSNode } SourceElementsTop : SourceElement { fp (AST.NN (AST.JSSourceElementsTop [$1]) ) } | SourceElementsTop SourceElement { (combineSourceElementsTop $1 $2) } -- SourceElement : -- Statement -- FunctionDeclaration SourceElement :: { AST.JSNode } SourceElement : Statement { $1 {- SourceElement1 -} } | FunctionDeclaration { $1 {- SourceElement2 -} } { combineSourceElementsTop :: AST.JSNode -> AST.JSNode -> AST.JSNode combineSourceElementsTop (AST.NN (AST.JSSourceElementsTop xs)) x1 = fp (AST.NN (AST.JSSourceElementsTop (xs++[x1]))) combineTop :: AST.JSNode -> AST.JSNode -> AST.JSNode combineTop (AST.NN (AST.JSSourceElementsTop xs)) x1 = fp (AST.NN (AST.JSSourceElementsTop (xs++[x1]))) parseError :: Token -> Alex a -- parseError = throwError . UnexpectedToken parseError tok = alexError (show tok) -- -------------------------------- {- mex :: [AST.JSNode] -> TokenPosn mex [] = tokenPosnEmpty mex xs = ex (head xs) ex :: AST.JSNode -> TokenPosn ex (AST.NN _node span _c) = span -} --ss token = toSrcSpan (token_span token) ss :: Token -> TokenPosn ss token = token_span token -- ------------------------------ gc :: Token -> [CommentAnnotation] gc token = token_comment token mgc :: [Token] -> [CommentAnnotation] mgc xs = concatMap gc xs -- --------------------------------------------------------------------- fp :: AST.JSNode -> AST.JSNode fp (AST.NN x) = (AST.NN x) fp (AST.NT x p cs) = (AST.NT x p cs) {- fp (AST.NN x p cs) = (AST.NN x p' cs) where p' = case (filter (/= NoComment) cs) of [] -> p [(CommentA posn _)] -> posn ((CommentA posn _):_) -> posn -} } -- Set emacs mode -- Local Variables: -- mode:haskell -- End: