%{ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. * Copyright (C) 2007 Eric Seidel * * 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 "config.h" #include #include #include "value.h" #include "object.h" #include "types.h" #include "nodes.h" #include "lexer.h" #include "internal.h" #include "CommonIdentifiers.h" #include "NodeInfo.h" #include "Parser.h" #include // Not sure why, but yacc doesn't add this define along with the others. #define yylloc kjsyylloc #define YYMAXDEPTH 10000 #define YYENABLE_NLS 0 /* 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) using namespace KJS; using namespace std; static AddNode* makeAddNode(ExpressionNode*, ExpressionNode*); static LessNode* makeLessNode(ExpressionNode*, ExpressionNode*); static ExpressionNode* makeAssignNode(ExpressionNode* loc, Operator, ExpressionNode* expr); static ExpressionNode* makePrefixNode(ExpressionNode* expr, Operator); static ExpressionNode* makePostfixNode(ExpressionNode* expr, Operator); static PropertyNode* makeGetterOrSetterPropertyNode(const Identifier &getOrSet, const Identifier& name, ParameterNode*, FunctionBodyNode*); static ExpressionNode* makeFunctionCallNode(ExpressionNode* func, ArgumentsNode*); static ExpressionNode* makeTypeOfNode(ExpressionNode*); static ExpressionNode* makeDeleteNode(ExpressionNode*); static ExpressionNode* makeNegateNode(ExpressionNode*); static NumberNode* makeNumberNode(double); static StatementNode* makeVarStatementNode(ExpressionNode*); static ExpressionNode* combineVarInitializers(ExpressionNode* list, AssignResolveNode* init); #if COMPILER(MSVC) #pragma warning(disable: 4065) #pragma warning(disable: 4244) #pragma warning(disable: 4702) // At least some of the time, the declarations of malloc and free that bison // generates are causing warnings. A way to avoid this is to explicitly define // the macros so that bison doesn't try to declare malloc and free. #define YYMALLOC malloc #define YYFREE free #endif template NodeInfo createNodeInfo(T node, ParserRefCountedData* varDecls, ParserRefCountedData* funcDecls) { NodeInfo result = {node, varDecls, funcDecls}; return result; } template T mergeDeclarationLists(T decls1, T decls2) { // decls1 or both are null if (!decls1) return decls2; // only decls1 is non-null if (!decls2) return decls1; // Both are non-null decls1->data.append(decls2->data); // We manually release the declaration lists to avoid accumulating many many // unused heap allocated vectors decls2->ref(); decls2->deref(); return decls1; } static void appendToVarDeclarationList(ParserRefCountedData*& varDecls, const Identifier& ident, unsigned attrs) { if (!varDecls) varDecls = new ParserRefCountedData; varDecls->data.append(make_pair(ident, attrs)); } static inline void appendToVarDeclarationList(ParserRefCountedData*& varDecls, ConstDeclNode* decl) { unsigned attrs = DeclarationStacks::IsConstant; if (decl->m_init) attrs |= DeclarationStacks::HasInitializer; appendToVarDeclarationList(varDecls, decl->m_ident, attrs); } %} %union { int intValue; double doubleValue; UString* string; Identifier* ident; // expression subtrees ExpressionNode* expressionNode; FuncDeclNode* funcDeclNode; PropertyNode* propertyNode; ArgumentsNode* argumentsNode; ConstDeclNode* constDeclNode; CaseBlockNodeInfo caseBlockNode; CaseClauseNodeInfo caseClauseNode; FuncExprNode* funcExprNode; // statement nodes StatementNodeInfo statementNode; FunctionBodyNode* functionBodyNode; ProgramNode* programNode; SourceElementsInfo sourceElements; PropertyList propertyList; ArgumentList argumentList; VarDeclListInfo varDeclList; ConstDeclListInfo constDeclList; ClauseListInfo clauseList; ElementList elementList; ParameterList parameterList; Operator op; } %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 /* 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 %type SourceElement %type Initializer InitializerNoIn %type FunctionDeclaration %type FunctionExpr %type FunctionBody %type SourceElements %type FormalParameterList %type AssignmentOperator %type Arguments %type ArgumentList %type VariableDeclarationList VariableDeclarationListNoIn %type ConstDeclarationList %type ConstDeclaration %type CaseBlock %type CaseClause DefaultClause %type CaseClauses CaseClausesOpt %type Elision ElisionOpt %type ElementList %type Property %type PropertyList %% Literal: NULLTOKEN { $$ = new NullNode; } | TRUETOKEN { $$ = new TrueNode; } | FALSETOKEN { $$ = new FalseNode; } | NUMBER { $$ = makeNumberNode($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()); } ; Property: IDENT ':' AssignmentExpr { $$ = new PropertyNode(*$1, $3, PropertyNode::Constant); } | STRING ':' AssignmentExpr { $$ = new PropertyNode(Identifier(*$1), $3, PropertyNode::Constant); } | NUMBER ':' AssignmentExpr { $$ = new PropertyNode(Identifier(UString::from($1)), $3, PropertyNode::Constant); } | IDENT IDENT '(' ')' '{' FunctionBody '}' { $$ = makeGetterOrSetterPropertyNode(*$1, *$2, 0, $6); DBG($6, @5, @7); if (!$$) YYABORT; } | IDENT IDENT '(' FormalParameterList ')' '{' FunctionBody '}' { $$ = makeGetterOrSetterPropertyNode(*$1, *$2, $4.head, $7); DBG($7, @6, @8); if (!$$) YYABORT; } ; PropertyList: Property { $$.head = new PropertyListNode($1); $$.tail = $$.head; } | PropertyList ',' Property { $$.head = $1.head; $$.tail = new PropertyListNode($3, $1.tail); } ; PrimaryExpr: PrimaryExprNoBrace | '{' '}' { $$ = new ObjectLiteralNode(); } | '{' PropertyList '}' { $$ = new ObjectLiteralNode($2.head); } /* allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 */ | '{' PropertyList ',' '}' { $$ = new ObjectLiteralNode($2.head); } ; PrimaryExprNoBrace: THISTOKEN { $$ = new ThisNode(); } | Literal | ArrayLiteral | IDENT { $$ = new ResolveNode(*$1); } | '(' Expr ')' { $$ = $2; } ; ArrayLiteral: '[' ElisionOpt ']' { $$ = new ArrayNode($2); } | '[' ElementList ']' { $$ = new ArrayNode($2.head); } | '[' ElementList ',' ElisionOpt ']' { $$ = new ArrayNode($4, $2.head); } ; ElementList: ElisionOpt AssignmentExpr { $$.head = new ElementNode($1, $2); $$.tail = $$.head; } | ElementList ',' ElisionOpt AssignmentExpr { $$.head = $1.head; $$.tail = new ElementNode($1.tail, $3, $4); } ; ElisionOpt: /* nothing */ { $$ = 0; } | Elision ; Elision: ',' { $$ = 1; } | Elision ',' { $$ = $1 + 1; } ; MemberExpr: PrimaryExpr | FunctionExpr { $$ = $1; } | MemberExpr '[' Expr ']' { $$ = new BracketAccessorNode($1, $3); } | MemberExpr '.' IDENT { $$ = new DotAccessorNode($1, *$3); } | NEW MemberExpr Arguments { $$ = new NewExprNode($2, $3); } ; MemberExprNoBF: PrimaryExprNoBrace | MemberExprNoBF '[' Expr ']' { $$ = new BracketAccessorNode($1, $3); } | MemberExprNoBF '.' IDENT { $$ = 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 '.' IDENT { $$ = new DotAccessorNode($1, *$3); } ; CallExprNoBF: MemberExprNoBF Arguments { $$ = makeFunctionCallNode($1, $2); } | CallExprNoBF Arguments { $$ = makeFunctionCallNode($1, $2); } | CallExprNoBF '[' Expr ']' { $$ = new BracketAccessorNode($1, $3); } | CallExprNoBF '.' IDENT { $$ = new DotAccessorNode($1, *$3); } ; Arguments: '(' ')' { $$ = new ArgumentsNode(); } | '(' ArgumentList ')' { $$ = new ArgumentsNode($2.head); } ; ArgumentList: AssignmentExpr { $$.head = new ArgumentListNode($1); $$.tail = $$.head; } | ArgumentList ',' AssignmentExpr { $$.head = $1.head; $$.tail = new ArgumentListNode($1.tail, $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 { $$ = new UnaryPlusNode($2); } | '-' UnaryExpr { $$ = makeNegateNode($2); } | '~' UnaryExpr { $$ = new BitwiseNotNode($2); } | '!' UnaryExpr { $$ = new LogicalNotNode($2); } UnaryExpr: PostfixExpr | UnaryExprCommon ; UnaryExprNoBF: PostfixExprNoBF | UnaryExprCommon ; MultiplicativeExpr: UnaryExpr | MultiplicativeExpr '*' UnaryExpr { $$ = new MultNode($1, $3); } | MultiplicativeExpr '/' UnaryExpr { $$ = new DivNode($1, $3); } | MultiplicativeExpr '%' UnaryExpr { $$ = new ModNode($1, $3); } ; MultiplicativeExprNoBF: UnaryExprNoBF | MultiplicativeExprNoBF '*' UnaryExpr { $$ = new MultNode($1, $3); } | MultiplicativeExprNoBF '/' UnaryExpr { $$ = new DivNode($1, $3); } | MultiplicativeExprNoBF '%' UnaryExpr { $$ = new ModNode($1, $3); } ; AdditiveExpr: MultiplicativeExpr | AdditiveExpr '+' MultiplicativeExpr { $$ = makeAddNode($1, $3); } | AdditiveExpr '-' MultiplicativeExpr { $$ = new SubNode($1, $3); } ; AdditiveExprNoBF: MultiplicativeExprNoBF | AdditiveExprNoBF '+' MultiplicativeExpr { $$ = makeAddNode($1, $3); } | AdditiveExprNoBF '-' MultiplicativeExpr { $$ = new SubNode($1, $3); } ; ShiftExpr: AdditiveExpr | ShiftExpr LSHIFT AdditiveExpr { $$ = new LeftShiftNode($1, $3); } | ShiftExpr RSHIFT AdditiveExpr { $$ = new RightShiftNode($1, $3); } | ShiftExpr URSHIFT AdditiveExpr { $$ = new UnsignedRightShiftNode($1, $3); } ; ShiftExprNoBF: AdditiveExprNoBF | ShiftExprNoBF LSHIFT AdditiveExpr { $$ = new LeftShiftNode($1, $3); } | ShiftExprNoBF RSHIFT AdditiveExpr { $$ = new RightShiftNode($1, $3); } | ShiftExprNoBF URSHIFT AdditiveExpr { $$ = new UnsignedRightShiftNode($1, $3); } ; RelationalExpr: ShiftExpr | RelationalExpr '<' ShiftExpr { $$ = makeLessNode($1, $3); } | RelationalExpr '>' ShiftExpr { $$ = new GreaterNode($1, $3); } | RelationalExpr LE ShiftExpr { $$ = new LessEqNode($1, $3); } | RelationalExpr GE ShiftExpr { $$ = new GreaterEqNode($1, $3); } | RelationalExpr INSTANCEOF ShiftExpr { $$ = new InstanceOfNode($1, $3); } | RelationalExpr INTOKEN ShiftExpr { $$ = new InNode($1, $3); } ; RelationalExprNoIn: ShiftExpr | RelationalExprNoIn '<' ShiftExpr { $$ = makeLessNode($1, $3); } | RelationalExprNoIn '>' ShiftExpr { $$ = new GreaterNode($1, $3); } | RelationalExprNoIn LE ShiftExpr { $$ = new LessEqNode($1, $3); } | RelationalExprNoIn GE ShiftExpr { $$ = new GreaterEqNode($1, $3); } | RelationalExprNoIn INSTANCEOF ShiftExpr { $$ = new InstanceOfNode($1, $3); } ; RelationalExprNoBF: ShiftExprNoBF | RelationalExprNoBF '<' ShiftExpr { $$ = makeLessNode($1, $3); } | RelationalExprNoBF '>' ShiftExpr { $$ = new GreaterNode($1, $3); } | RelationalExprNoBF LE ShiftExpr { $$ = new LessEqNode($1, $3); } | RelationalExprNoBF GE ShiftExpr { $$ = new GreaterEqNode($1, $3); } | RelationalExprNoBF INSTANCEOF ShiftExpr { $$ = new InstanceOfNode($1, $3); } | RelationalExprNoBF INTOKEN ShiftExpr { $$ = new InNode($1, $3); } ; EqualityExpr: RelationalExpr | EqualityExpr EQEQ RelationalExpr { $$ = new EqualNode($1, $3); } | EqualityExpr NE RelationalExpr { $$ = new NotEqualNode($1, $3); } | EqualityExpr STREQ RelationalExpr { $$ = new StrictEqualNode($1, $3); } | EqualityExpr STRNEQ RelationalExpr { $$ = new NotStrictEqualNode($1, $3); } ; EqualityExprNoIn: RelationalExprNoIn | EqualityExprNoIn EQEQ RelationalExprNoIn { $$ = new EqualNode($1, $3); } | EqualityExprNoIn NE RelationalExprNoIn { $$ = new NotEqualNode($1, $3); } | EqualityExprNoIn STREQ RelationalExprNoIn { $$ = new StrictEqualNode($1, $3); } | EqualityExprNoIn STRNEQ RelationalExprNoIn { $$ = new NotStrictEqualNode($1, $3); } ; EqualityExprNoBF: RelationalExprNoBF | EqualityExprNoBF EQEQ RelationalExpr { $$ = new EqualNode($1, $3); } | EqualityExprNoBF NE RelationalExpr { $$ = new NotEqualNode($1, $3); } | EqualityExprNoBF STREQ RelationalExpr { $$ = new StrictEqualNode($1, $3); } | EqualityExprNoBF STRNEQ RelationalExpr { $$ = new NotStrictEqualNode($1, $3); } ; BitwiseANDExpr: EqualityExpr | BitwiseANDExpr '&' EqualityExpr { $$ = new BitAndNode($1, $3); } ; BitwiseANDExprNoIn: EqualityExprNoIn | BitwiseANDExprNoIn '&' EqualityExprNoIn { $$ = new BitAndNode($1, $3); } ; BitwiseANDExprNoBF: EqualityExprNoBF | BitwiseANDExprNoBF '&' EqualityExpr { $$ = new BitAndNode($1, $3); } ; BitwiseXORExpr: BitwiseANDExpr | BitwiseXORExpr '^' BitwiseANDExpr { $$ = new BitXOrNode($1, $3); } ; BitwiseXORExprNoIn: BitwiseANDExprNoIn | BitwiseXORExprNoIn '^' BitwiseANDExprNoIn { $$ = new BitXOrNode($1, $3); } ; BitwiseXORExprNoBF: BitwiseANDExprNoBF | BitwiseXORExprNoBF '^' BitwiseANDExpr { $$ = new BitXOrNode($1, $3); } ; BitwiseORExpr: BitwiseXORExpr | BitwiseORExpr '|' BitwiseXORExpr { $$ = new BitOrNode($1, $3); } ; BitwiseORExprNoIn: BitwiseXORExprNoIn | BitwiseORExprNoIn '|' BitwiseXORExprNoIn { $$ = new BitOrNode($1, $3); } ; BitwiseORExprNoBF: BitwiseXORExprNoBF | BitwiseORExprNoBF '|' BitwiseXORExpr { $$ = new BitOrNode($1, $3); } ; LogicalANDExpr: BitwiseORExpr | LogicalANDExpr AND BitwiseORExpr { $$ = new LogicalAndNode($1, $3); } ; LogicalANDExprNoIn: BitwiseORExprNoIn | LogicalANDExprNoIn AND BitwiseORExprNoIn { $$ = new LogicalAndNode($1, $3); } ; LogicalANDExprNoBF: BitwiseORExprNoBF | LogicalANDExprNoBF AND BitwiseORExpr { $$ = new LogicalAndNode($1, $3); } ; LogicalORExpr: LogicalANDExpr | LogicalORExpr OR LogicalANDExpr { $$ = new LogicalOrNode($1, $3); } ; LogicalORExprNoIn: LogicalANDExprNoIn | LogicalORExprNoIn OR LogicalANDExprNoIn { $$ = new LogicalOrNode($1, $3); } ; LogicalORExprNoBF: LogicalANDExprNoBF | LogicalORExprNoBF OR LogicalANDExpr { $$ = new LogicalOrNode($1, $3); } ; ConditionalExpr: LogicalORExpr | LogicalORExpr '?' AssignmentExpr ':' AssignmentExpr { $$ = new ConditionalNode($1, $3, $5); } ; ConditionalExprNoIn: LogicalORExprNoIn | LogicalORExprNoIn '?' AssignmentExprNoIn ':' AssignmentExprNoIn { $$ = new ConditionalNode($1, $3, $5); } ; ConditionalExprNoBF: LogicalORExprNoBF | LogicalORExprNoBF '?' AssignmentExpr ':' AssignmentExpr { $$ = new ConditionalNode($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 ; Block: '{' '}' { $$ = createNodeInfo(new BlockNode(0), 0, 0); DBG($$.m_node, @1, @2); } | '{' SourceElements '}' { $$ = createNodeInfo(new BlockNode($2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations); DBG($$.m_node, @1, @3); } ; VariableStatement: VAR VariableDeclarationList ';' { $$ = createNodeInfo(makeVarStatementNode($2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations); DBG($$.m_node, @1, @3); } | VAR VariableDeclarationList error { $$ = createNodeInfo(makeVarStatementNode($2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; } ; VariableDeclarationList: IDENT { $$.m_node = 0; $$.m_varDeclarations = new ParserRefCountedData; appendToVarDeclarationList($$.m_varDeclarations, *$1, 0); $$.m_funcDeclarations = 0; } | IDENT Initializer { $$.m_node = new AssignResolveNode(*$1, $2); $$.m_varDeclarations = new ParserRefCountedData; appendToVarDeclarationList($$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer); $$.m_funcDeclarations = 0; } | VariableDeclarationList ',' IDENT { $$.m_node = $1.m_node; $$.m_varDeclarations = $1.m_varDeclarations; appendToVarDeclarationList($$.m_varDeclarations, *$3, 0); $$.m_funcDeclarations = 0; } | VariableDeclarationList ',' IDENT Initializer { $$.m_node = combineVarInitializers($1.m_node, new AssignResolveNode(*$3, $4)); $$.m_varDeclarations = $1.m_varDeclarations; appendToVarDeclarationList($$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer); $$.m_funcDeclarations = 0; } ; VariableDeclarationListNoIn: IDENT { $$.m_node = 0; $$.m_varDeclarations = new ParserRefCountedData; appendToVarDeclarationList($$.m_varDeclarations, *$1, 0); $$.m_funcDeclarations = 0; } | IDENT InitializerNoIn { $$.m_node = new AssignResolveNode(*$1, $2); $$.m_varDeclarations = new ParserRefCountedData; appendToVarDeclarationList($$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer); $$.m_funcDeclarations = 0; } | VariableDeclarationListNoIn ',' IDENT { $$.m_node = $1.m_node; $$.m_varDeclarations = $1.m_varDeclarations; appendToVarDeclarationList($$.m_varDeclarations, *$3, 0); $$.m_funcDeclarations = 0; } | VariableDeclarationListNoIn ',' IDENT InitializerNoIn { $$.m_node = combineVarInitializers($1.m_node, new AssignResolveNode(*$3, $4)); $$.m_varDeclarations = $1.m_varDeclarations; appendToVarDeclarationList($$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer); $$.m_funcDeclarations = 0; } ; ConstStatement: CONSTTOKEN ConstDeclarationList ';' { $$ = createNodeInfo(new ConstStatementNode($2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations); DBG($$.m_node, @1, @3); } | CONSTTOKEN ConstDeclarationList error { $$ = createNodeInfo(new ConstStatementNode($2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; } ; ConstDeclarationList: ConstDeclaration { $$.m_node.head = $1; $$.m_node.tail = $$.m_node.head; $$.m_varDeclarations = new ParserRefCountedData; appendToVarDeclarationList($$.m_varDeclarations, $1); $$.m_funcDeclarations = 0; } | ConstDeclarationList ',' ConstDeclaration { $$.m_node.head = $1.m_node.head; $1.m_node.tail->m_next = $3; $$.m_node.tail = $3; $$.m_varDeclarations = $1.m_varDeclarations; appendToVarDeclarationList($$.m_varDeclarations, $3); $$.m_funcDeclarations = 0; } ; ConstDeclaration: IDENT { $$ = new ConstDeclNode(*$1, 0); } | IDENT Initializer { $$ = new ConstDeclNode(*$1, $2); } ; Initializer: '=' AssignmentExpr { $$ = $2; } ; InitializerNoIn: '=' AssignmentExprNoIn { $$ = $2; } ; EmptyStatement: ';' { $$ = createNodeInfo(new EmptyStatementNode(), 0, 0); } ; ExprStatement: ExprNoBF ';' { $$ = createNodeInfo(new ExprStatementNode($1), 0, 0); DBG($$.m_node, @1, @2); } | ExprNoBF error { $$ = createNodeInfo(new ExprStatementNode($1), 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; } ; IfStatement: IF '(' Expr ')' Statement %prec IF_WITHOUT_ELSE { $$ = createNodeInfo(new IfNode($3, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations); DBG($$.m_node, @1, @4); } | IF '(' Expr ')' Statement ELSE Statement { $$ = createNodeInfo(new IfElseNode($3, $5.m_node, $7.m_node), mergeDeclarationLists($5.m_varDeclarations, $7.m_varDeclarations), mergeDeclarationLists($5.m_funcDeclarations, $7.m_funcDeclarations)); DBG($$.m_node, @1, @4); } ; IterationStatement: DO Statement WHILE '(' Expr ')' ';' { $$ = createNodeInfo(new DoWhileNode($2.m_node, $5), $2.m_varDeclarations, $2.m_funcDeclarations); DBG($$.m_node, @1, @3); } | DO Statement WHILE '(' Expr ')' error { $$ = createNodeInfo(new DoWhileNode($2.m_node, $5), $2.m_varDeclarations, $2.m_funcDeclarations); DBG($$.m_node, @1, @3); } // Always performs automatic semicolon insertion. | WHILE '(' Expr ')' Statement { $$ = createNodeInfo(new WhileNode($3, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations); DBG($$.m_node, @1, @4); } | FOR '(' ExprNoInOpt ';' ExprOpt ';' ExprOpt ')' Statement { $$ = createNodeInfo(new ForNode($3, $5, $7, $9.m_node, false), $9.m_varDeclarations, $9.m_funcDeclarations); DBG($$.m_node, @1, @8); } | FOR '(' VAR VariableDeclarationListNoIn ';' ExprOpt ';' ExprOpt ')' Statement { $$ = createNodeInfo(new ForNode($4.m_node, $6, $8, $10.m_node, true), mergeDeclarationLists($4.m_varDeclarations, $10.m_varDeclarations), mergeDeclarationLists($4.m_funcDeclarations, $10.m_funcDeclarations)); DBG($$.m_node, @1, @9); } | FOR '(' LeftHandSideExpr INTOKEN Expr ')' Statement { ExpressionNode* n = $3; if (!n->isLocation()) YYABORT; $$ = createNodeInfo(new ForInNode(n, $5, $7.m_node), $7.m_varDeclarations, $7.m_funcDeclarations); DBG($$.m_node, @1, @6); } | FOR '(' VAR IDENT INTOKEN Expr ')' Statement { ForInNode *forIn = new ForInNode(*$4, 0, $6, $8.m_node); appendToVarDeclarationList($8.m_varDeclarations, *$4, DeclarationStacks::HasInitializer); $$ = createNodeInfo(forIn, $8.m_varDeclarations, $8.m_funcDeclarations); DBG($$.m_node, @1, @7); } | FOR '(' VAR IDENT InitializerNoIn INTOKEN Expr ')' Statement { ForInNode *forIn = new ForInNode(*$4, $5, $7, $9.m_node); appendToVarDeclarationList($9.m_varDeclarations, *$4, DeclarationStacks::HasInitializer); $$ = createNodeInfo(forIn, $9.m_varDeclarations, $9.m_funcDeclarations); DBG($$.m_node, @1, @8); } ; ExprOpt: /* nothing */ { $$ = 0; } | Expr ; ExprNoInOpt: /* nothing */ { $$ = 0; } | ExprNoIn ; ContinueStatement: CONTINUE ';' { $$ = createNodeInfo(new ContinueNode(), 0, 0); DBG($$.m_node, @1, @2); } | CONTINUE error { $$ = createNodeInfo(new ContinueNode(), 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; } | CONTINUE IDENT ';' { $$ = createNodeInfo(new ContinueNode(*$2), 0, 0); DBG($$.m_node, @1, @3); } | CONTINUE IDENT error { $$ = createNodeInfo(new ContinueNode(*$2), 0, 0); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; } ; BreakStatement: BREAK ';' { $$ = createNodeInfo(new BreakNode(), 0, 0); DBG($$.m_node, @1, @2); } | BREAK error { $$ = createNodeInfo(new BreakNode(), 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; } | BREAK IDENT ';' { $$ = createNodeInfo(new BreakNode(*$2), 0, 0); DBG($$.m_node, @1, @3); } | BREAK IDENT error { $$ = createNodeInfo(new BreakNode(*$2), 0, 0); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; } ; ReturnStatement: RETURN ';' { $$ = createNodeInfo(new ReturnNode(0), 0, 0); DBG($$.m_node, @1, @2); } | RETURN error { $$ = createNodeInfo(new ReturnNode(0), 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; } | RETURN Expr ';' { $$ = createNodeInfo(new ReturnNode($2), 0, 0); DBG($$.m_node, @1, @3); } | RETURN Expr error { $$ = createNodeInfo(new ReturnNode($2), 0, 0); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; } ; WithStatement: WITH '(' Expr ')' Statement { $$ = createNodeInfo(new WithNode($3, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations); DBG($$.m_node, @1, @4); } ; SwitchStatement: SWITCH '(' Expr ')' CaseBlock { $$ = createNodeInfo(new SwitchNode($3, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations); DBG($$.m_node, @1, @4); } ; CaseBlock: '{' CaseClausesOpt '}' { $$ = createNodeInfo(new CaseBlockNode($2.m_node.head, 0, 0), $2.m_varDeclarations, $2.m_funcDeclarations); } | '{' CaseClausesOpt DefaultClause CaseClausesOpt '}' { $$ = createNodeInfo(new CaseBlockNode($2.m_node.head, $3.m_node, $4.m_node.head), mergeDeclarationLists(mergeDeclarationLists($2.m_varDeclarations, $3.m_varDeclarations), $4.m_varDeclarations), mergeDeclarationLists(mergeDeclarationLists($2.m_funcDeclarations, $3.m_funcDeclarations), $4.m_funcDeclarations)); } ; CaseClausesOpt: /* nothing */ { $$.m_node.head = 0; $$.m_node.tail = 0; $$.m_varDeclarations = 0; $$.m_funcDeclarations = 0; } | CaseClauses ; CaseClauses: CaseClause { $$.m_node.head = new ClauseListNode($1.m_node); $$.m_node.tail = $$.m_node.head; $$.m_varDeclarations = $1.m_varDeclarations; $$.m_funcDeclarations = $1.m_funcDeclarations; } | CaseClauses CaseClause { $$.m_node.head = $1.m_node.head; $$.m_node.tail = new ClauseListNode($1.m_node.tail, $2.m_node); $$.m_varDeclarations = mergeDeclarationLists($1.m_varDeclarations, $2.m_varDeclarations); $$.m_funcDeclarations = mergeDeclarationLists($1.m_funcDeclarations, $2.m_funcDeclarations); } ; CaseClause: CASE Expr ':' { $$ = createNodeInfo(new CaseClauseNode($2), 0, 0); } | CASE Expr ':' SourceElements { $$ = createNodeInfo(new CaseClauseNode($2, $4.m_node), $4.m_varDeclarations, $4.m_funcDeclarations); } ; DefaultClause: DEFAULT ':' { $$ = createNodeInfo(new CaseClauseNode(0), 0, 0); } | DEFAULT ':' SourceElements { $$ = createNodeInfo(new CaseClauseNode(0, $3.m_node), $3.m_varDeclarations, $3.m_funcDeclarations); } ; LabelledStatement: IDENT ':' Statement { $3.m_node->pushLabel(*$1); $$ = createNodeInfo(new LabelNode(*$1, $3.m_node), $3.m_varDeclarations, $3.m_funcDeclarations); } ; ThrowStatement: THROW Expr ';' { $$ = createNodeInfo(new ThrowNode($2), 0, 0); DBG($$.m_node, @1, @3); } | THROW Expr error { $$ = createNodeInfo(new ThrowNode($2), 0, 0); DBG($$.m_node, @1, @2); AUTO_SEMICOLON; } ; TryStatement: TRY Block FINALLY Block { $$ = createNodeInfo(new TryNode($2.m_node, CommonIdentifiers::shared()->nullIdentifier, 0, $4.m_node), mergeDeclarationLists($2.m_varDeclarations, $4.m_varDeclarations), mergeDeclarationLists($2.m_funcDeclarations, $4.m_funcDeclarations)); DBG($$.m_node, @1, @2); } | TRY Block CATCH '(' IDENT ')' Block { $$ = createNodeInfo(new TryNode($2.m_node, *$5, $7.m_node, 0), mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations), mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations)); DBG($$.m_node, @1, @2); } | TRY Block CATCH '(' IDENT ')' Block FINALLY Block { $$ = createNodeInfo(new TryNode($2.m_node, *$5, $7.m_node, $9.m_node), mergeDeclarationLists(mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations), $9.m_varDeclarations), mergeDeclarationLists(mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations), $9.m_funcDeclarations)); DBG($$.m_node, @1, @2); } ; DebuggerStatement: DEBUGGER ';' { $$ = createNodeInfo(new EmptyStatementNode(), 0, 0); DBG($$.m_node, @1, @2); } | DEBUGGER error { $$ = createNodeInfo(new EmptyStatementNode(), 0, 0); DBG($$.m_node, @1, @1); AUTO_SEMICOLON; } ; FunctionDeclaration: FUNCTION IDENT '(' ')' '{' FunctionBody '}' { $$ = new FuncDeclNode(*$2, $6); DBG($6, @5, @7); } | FUNCTION IDENT '(' FormalParameterList ')' '{' FunctionBody '}' { $$ = new FuncDeclNode(*$2, $4.head, $7); DBG($7, @6, @8); } ; FunctionExpr: FUNCTION '(' ')' '{' FunctionBody '}' { $$ = new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, $5); DBG($5, @4, @6); } | FUNCTION '(' FormalParameterList ')' '{' FunctionBody '}' { $$ = new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, $6, $3.head); DBG($6, @5, @7); } | FUNCTION IDENT '(' ')' '{' FunctionBody '}' { $$ = new FuncExprNode(*$2, $6); DBG($6, @5, @7); } | FUNCTION IDENT '(' FormalParameterList ')' '{' FunctionBody '}' { $$ = new FuncExprNode(*$2, $7, $4.head); DBG($7, @6, @8); } ; FormalParameterList: IDENT { $$.head = new ParameterNode(*$1); $$.tail = $$.head; } | FormalParameterList ',' IDENT { $$.head = $1.head; $$.tail = new ParameterNode($1.tail, *$3); } ; FunctionBody: /* not in spec */ { $$ = FunctionBodyNode::create(0, 0, 0); } | SourceElements { $$ = FunctionBodyNode::create($1.m_node, $1.m_varDeclarations ? &$1.m_varDeclarations->data : 0, $1.m_funcDeclarations ? &$1.m_funcDeclarations->data : 0); // As in mergeDeclarationLists() we have to ref/deref to safely get rid of // the declaration lists. if ($1.m_varDeclarations) { $1.m_varDeclarations->ref(); $1.m_varDeclarations->deref(); } if ($1.m_funcDeclarations) { $1.m_funcDeclarations->ref(); $1.m_funcDeclarations->deref(); } } ; Program: /* not in spec */ { parser().didFinishParsing(0, 0, 0, @0.last_line); } | SourceElements { parser().didFinishParsing($1.m_node, $1.m_varDeclarations, $1.m_funcDeclarations, @1.last_line); } ; SourceElements: SourceElement { $$.m_node = new SourceElements; $$.m_node->append($1.m_node); $$.m_varDeclarations = $1.m_varDeclarations; $$.m_funcDeclarations = $1.m_funcDeclarations; } | SourceElements SourceElement { $$.m_node->append($2.m_node); $$.m_varDeclarations = mergeDeclarationLists($1.m_varDeclarations, $2.m_varDeclarations); $$.m_funcDeclarations = mergeDeclarationLists($1.m_funcDeclarations, $2.m_funcDeclarations); } ; SourceElement: FunctionDeclaration { $$ = createNodeInfo($1, 0, new ParserRefCountedData); $$.m_funcDeclarations->data.append($1); } | Statement { $$ = $1; } ; %% static AddNode* makeAddNode(ExpressionNode* left, ExpressionNode* right) { JSType t1 = left->expectedReturnType(); JSType t2 = right->expectedReturnType(); if (t1 == NumberType && t2 == NumberType) return new AddNumbersNode(left, right); if (t1 == StringType && t2 == StringType) return new AddStringsNode(left, right); if (t1 == StringType) return new AddStringLeftNode(left, right); if (t2 == StringType) return new AddStringRightNode(left, right); return new AddNode(left, right); } static LessNode* makeLessNode(ExpressionNode* left, ExpressionNode* right) { JSType t1 = left->expectedReturnType(); JSType t2 = right->expectedReturnType(); if (t1 == StringType && t2 == StringType) return new LessStringsNode(left, right); // There are certainly more efficient ways to do this type check if necessary if (t1 == NumberType || t1 == BooleanType || t1 == UndefinedType || t1 == NullType || t2 == NumberType || t2 == BooleanType || t2 == UndefinedType || t2 == NullType) return new LessNumbersNode(left, right); // Neither is certain to be a number, nor were both certain to be strings, so we use the default (slow) implementation. return new LessNode(left, right); } static ExpressionNode* makeAssignNode(ExpressionNode* loc, Operator op, ExpressionNode* expr) { if (!loc->isLocation()) return new AssignErrorNode(loc, op, expr); if (loc->isResolveNode()) { ResolveNode* resolve = static_cast(loc); if (op == OpEqual) return new AssignResolveNode(resolve->identifier(), expr); else return new ReadModifyResolveNode(resolve->identifier(), op, expr); } if (loc->isBracketAccessorNode()) { BracketAccessorNode* bracket = static_cast(loc); if (op == OpEqual) return new AssignBracketNode(bracket->base(), bracket->subscript(), expr); else return new ReadModifyBracketNode(bracket->base(), bracket->subscript(), op, expr); } ASSERT(loc->isDotAccessorNode()); DotAccessorNode* dot = static_cast(loc); if (op == OpEqual) return new AssignDotNode(dot->base(), dot->identifier(), expr); return new ReadModifyDotNode(dot->base(), dot->identifier(), op, expr); } static ExpressionNode* makePrefixNode(ExpressionNode* expr, Operator op) { if (!expr->isLocation()) return new PrefixErrorNode(expr, op); if (expr->isResolveNode()) { ResolveNode* resolve = static_cast(expr); if (op == OpPlusPlus) return new PreIncResolveNode(resolve->identifier()); else return new PreDecResolveNode(resolve->identifier()); } if (expr->isBracketAccessorNode()) { BracketAccessorNode* bracket = static_cast(expr); if (op == OpPlusPlus) return new PreIncBracketNode(bracket->base(), bracket->subscript()); else return new PreDecBracketNode(bracket->base(), bracket->subscript()); } ASSERT(expr->isDotAccessorNode()); DotAccessorNode* dot = static_cast(expr); if (op == OpPlusPlus) return new PreIncDotNode(dot->base(), dot->identifier()); return new PreDecDotNode(dot->base(), dot->identifier()); } static ExpressionNode* makePostfixNode(ExpressionNode* expr, Operator op) { if (!expr->isLocation()) return new PostfixErrorNode(expr, op); if (expr->isResolveNode()) { ResolveNode* resolve = static_cast(expr); if (op == OpPlusPlus) return new PostIncResolveNode(resolve->identifier()); else return new PostDecResolveNode(resolve->identifier()); } if (expr->isBracketAccessorNode()) { BracketAccessorNode* bracket = static_cast(expr); if (op == OpPlusPlus) return new PostIncBracketNode(bracket->base(), bracket->subscript()); else return new PostDecBracketNode(bracket->base(), bracket->subscript()); } ASSERT(expr->isDotAccessorNode()); DotAccessorNode* dot = static_cast(expr); if (op == OpPlusPlus) return new PostIncDotNode(dot->base(), dot->identifier()); return new PostDecDotNode(dot->base(), dot->identifier()); } static ExpressionNode* makeFunctionCallNode(ExpressionNode* func, ArgumentsNode* args) { if (!func->isLocation()) return new FunctionCallValueNode(func, args); if (func->isResolveNode()) { ResolveNode* resolve = static_cast(func); return new FunctionCallResolveNode(resolve->identifier(), args); } if (func->isBracketAccessorNode()) { BracketAccessorNode* bracket = static_cast(func); return new FunctionCallBracketNode(bracket->base(), bracket->subscript(), args); } ASSERT(func->isDotAccessorNode()); DotAccessorNode* dot = static_cast(func); return new FunctionCallDotNode(dot->base(), dot->identifier(), args); } static ExpressionNode* makeTypeOfNode(ExpressionNode* expr) { if (expr->isResolveNode()) { ResolveNode* resolve = static_cast(expr); return new TypeOfResolveNode(resolve->identifier()); } return new TypeOfValueNode(expr); } static ExpressionNode* makeDeleteNode(ExpressionNode* expr) { if (!expr->isLocation()) return new DeleteValueNode(expr); if (expr->isResolveNode()) { ResolveNode* resolve = static_cast(expr); return new DeleteResolveNode(resolve->identifier()); } if (expr->isBracketAccessorNode()) { BracketAccessorNode* bracket = static_cast(expr); return new DeleteBracketNode(bracket->base(), bracket->subscript()); } ASSERT(expr->isDotAccessorNode()); DotAccessorNode* dot = static_cast(expr); return new DeleteDotNode(dot->base(), dot->identifier()); } static PropertyNode* makeGetterOrSetterPropertyNode(const Identifier& getOrSet, const Identifier& name, ParameterNode* params, FunctionBodyNode* body) { PropertyNode::Type type; if (getOrSet == "get") type = PropertyNode::Getter; else if (getOrSet == "set") type = PropertyNode::Setter; else return 0; return new PropertyNode(name, new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, body, params), type); } static ExpressionNode* makeNegateNode(ExpressionNode* n) { if (n->isNumber()) { NumberNode* number = static_cast(n); if (number->value() > 0.0) { number->setValue(-number->value()); return number; } } return new NegateNode(n); } static NumberNode* makeNumberNode(double d) { JSValue* value = JSImmediate::from(d); if (value) return new ImmediateNumberNode(value, d); return new NumberNode(d); } /* called by yyparse on error */ int yyerror(const char *) { return 1; } /* may we automatically insert a semicolon ? */ static bool allowAutomaticSemicolon() { return yychar == '}' || yychar == 0 || lexer().prevTerminator(); } static ExpressionNode* combineVarInitializers(ExpressionNode* list, AssignResolveNode* init) { if (!list) return init; return new VarDeclCommaNode(list, init); } // We turn variable declarations into either assignments or empty // statements (which later get stripped out), because the actual // declaration work is hoisted up to the start of the function body static StatementNode* makeVarStatementNode(ExpressionNode* expr) { if (!expr) return new EmptyStatementNode(); return new VarStatementNode(expr); }