%{ /* * This file is part of the KDE libraries * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ #include #include #include #include #include "value.h" #include "object.h" #include "types.h" #include "interpreter.h" #include "nodes.h" #include "makenodes.h" #include "lexer.h" #include "internal.h" // Not sure why, but yacc doesn't add this define along with the others. #define yylloc kjsyylloc /* default values for bison */ #define YYDEBUG 0 // Set to 1 to debug a parse error. #define kjsyydebug 0 // Set to 1 to debug a parse error. #if !PLATFORM(DARWIN) // avoid triggering warnings in older bison #define YYERROR_VERBOSE #endif extern int kjsyylex(); int kjsyyerror(const char *); static bool allowAutomaticSemicolon(); #define AUTO_SEMICOLON do { if (!allowAutomaticSemicolon()) YYABORT; } while (0) #define DBG(l, s, e) (l)->setLoc((s).first_line, (e).last_line) #ifndef __GNUC__ # define __attribute__(x) #endif using namespace KJS; %} %union { int ival; double dval; UString *ustr; Identifier *ident; Node *node; StatementNode *stat; ParameterNode *param; FunctionBodyNode *body; FuncDeclNode *func; FuncExprNode *funcExpr; ProgramNode *prog; AssignExprNode *init; SourceElementsNode *srcs; ArgumentsNode *args; ArgumentListNode *alist; VarDeclNode *decl; VarDeclListNode *vlist; CaseBlockNode *cblk; ClauseListNode *clist; CaseClauseNode *ccl; ElementNode *elm; Operator op; PropertyListNode *plist; PropertyNode *pnode; PropertyNameNode *pname; PackageNameNode *pkgn; } %start Program /* literals */ %token NULLTOKEN TRUETOKEN FALSETOKEN /* keywords */ %token BREAK CASE DEFAULT FOR NEW VAR CONSTTOKEN CONTINUE %token FUNCTION RETURN VOIDTOKEN DELETETOKEN %token IF THISTOKEN DO WHILE INTOKEN INSTANCEOF TYPEOF %token SWITCH WITH RESERVED %token THROW TRY CATCH FINALLY %token DEBUGGER IMPORT /* give an if without an else higher precedence than an else to resolve the ambiguity */ %nonassoc IF_WITHOUT_ELSE %nonassoc ELSE /* punctuators */ %token EQEQ NE /* == and != */ %token STREQ STRNEQ /* === and !== */ %token LE GE /* < and > */ %token OR AND /* || and && */ %token PLUSPLUS MINUSMINUS /* ++ and -- */ %token LSHIFT /* << */ %token RSHIFT URSHIFT /* >> and >>> */ %token PLUSEQUAL MINUSEQUAL /* += and -= */ %token MULTEQUAL DIVEQUAL /* *= and /= */ %token LSHIFTEQUAL /* <<= */ %token RSHIFTEQUAL URSHIFTEQUAL /* >>= and >>>= */ %token ANDEQUAL MODEQUAL /* &= and %= */ %token XOREQUAL OREQUAL /* ^= and |= */ /* terminal types */ %token NUMBER %token STRING %token IDENT /* automatically inserted semicolon */ %token AUTOPLUSPLUS AUTOMINUSMINUS /* non-terminal types */ %type Literal ArrayLiteral %type PrimaryExpr PrimaryExprNoBrace %type MemberExpr MemberExprNoBF /* BF => brace or function */ %type NewExpr NewExprNoBF %type CallExpr CallExprNoBF %type LeftHandSideExpr LeftHandSideExprNoBF %type PostfixExpr PostfixExprNoBF %type UnaryExpr UnaryExprNoBF UnaryExprCommon %type MultiplicativeExpr MultiplicativeExprNoBF %type AdditiveExpr AdditiveExprNoBF %type ShiftExpr ShiftExprNoBF %type RelationalExpr RelationalExprNoIn RelationalExprNoBF %type EqualityExpr EqualityExprNoIn EqualityExprNoBF %type BitwiseANDExpr BitwiseANDExprNoIn BitwiseANDExprNoBF %type BitwiseXORExpr BitwiseXORExprNoIn BitwiseXORExprNoBF %type BitwiseORExpr BitwiseORExprNoIn BitwiseORExprNoBF %type LogicalANDExpr LogicalANDExprNoIn LogicalANDExprNoBF %type LogicalORExpr LogicalORExprNoIn LogicalORExprNoBF %type ConditionalExpr ConditionalExprNoIn ConditionalExprNoBF %type AssignmentExpr AssignmentExprNoIn AssignmentExprNoBF %type Expr ExprNoIn ExprNoBF %type ExprOpt ExprNoInOpt %type Statement Block %type VariableStatement ConstStatement EmptyStatement ExprStatement %type IfStatement IterationStatement ContinueStatement %type BreakStatement ReturnStatement WithStatement %type SwitchStatement LabelledStatement %type ThrowStatement TryStatement %type DebuggerStatement ImportStatement %type SourceElement %type Initializer InitializerNoIn %type FunctionDeclaration %type FunctionExpr %type FunctionBody %type SourceElements %type FormalParameterList %type AssignmentOperator %type Arguments %type ArgumentList %type VariableDeclarationList VariableDeclarationListNoIn ConstDeclarationList %type VariableDeclaration VariableDeclarationNoIn ConstDeclaration %type CaseBlock %type CaseClause DefaultClause %type CaseClauses CaseClausesOpt %type Elision ElisionOpt %type ElementList %type PropertyName %type Property %type PropertyList %type PackageName %type Keywords %type IdentifierName %% Keywords: BREAK { $$ = new Identifier("break"); } | CASE { $$ = new Identifier("case"); } | DEFAULT { $$ = new Identifier("default"); } | FOR { $$ = new Identifier("for"); } | NEW { $$ = new Identifier("new"); } | VAR { $$ = new Identifier("var"); } | CONSTTOKEN { $$ = new Identifier("const"); } | CONTINUE { $$ = new Identifier("continue"); } | FUNCTION { $$ = new Identifier("function"); } | RETURN { $$ = new Identifier("return"); } | VOIDTOKEN { $$ = new Identifier("void"); } | DELETETOKEN { $$ = new Identifier("delete"); } | IF { $$ = new Identifier("if"); } | THISTOKEN { $$ = new Identifier("this"); } | DO { $$ = new Identifier("do"); } | WHILE { $$ = new Identifier("while"); } | INTOKEN { $$ = new Identifier("in"); } | INSTANCEOF { $$ = new Identifier("instanceof"); } | TYPEOF { $$ = new Identifier("typeof"); } | SWITCH { $$ = new Identifier("switch"); } | WITH { $$ = new Identifier("with"); } | THROW { $$ = new Identifier("throw"); } | TRY { $$ = new Identifier("try"); } | CATCH { $$ = new Identifier("catch"); } | FINALLY { $$ = new Identifier("finally"); } | DEBUGGER { $$ = new Identifier("debugger"); } | IMPORT { $$ = new Identifier("import"); } | NULLTOKEN { $$ = new Identifier("null"); } | TRUETOKEN { $$ = new Identifier("true"); } | FALSETOKEN { $$ = new Identifier("false"); } | ELSE { $$ = new Identifier("else"); } ; IdentifierName: IDENT { $$ = $1; } | Keywords { $$ = $1; } ; Literal: NULLTOKEN { $$ = new NullNode(); } | TRUETOKEN { $$ = new BooleanNode(true); } | FALSETOKEN { $$ = new BooleanNode(false); } | NUMBER { $$ = new NumberNode($1); } | STRING { $$ = new StringNode($1); } | '/' /* regexp */ { Lexer& l = lexer(); if (!l.scanRegExp()) YYABORT; $$ = new RegExpNode(l.pattern(), l.flags()); } | DIVEQUAL /* regexp with /= */ { Lexer& l = lexer(); if (!l.scanRegExp()) YYABORT; $$ = new RegExpNode("=" + l.pattern(), l.flags()); } ; PropertyName: IdentifierName { $$ = new PropertyNameNode(*$1); } | STRING { $$ = new PropertyNameNode(Identifier(*$1)); } | NUMBER { $$ = new PropertyNameNode(Identifier(UString::from($1))); } ; Property: PropertyName ':' AssignmentExpr { $$ = new PropertyNode($1, $3, PropertyNode::Constant); } | IDENT IdentifierName '(' ')' {inFuncExpr();} FunctionBody { if (!makeGetterOrSetterPropertyNode($$, *$1, *$2, 0, $6)) YYABORT; } | IDENT IdentifierName '(' FormalParameterList ')' {inFuncExpr();} FunctionBody { if (!makeGetterOrSetterPropertyNode($$, *$1, *$2, $4, $7)) YYABORT; } ; PropertyList: Property { $$ = new PropertyListNode($1); } | PropertyList ',' Property { $$ = new PropertyListNode($3, $1); } ; PrimaryExpr: PrimaryExprNoBrace | '{' '}' { $$ = new ObjectLiteralNode(); } | '{' PropertyList '}' { $$ = new ObjectLiteralNode($2); } /* allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 */ | '{' PropertyList ',' '}' { $$ = new ObjectLiteralNode($2); } ; PrimaryExprNoBrace: THISTOKEN { $$ = new ThisNode(); } | Literal | ArrayLiteral | IDENT { $$ = new VarAccessNode(*$1); } | '(' Expr ')' { $$ = makeGroupNode($2); } ; ArrayLiteral: '[' ElisionOpt ']' { $$ = new ArrayNode($2); } | '[' ElementList ']' { $$ = new ArrayNode($2); } | '[' ElementList ',' ElisionOpt ']' { $$ = new ArrayNode($4, $2); } ; ElementList: ElisionOpt AssignmentExpr { $$ = new ElementNode($1, $2); } | ElementList ',' ElisionOpt AssignmentExpr { $$ = new ElementNode($1, $3, $4); } ; ElisionOpt: /* nothing */ { $$ = 0; } | Elision ; Elision: ',' { $$ = 1; } | Elision ',' { $$ = $1 + 1; } ; MemberExpr: PrimaryExpr | FunctionExpr { $$ = $1; } | MemberExpr '[' Expr ']' { $$ = new BracketAccessorNode($1, $3); } | MemberExpr '.' IdentifierName { $$ = new DotAccessorNode($1, *$3); } | NEW MemberExpr Arguments { $$ = new NewExprNode($2, $3); } ; MemberExprNoBF: PrimaryExprNoBrace | MemberExprNoBF '[' Expr ']' { $$ = new BracketAccessorNode($1, $3); } | MemberExprNoBF '.' IdentifierName { $$ = new DotAccessorNode($1, *$3); } | NEW MemberExpr Arguments { $$ = new NewExprNode($2, $3); } ; NewExpr: MemberExpr | NEW NewExpr { $$ = new NewExprNode($2); } ; NewExprNoBF: MemberExprNoBF | NEW NewExpr { $$ = new NewExprNode($2); } ; CallExpr: MemberExpr Arguments { $$ = makeFunctionCallNode($1, $2); } | CallExpr Arguments { $$ = makeFunctionCallNode($1, $2); } | CallExpr '[' Expr ']' { $$ = new BracketAccessorNode($1, $3); } | CallExpr '.' IdentifierName { $$ = new DotAccessorNode($1, *$3); } ; CallExprNoBF: MemberExprNoBF Arguments { $$ = makeFunctionCallNode($1, $2); } | CallExprNoBF Arguments { $$ = makeFunctionCallNode($1, $2); } | CallExprNoBF '[' Expr ']' { $$ = new BracketAccessorNode($1, $3); } | CallExprNoBF '.' IdentifierName { $$ = new DotAccessorNode($1, *$3); } ; Arguments: '(' ')' { $$ = new ArgumentsNode(); } | '(' ArgumentList ')' { $$ = new ArgumentsNode($2); } ; ArgumentList: AssignmentExpr { $$ = new ArgumentListNode($1); } | ArgumentList ',' AssignmentExpr { $$ = new ArgumentListNode($1, $3); } ; LeftHandSideExpr: NewExpr | CallExpr ; LeftHandSideExprNoBF: NewExprNoBF | CallExprNoBF ; PostfixExpr: LeftHandSideExpr | LeftHandSideExpr PLUSPLUS { $$ = makePostfixNode($1, OpPlusPlus); } | LeftHandSideExpr MINUSMINUS { $$ = makePostfixNode($1, OpMinusMinus); } ; PostfixExprNoBF: LeftHandSideExprNoBF | LeftHandSideExprNoBF PLUSPLUS { $$ = makePostfixNode($1, OpPlusPlus); } | LeftHandSideExprNoBF MINUSMINUS { $$ = makePostfixNode($1, OpMinusMinus); } ; UnaryExprCommon: DELETETOKEN UnaryExpr { $$ = makeDeleteNode($2); } | VOIDTOKEN UnaryExpr { $$ = new VoidNode($2); } | TYPEOF UnaryExpr { $$ = makeTypeOfNode($2); } | PLUSPLUS UnaryExpr { $$ = makePrefixNode($2, OpPlusPlus); } | AUTOPLUSPLUS UnaryExpr { $$ = makePrefixNode($2, OpPlusPlus); } | MINUSMINUS UnaryExpr { $$ = makePrefixNode($2, OpMinusMinus); } | AUTOMINUSMINUS UnaryExpr { $$ = makePrefixNode($2, OpMinusMinus); } | '+' UnaryExpr { $$ = makeUnaryPlusNode($2); } | '-' UnaryExpr { $$ = makeNegateNode($2); } | '~' UnaryExpr { $$ = makeBitwiseNotNode($2); } | '!' UnaryExpr { $$ = makeLogicalNotNode($2); } UnaryExpr: PostfixExpr | UnaryExprCommon ; UnaryExprNoBF: PostfixExprNoBF | UnaryExprCommon ; MultiplicativeExpr: UnaryExpr | MultiplicativeExpr '*' UnaryExpr { $$ = makeMultNode($1, $3, OpMult); } | MultiplicativeExpr '/' UnaryExpr { $$ = makeMultNode($1, $3, OpDiv); } | MultiplicativeExpr '%' UnaryExpr { $$ = makeMultNode($1, $3, OpMod); } ; MultiplicativeExprNoBF: UnaryExprNoBF | MultiplicativeExprNoBF '*' UnaryExpr { $$ = makeMultNode($1, $3, OpMult); } | MultiplicativeExprNoBF '/' UnaryExpr { $$ = makeMultNode($1, $3, OpDiv); } | MultiplicativeExprNoBF '%' UnaryExpr { $$ = makeMultNode($1, $3, OpMod); } ; AdditiveExpr: MultiplicativeExpr | AdditiveExpr '+' MultiplicativeExpr { $$ = makeAddNode($1, $3, OpPlus); } | AdditiveExpr '-' MultiplicativeExpr { $$ = makeAddNode($1, $3, OpMinus); } ; AdditiveExprNoBF: MultiplicativeExprNoBF | AdditiveExprNoBF '+' MultiplicativeExpr { $$ = makeAddNode($1, $3, OpPlus); } | AdditiveExprNoBF '-' MultiplicativeExpr { $$ = makeAddNode($1, $3, OpMinus); } ; ShiftExpr: AdditiveExpr | ShiftExpr LSHIFT AdditiveExpr { $$ = makeShiftNode($1, $3, OpLShift); } | ShiftExpr RSHIFT AdditiveExpr { $$ = makeShiftNode($1, $3, OpRShift); } | ShiftExpr URSHIFT AdditiveExpr { $$ = makeShiftNode($1, $3, OpURShift); } ; ShiftExprNoBF: AdditiveExprNoBF | ShiftExprNoBF LSHIFT AdditiveExpr { $$ = makeShiftNode($1, $3, OpLShift); } | ShiftExprNoBF RSHIFT AdditiveExpr { $$ = makeShiftNode($1, $3, OpRShift); } | ShiftExprNoBF URSHIFT AdditiveExpr { $$ = makeShiftNode($1, $3, OpURShift); } ; RelationalExpr: ShiftExpr | RelationalExpr '<' ShiftExpr { $$ = makeRelationalNode($1, OpLess, $3); } | RelationalExpr '>' ShiftExpr { $$ = makeRelationalNode($1, OpGreater, $3); } | RelationalExpr LE ShiftExpr { $$ = makeRelationalNode($1, OpLessEq, $3); } | RelationalExpr GE ShiftExpr { $$ = makeRelationalNode($1, OpGreaterEq, $3); } | RelationalExpr INSTANCEOF ShiftExpr { $$ = makeRelationalNode($1, OpInstanceOf, $3); } | RelationalExpr INTOKEN ShiftExpr { $$ = makeRelationalNode($1, OpIn, $3); } ; RelationalExprNoIn: ShiftExpr | RelationalExprNoIn '<' ShiftExpr { $$ = makeRelationalNode($1, OpLess, $3); } | RelationalExprNoIn '>' ShiftExpr { $$ = makeRelationalNode($1, OpGreater, $3); } | RelationalExprNoIn LE ShiftExpr { $$ = makeRelationalNode($1, OpLessEq, $3); } | RelationalExprNoIn GE ShiftExpr { $$ = makeRelationalNode($1, OpGreaterEq, $3); } | RelationalExprNoIn INSTANCEOF ShiftExpr { $$ = makeRelationalNode($1, OpInstanceOf, $3); } ; RelationalExprNoBF: ShiftExprNoBF | RelationalExprNoBF '<' ShiftExpr { $$ = makeRelationalNode($1, OpLess, $3); } | RelationalExprNoBF '>' ShiftExpr { $$ = makeRelationalNode($1, OpGreater, $3); } | RelationalExprNoBF LE ShiftExpr { $$ = makeRelationalNode($1, OpLessEq, $3); } | RelationalExprNoBF GE ShiftExpr { $$ = makeRelationalNode($1, OpGreaterEq, $3); } | RelationalExprNoBF INSTANCEOF ShiftExpr { $$ = makeRelationalNode($1, OpInstanceOf, $3); } | RelationalExprNoBF INTOKEN ShiftExpr { $$ = makeRelationalNode($1, OpIn, $3); } ; EqualityExpr: RelationalExpr | EqualityExpr EQEQ RelationalExpr { $$ = makeEqualNode($1, OpEqEq, $3); } | EqualityExpr NE RelationalExpr { $$ = makeEqualNode($1, OpNotEq, $3); } | EqualityExpr STREQ RelationalExpr { $$ = makeEqualNode($1, OpStrEq, $3); } | EqualityExpr STRNEQ RelationalExpr { $$ = makeEqualNode($1, OpStrNEq, $3);} ; EqualityExprNoIn: RelationalExprNoIn | EqualityExprNoIn EQEQ RelationalExprNoIn { $$ = makeEqualNode($1, OpEqEq, $3); } | EqualityExprNoIn NE RelationalExprNoIn { $$ = makeEqualNode($1, OpNotEq, $3); } | EqualityExprNoIn STREQ RelationalExprNoIn { $$ = makeEqualNode($1, OpStrEq, $3); } | EqualityExprNoIn STRNEQ RelationalExprNoIn { $$ = makeEqualNode($1, OpStrNEq, $3);} ; EqualityExprNoBF: RelationalExprNoBF | EqualityExprNoBF EQEQ RelationalExpr { $$ = makeEqualNode($1, OpEqEq, $3); } | EqualityExprNoBF NE RelationalExpr { $$ = makeEqualNode($1, OpNotEq, $3); } | EqualityExprNoBF STREQ RelationalExpr { $$ = makeEqualNode($1, OpStrEq, $3); } | EqualityExprNoBF STRNEQ RelationalExpr { $$ = makeEqualNode($1, OpStrNEq, $3);} ; BitwiseANDExpr: EqualityExpr | BitwiseANDExpr '&' EqualityExpr { $$ = makeBitOperNode($1, OpBitAnd, $3); } ; BitwiseANDExprNoIn: EqualityExprNoIn | BitwiseANDExprNoIn '&' EqualityExprNoIn { $$ = makeBitOperNode($1, OpBitAnd, $3); } ; BitwiseANDExprNoBF: EqualityExprNoBF | BitwiseANDExprNoBF '&' EqualityExpr { $$ = makeBitOperNode($1, OpBitAnd, $3); } ; BitwiseXORExpr: BitwiseANDExpr | BitwiseXORExpr '^' BitwiseANDExpr { $$ = makeBitOperNode($1, OpBitXOr, $3); } ; BitwiseXORExprNoIn: BitwiseANDExprNoIn | BitwiseXORExprNoIn '^' BitwiseANDExprNoIn { $$ = makeBitOperNode($1, OpBitXOr, $3); } ; BitwiseXORExprNoBF: BitwiseANDExprNoBF | BitwiseXORExprNoBF '^' BitwiseANDExpr { $$ = makeBitOperNode($1, OpBitXOr, $3); } ; BitwiseORExpr: BitwiseXORExpr | BitwiseORExpr '|' BitwiseXORExpr { $$ = makeBitOperNode($1, OpBitOr, $3); } ; BitwiseORExprNoIn: BitwiseXORExprNoIn | BitwiseORExprNoIn '|' BitwiseXORExprNoIn { $$ = makeBitOperNode($1, OpBitOr, $3); } ; BitwiseORExprNoBF: BitwiseXORExprNoBF | BitwiseORExprNoBF '|' BitwiseXORExpr { $$ = makeBitOperNode($1, OpBitOr, $3); } ; LogicalANDExpr: BitwiseORExpr | LogicalANDExpr AND BitwiseORExpr { $$ = makeBinaryLogicalNode($1, OpAnd, $3); } ; LogicalANDExprNoIn: BitwiseORExprNoIn | LogicalANDExprNoIn AND BitwiseORExprNoIn { $$ = makeBinaryLogicalNode($1, OpAnd, $3); } ; LogicalANDExprNoBF: BitwiseORExprNoBF | LogicalANDExprNoBF AND BitwiseORExpr { $$ = makeBinaryLogicalNode($1, OpAnd, $3); } ; LogicalORExpr: LogicalANDExpr | LogicalORExpr OR LogicalANDExpr { $$ = makeBinaryLogicalNode($1, OpOr, $3); } ; LogicalORExprNoIn: LogicalANDExprNoIn | LogicalORExprNoIn OR LogicalANDExprNoIn { $$ = makeBinaryLogicalNode($1, OpOr, $3); } ; LogicalORExprNoBF: LogicalANDExprNoBF | LogicalORExprNoBF OR LogicalANDExpr { $$ = makeBinaryLogicalNode($1, OpOr, $3); } ; ConditionalExpr: LogicalORExpr | LogicalORExpr '?' AssignmentExpr ':' AssignmentExpr { $$ = makeConditionalNode($1, $3, $5); } ; ConditionalExprNoIn: LogicalORExprNoIn | LogicalORExprNoIn '?' AssignmentExprNoIn ':' AssignmentExprNoIn { $$ = makeConditionalNode($1, $3, $5); } ; ConditionalExprNoBF: LogicalORExprNoBF | LogicalORExprNoBF '?' AssignmentExpr ':' AssignmentExpr { $$ = makeConditionalNode($1, $3, $5); } ; AssignmentExpr: ConditionalExpr | LeftHandSideExpr AssignmentOperator AssignmentExpr { $$ = makeAssignNode($1, $2, $3); } ; AssignmentExprNoIn: ConditionalExprNoIn | LeftHandSideExpr AssignmentOperator AssignmentExprNoIn { $$ = makeAssignNode($1, $2, $3); } ; AssignmentExprNoBF: ConditionalExprNoBF | LeftHandSideExprNoBF AssignmentOperator AssignmentExpr { $$ = makeAssignNode($1, $2, $3); } ; AssignmentOperator: '=' { $$ = OpEqual; } | PLUSEQUAL { $$ = OpPlusEq; } | MINUSEQUAL { $$ = OpMinusEq; } | MULTEQUAL { $$ = OpMultEq; } | DIVEQUAL { $$ = OpDivEq; } | LSHIFTEQUAL { $$ = OpLShift; } | RSHIFTEQUAL { $$ = OpRShift; } | URSHIFTEQUAL { $$ = OpURShift; } | ANDEQUAL { $$ = OpAndEq; } | XOREQUAL { $$ = OpXOrEq; } | OREQUAL { $$ = OpOrEq; } | MODEQUAL { $$ = OpModEq; } ; Expr: AssignmentExpr | Expr ',' AssignmentExpr { $$ = new CommaNode($1, $3); } ; ExprNoIn: AssignmentExprNoIn | ExprNoIn ',' AssignmentExprNoIn { $$ = new CommaNode($1, $3); } ; ExprNoBF: AssignmentExprNoBF | ExprNoBF ',' AssignmentExpr { $$ = new CommaNode($1, $3); } ; Statement: Block | VariableStatement | ConstStatement | EmptyStatement | ExprStatement | IfStatement | IterationStatement | ContinueStatement | BreakStatement | ReturnStatement | WithStatement | SwitchStatement | LabelledStatement | ThrowStatement | TryStatement | DebuggerStatement | ImportStatement ; Block: '{' '}' { $$ = new BlockNode(0); DBG($$, @2, @2); } | '{' SourceElements '}' { $$ = new BlockNode($2); DBG($$, @3, @3); } ; VariableStatement: VAR VariableDeclarationList ';' { $$ = new VarStatementNode($2); DBG($$, @1, @3); } | VAR VariableDeclarationList error { $$ = new VarStatementNode($2); DBG($$, @1, @2); AUTO_SEMICOLON; } ; VariableDeclarationList: VariableDeclaration { $$ = new VarDeclListNode($1); } | VariableDeclarationList ',' VariableDeclaration { $$ = new VarDeclListNode($1, $3); } ; VariableDeclarationListNoIn: VariableDeclarationNoIn { $$ = new VarDeclListNode($1); } | VariableDeclarationListNoIn ',' VariableDeclarationNoIn { $$ = new VarDeclListNode($1, $3); } ; VariableDeclaration: IDENT { $$ = new VarDeclNode(*$1, 0, VarDeclNode::Variable); } | IDENT Initializer { $$ = new VarDeclNode(*$1, $2, VarDeclNode::Variable); } ; VariableDeclarationNoIn: IDENT { $$ = new VarDeclNode(*$1, 0, VarDeclNode::Variable); } | IDENT InitializerNoIn { $$ = new VarDeclNode(*$1, $2, VarDeclNode::Variable); } ; ConstStatement: CONSTTOKEN ConstDeclarationList ';' { $$ = new VarStatementNode($2); DBG($$, @1, @3); } | CONSTTOKEN ConstDeclarationList error { $$ = new VarStatementNode($2); DBG($$, @1, @2); AUTO_SEMICOLON; } ; ConstDeclarationList: ConstDeclaration { $$ = new VarDeclListNode($1); } | ConstDeclarationList ',' ConstDeclaration { $$ = new VarDeclListNode($1, $3); } ; ConstDeclaration: IDENT { $$ = new VarDeclNode(*$1, 0, VarDeclNode::Constant); } | IDENT Initializer { $$ = new VarDeclNode(*$1, $2, VarDeclNode::Constant); } ; Initializer: '=' AssignmentExpr { $$ = new AssignExprNode($2); } ; InitializerNoIn: '=' AssignmentExprNoIn { $$ = new AssignExprNode($2); } ; EmptyStatement: ';' { $$ = new EmptyStatementNode(); } ; ExprStatement: ExprNoBF ';' { $$ = new ExprStatementNode($1); DBG($$, @1, @2); } | ExprNoBF error { $$ = new ExprStatementNode($1); DBG($$, @1, @1); AUTO_SEMICOLON; } ; IfStatement: IF '(' Expr ')' Statement %prec IF_WITHOUT_ELSE { $$ = makeIfNode($3, $5, 0); DBG($$, @1, @4); } | IF '(' Expr ')' Statement ELSE Statement { $$ = makeIfNode($3, $5, $7); DBG($$, @1, @4); } ; IterationStatement: DO Statement WHILE '(' Expr ')' ';' { $$ = new DoWhileNode($2, $5); DBG($$, @1, @3);} | DO Statement WHILE '(' Expr ')' error { $$ = new DoWhileNode($2, $5); DBG($$, @1, @3); AUTO_SEMICOLON; } | WHILE '(' Expr ')' Statement { $$ = new WhileNode($3, $5); DBG($$, @1, @4); } | FOR '(' ExprNoInOpt ';' ExprOpt ';' ExprOpt ')' Statement { $$ = new ForNode($3, $5, $7, $9); DBG($$, @1, @8); } | FOR '(' VAR VariableDeclarationListNoIn ';' ExprOpt ';' ExprOpt ')' Statement { $$ = new ForNode($4, $6, $8, $10); DBG($$, @1, @9); } | FOR '(' LeftHandSideExpr INTOKEN Expr ')' Statement { Node *n = $3->nodeInsideAllParens(); if (!n->isLocation()) YYABORT; $$ = new ForInNode(n, $5, $7); DBG($$, @1, @6); } | FOR '(' VAR IDENT INTOKEN Expr ')' Statement { $$ = new ForInNode(*$4, 0, $6, $8); DBG($$, @1, @7); } | FOR '(' VAR IDENT InitializerNoIn INTOKEN Expr ')' Statement { $$ = new ForInNode(*$4, $5, $7, $9); DBG($$, @1, @8); } ; ExprOpt: /* nothing */ { $$ = 0; } | Expr ; ExprNoInOpt: /* nothing */ { $$ = 0; } | ExprNoIn ; ContinueStatement: CONTINUE ';' { $$ = new ContinueNode(); DBG($$, @1, @2); } | CONTINUE error { $$ = new ContinueNode(); DBG($$, @1, @1); AUTO_SEMICOLON; } | CONTINUE IDENT ';' { $$ = new ContinueNode(*$2); DBG($$, @1, @3); } | CONTINUE IDENT error { $$ = new ContinueNode(*$2); DBG($$, @1, @2); AUTO_SEMICOLON; } ; BreakStatement: BREAK ';' { $$ = new BreakNode(); DBG($$, @1, @2); } | BREAK error { $$ = new BreakNode(); DBG($$, @1, @1); AUTO_SEMICOLON; } | BREAK IDENT ';' { $$ = new BreakNode(*$2); DBG($$, @1, @3); } | BREAK IDENT error { $$ = new BreakNode(*$2); DBG($$, @1, @2); AUTO_SEMICOLON; } ; ReturnStatement: RETURN ';' { $$ = new ReturnNode(0); DBG($$, @1, @2); } | RETURN error { $$ = new ReturnNode(0); DBG($$, @1, @1); AUTO_SEMICOLON; } | RETURN Expr ';' { $$ = new ReturnNode($2); DBG($$, @1, @3); } | RETURN Expr error { $$ = new ReturnNode($2); DBG($$, @1, @2); AUTO_SEMICOLON; } ; WithStatement: WITH '(' Expr ')' Statement { $$ = new WithNode($3, $5); DBG($$, @1, @4); } ; SwitchStatement: SWITCH '(' Expr ')' CaseBlock { $$ = new SwitchNode($3, $5); DBG($$, @1, @4); } ; CaseBlock: '{' CaseClausesOpt '}' { $$ = new CaseBlockNode($2, 0, 0); } | '{' CaseClausesOpt DefaultClause CaseClausesOpt '}' { $$ = new CaseBlockNode($2, $3, $4); } ; CaseClausesOpt: /* nothing */ { $$ = 0; } | CaseClauses ; CaseClauses: CaseClause { $$ = new ClauseListNode($1); } | CaseClauses CaseClause { $$ = new ClauseListNode($1, $2); } ; CaseClause: CASE Expr ':' { $$ = new CaseClauseNode($2); } | CASE Expr ':' SourceElements { $$ = new CaseClauseNode($2, $4); } ; DefaultClause: DEFAULT ':' { $$ = new CaseClauseNode(0); } | DEFAULT ':' SourceElements { $$ = new CaseClauseNode(0, $3); } ; LabelledStatement: IDENT ':' Statement { $$ = makeLabelNode(*$1, $3); } ; ThrowStatement: THROW Expr ';' { $$ = new ThrowNode($2); DBG($$, @1, @3); } | THROW Expr error { $$ = new ThrowNode($2); DBG($$, @1, @2); AUTO_SEMICOLON; } ; TryStatement: TRY Block FINALLY Block { $$ = new TryNode($2, CommonIdentifiers::shared()->nullIdentifier, 0, $4); DBG($$, @1, @2); } | TRY Block CATCH '(' IDENT ')' Block { $$ = new TryNode($2, *$5, $7, 0); DBG($$, @1, @2); } | TRY Block CATCH '(' IDENT ')' Block FINALLY Block { $$ = new TryNode($2, *$5, $7, $9); DBG($$, @1, @2); } ; DebuggerStatement: DEBUGGER ';' { $$ = new EmptyStatementNode(); DBG($$, @1, @2); } | DEBUGGER error { $$ = new EmptyStatementNode(); DBG($$, @1, @1); AUTO_SEMICOLON; } ; PackageName: IDENT { $$ = new PackageNameNode(*$1); } | PackageName '.' IDENT { $$ = new PackageNameNode($1, *$3); } ; ImportStatement: IMPORT PackageName '.' '*' ';' { $$ = makeImportNode($2, true, 0); DBG($$, @1, @5); } | IMPORT PackageName '.' '*' error { $$ = makeImportNode($2, true, 0); DBG($$, @1, @5); AUTO_SEMICOLON; } | IMPORT PackageName ';' { $$ = makeImportNode($2, false, 0); DBG($$, @1, @3); } | IMPORT PackageName error { $$ = makeImportNode($2, false, 0); DBG($$, @1, @3); AUTO_SEMICOLON; } | IMPORT IDENT '=' PackageName ';' { $$ = makeImportNode($4, false, *$2); DBG($$, @1, @5); } | IMPORT IDENT '=' PackageName error { $$ = makeImportNode($4, false, *$2); DBG($$, @1, @5); AUTO_SEMICOLON; } ; FunctionDeclaration: FUNCTION IDENT '(' ')' {inFuncDecl();} FunctionBody { $$ = new FuncDeclNode(*$2, $6); } | FUNCTION IDENT '(' FormalParameterList ')' {inFuncDecl();} FunctionBody { $$ = new FuncDeclNode(*$2, $4, $7); } ; FunctionExpr: FUNCTION '(' ')' {inFuncExpr();} FunctionBody { $$ = new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, $5); } | FUNCTION '(' FormalParameterList ')' {inFuncExpr();} FunctionBody { $$ = new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, $6, $3); } | FUNCTION IDENT '(' ')' {inFuncExpr();} FunctionBody { $$ = new FuncExprNode(*$2, $6); } | FUNCTION IDENT '(' FormalParameterList ')' {inFuncExpr();} FunctionBody { $$ = new FuncExprNode(*$2, $7, $4); } ; FormalParameterList: IDENT { $$ = new ParameterNode(*$1); } | FormalParameterList ',' IDENT { $$ = new ParameterNode($1, *$3); } ; FunctionBody: '{' '}' /* not in spec */ { $$ = new FunctionBodyNode(0); DBG($$, @1, @2); } | '{' SourceElements '}' { $$ = new FunctionBodyNode($2); DBG($$, @1, @3); } ; Program: /* not in spec */ { parser().didFinishParsing(new ProgramNode(0)); } | SourceElements { parser().didFinishParsing(new ProgramNode($1)); } ; SourceElements: SourceElement { $$ = new SourceElementsNode($1); } | SourceElements SourceElement { $$ = new SourceElementsNode($1, $2); } ; SourceElement: FunctionDeclaration { $$ = $1; } | Statement { $$ = $1; } ; %% /* called by yyparse on error */ int yyerror(const char *) { // fprintf(stderr, "ERROR: %s at line %d\n", s, KJS::Lexer::curr()->lineNo()); return 1; } /* may we automatically insert a semicolon ? */ static bool allowAutomaticSemicolon() { return yychar == '}' || yychar == 0 || lexer().prevTerminator(); } // kate: indent-width 2; replace-tabs on; tab-width 4; space-indent on;