webengine/osswebengine/JavaScriptCore/kjs/grammar.y
changeset 0 dd21522fd290
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/osswebengine/JavaScriptCore/kjs/grammar.y	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,1016 @@
+%{
+
+/*
+ *  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 "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include "value.h"
+#include "object.h"
+#include "types.h"
+#include "interpreter.h"
+#include "nodes.h"
+#include "lexer.h"
+#include "internal.h"
+#include "CommonIdentifiers.h"
+    
+// 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
+#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;
+
+static Node* makeAssignNode(Node* loc, Operator, Node* expr);
+static Node* makePrefixNode(Node* expr, Operator);
+static Node* makePostfixNode(Node* expr, Operator);
+static bool makeGetterOrSetterPropertyNode(PropertyNode*& result, Identifier &getOrSet, Identifier& name, ParameterNode *params, FunctionBodyNode *body);
+static Node *makeFunctionCallNode(Node *func, ArgumentsNode *args);
+static Node *makeTypeOfNode(Node *expr);
+static Node *makeDeleteNode(Node *expr);
+
+#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
+
+%}
+
+%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;
+}
+
+%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 <dval> NUMBER
+%token <ustr> STRING
+%token <ident> IDENT
+
+/* automatically inserted semicolon */
+%token AUTOPLUSPLUS AUTOMINUSMINUS
+
+/* non-terminal types */
+%type <node>  Literal ArrayLiteral
+
+%type <node>  PrimaryExpr PrimaryExprNoBrace
+%type <node>  MemberExpr MemberExprNoBF /* BF => brace or function */
+%type <node>  NewExpr NewExprNoBF
+%type <node>  CallExpr CallExprNoBF
+%type <node>  LeftHandSideExpr LeftHandSideExprNoBF
+%type <node>  PostfixExpr PostfixExprNoBF
+%type <node>  UnaryExpr UnaryExprNoBF UnaryExprCommon
+%type <node>  MultiplicativeExpr MultiplicativeExprNoBF
+%type <node>  AdditiveExpr AdditiveExprNoBF
+%type <node>  ShiftExpr ShiftExprNoBF
+%type <node>  RelationalExpr RelationalExprNoIn RelationalExprNoBF
+%type <node>  EqualityExpr EqualityExprNoIn EqualityExprNoBF
+%type <node>  BitwiseANDExpr BitwiseANDExprNoIn BitwiseANDExprNoBF
+%type <node>  BitwiseXORExpr BitwiseXORExprNoIn BitwiseXORExprNoBF
+%type <node>  BitwiseORExpr BitwiseORExprNoIn BitwiseORExprNoBF
+%type <node>  LogicalANDExpr LogicalANDExprNoIn LogicalANDExprNoBF
+%type <node>  LogicalORExpr LogicalORExprNoIn LogicalORExprNoBF
+%type <node>  ConditionalExpr ConditionalExprNoIn ConditionalExprNoBF
+%type <node>  AssignmentExpr AssignmentExprNoIn AssignmentExprNoBF
+%type <node>  Expr ExprNoIn ExprNoBF
+
+%type <node>  ExprOpt ExprNoInOpt
+
+%type <stat>  Statement Block
+%type <stat>  VariableStatement ConstStatement EmptyStatement ExprStatement
+%type <stat>  IfStatement IterationStatement ContinueStatement
+%type <stat>  BreakStatement ReturnStatement WithStatement
+%type <stat>  SwitchStatement LabelledStatement
+%type <stat>  ThrowStatement TryStatement
+%type <stat>  DebuggerStatement
+%type <stat>  SourceElement
+
+%type <init>  Initializer InitializerNoIn
+%type <func>  FunctionDeclaration
+%type <funcExpr>  FunctionExpr
+%type <body>  FunctionBody
+%type <srcs>  SourceElements
+%type <param> FormalParameterList
+%type <op>    AssignmentOperator
+%type <args>  Arguments
+%type <alist> ArgumentList
+%type <vlist> VariableDeclarationList VariableDeclarationListNoIn ConstDeclarationList
+%type <decl>  VariableDeclaration VariableDeclarationNoIn ConstDeclaration
+%type <cblk>  CaseBlock
+%type <ccl>   CaseClause DefaultClause
+%type <clist> CaseClauses  CaseClausesOpt
+%type <ival>  Elision ElisionOpt
+%type <elm>   ElementList
+%type <pname> PropertyName
+%type <pnode> Property
+%type <plist> PropertyList
+%%
+
+Literal:
+    NULLTOKEN                           { $$ = new NullNode(); }
+  | TRUETOKEN                           { $$ = new BooleanNode(true); }
+  | FALSETOKEN                          { $$ = new BooleanNode(false); }
+  | NUMBER                              { $$ = new NumberNode($1); }
+  | STRING                              { $$ = new StringNode($1); }
+  | '/' /* regexp */                    {
+                                            Lexer *l = Lexer::curr();
+                                            if (!l->scanRegExp()) YYABORT;
+                                            $$ = new RegExpNode(l->pattern, l->flags);
+                                        }
+  | DIVEQUAL /* regexp with /= */       {
+                                            Lexer *l = Lexer::curr();
+                                            if (!l->scanRegExp()) YYABORT;
+                                            $$ = new RegExpNode("=" + l->pattern, l->flags);
+                                        }
+;
+
+PropertyName:
+    IDENT                               { $$ = new PropertyNameNode(*$1); }
+  | STRING                              { $$ = new PropertyNameNode(Identifier(*$1)); }
+  | NUMBER                              { $$ = new PropertyNameNode($1); }
+;
+
+Property:
+    PropertyName ':' AssignmentExpr     { $$ = new PropertyNode($1, $3, PropertyNode::Constant); }
+  | IDENT IDENT '(' ')' FunctionBody    { if (!makeGetterOrSetterPropertyNode($$, *$1, *$2, 0, $5)) YYABORT; }
+  | IDENT IDENT '(' FormalParameterList ')' FunctionBody
+                                        { if (!makeGetterOrSetterPropertyNode($$, *$1, *$2, $4, $6)) 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 ResolveNode(*$1); }
+  | '(' Expr ')'                        { $$ = ($2->isResolveNode() || $2->isGroupNode()) ?
+                                            $2 : new GroupNode($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 '.' 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); }
+;
+
+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                       { $$ = new UnaryPlusNode($2); }
+  | '-' UnaryExpr                       { $$ = new NegateNode($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 MultNode($1, $3, '/'); }
+  | MultiplicativeExpr '%' UnaryExpr    { $$ = new MultNode($1, $3,'%'); }
+;
+
+MultiplicativeExprNoBF:
+    UnaryExprNoBF
+  | MultiplicativeExprNoBF '*' UnaryExpr
+                                        { $$ = new MultNode($1, $3, '*'); }
+  | MultiplicativeExprNoBF '/' UnaryExpr
+                                        { $$ = new MultNode($1, $3, '/'); }
+  | MultiplicativeExprNoBF '%' UnaryExpr
+                                        { $$ = new MultNode($1, $3,'%'); }
+;
+
+AdditiveExpr:
+    MultiplicativeExpr
+  | AdditiveExpr '+' MultiplicativeExpr { $$ = new AddNode($1, $3, '+'); }
+  | AdditiveExpr '-' MultiplicativeExpr { $$ = new AddNode($1, $3, '-'); }
+;
+
+AdditiveExprNoBF:
+    MultiplicativeExprNoBF
+  | AdditiveExprNoBF '+' MultiplicativeExpr
+                                        { $$ = new AddNode($1, $3, '+'); }
+  | AdditiveExprNoBF '-' MultiplicativeExpr
+                                        { $$ = new AddNode($1, $3, '-'); }
+;
+
+ShiftExpr:
+    AdditiveExpr
+  | ShiftExpr LSHIFT AdditiveExpr       { $$ = new ShiftNode($1, OpLShift, $3); }
+  | ShiftExpr RSHIFT AdditiveExpr       { $$ = new ShiftNode($1, OpRShift, $3); }
+  | ShiftExpr URSHIFT AdditiveExpr      { $$ = new ShiftNode($1, OpURShift, $3); }
+;
+
+ShiftExprNoBF:
+    AdditiveExprNoBF
+  | ShiftExprNoBF LSHIFT AdditiveExpr   { $$ = new ShiftNode($1, OpLShift, $3); }
+  | ShiftExprNoBF RSHIFT AdditiveExpr   { $$ = new ShiftNode($1, OpRShift, $3); }
+  | ShiftExprNoBF URSHIFT AdditiveExpr  { $$ = new ShiftNode($1, OpURShift, $3); }
+;
+
+RelationalExpr:
+    ShiftExpr
+  | RelationalExpr '<' ShiftExpr        { $$ = new RelationalNode($1, OpLess, $3); }
+  | RelationalExpr '>' ShiftExpr        { $$ = new RelationalNode($1, OpGreater, $3); }
+  | RelationalExpr LE ShiftExpr         { $$ = new RelationalNode($1, OpLessEq, $3); }
+  | RelationalExpr GE ShiftExpr         { $$ = new RelationalNode($1, OpGreaterEq, $3); }
+  | RelationalExpr INSTANCEOF ShiftExpr { $$ = new RelationalNode($1, OpInstanceOf, $3); }
+  | RelationalExpr INTOKEN ShiftExpr    { $$ = new RelationalNode($1, OpIn, $3); }
+;
+
+RelationalExprNoIn:
+    ShiftExpr
+  | RelationalExprNoIn '<' ShiftExpr    { $$ = new RelationalNode($1, OpLess, $3); }
+  | RelationalExprNoIn '>' ShiftExpr    { $$ = new RelationalNode($1, OpGreater, $3); }
+  | RelationalExprNoIn LE ShiftExpr     { $$ = new RelationalNode($1, OpLessEq, $3); }
+  | RelationalExprNoIn GE ShiftExpr     { $$ = new RelationalNode($1, OpGreaterEq, $3); }
+  | RelationalExprNoIn INSTANCEOF ShiftExpr
+                                        { $$ = new RelationalNode($1, OpInstanceOf, $3); }
+;
+
+RelationalExprNoBF:
+    ShiftExprNoBF
+  | RelationalExprNoBF '<' ShiftExpr    { $$ = new RelationalNode($1, OpLess, $3); }
+  | RelationalExprNoBF '>' ShiftExpr    { $$ = new RelationalNode($1, OpGreater, $3); }
+  | RelationalExprNoBF LE ShiftExpr     { $$ = new RelationalNode($1, OpLessEq, $3); }
+  | RelationalExprNoBF GE ShiftExpr     { $$ = new RelationalNode($1, OpGreaterEq, $3); }
+  | RelationalExprNoBF INSTANCEOF ShiftExpr
+                                        { $$ = new RelationalNode($1, OpInstanceOf, $3); }
+  | RelationalExprNoBF INTOKEN ShiftExpr     { $$ = new RelationalNode($1, OpIn, $3); }
+;
+
+EqualityExpr:
+    RelationalExpr
+  | EqualityExpr EQEQ RelationalExpr    { $$ = new EqualNode($1, OpEqEq, $3); }
+  | EqualityExpr NE RelationalExpr      { $$ = new EqualNode($1, OpNotEq, $3); }
+  | EqualityExpr STREQ RelationalExpr   { $$ = new EqualNode($1, OpStrEq, $3); }
+  | EqualityExpr STRNEQ RelationalExpr  { $$ = new EqualNode($1, OpStrNEq, $3);}
+;
+
+EqualityExprNoIn:
+    RelationalExprNoIn
+  | EqualityExprNoIn EQEQ RelationalExprNoIn
+                                        { $$ = new EqualNode($1, OpEqEq, $3); }
+  | EqualityExprNoIn NE RelationalExprNoIn
+                                        { $$ = new EqualNode($1, OpNotEq, $3); }
+  | EqualityExprNoIn STREQ RelationalExprNoIn
+                                        { $$ = new EqualNode($1, OpStrEq, $3); }
+  | EqualityExprNoIn STRNEQ RelationalExprNoIn
+                                        { $$ = new EqualNode($1, OpStrNEq, $3);}
+;
+
+EqualityExprNoBF:
+    RelationalExprNoBF
+  | EqualityExprNoBF EQEQ RelationalExpr
+                                        { $$ = new EqualNode($1, OpEqEq, $3); }
+  | EqualityExprNoBF NE RelationalExpr  { $$ = new EqualNode($1, OpNotEq, $3); }
+  | EqualityExprNoBF STREQ RelationalExpr
+                                        { $$ = new EqualNode($1, OpStrEq, $3); }
+  | EqualityExprNoBF STRNEQ RelationalExpr
+                                        { $$ = new EqualNode($1, OpStrNEq, $3);}
+;
+
+BitwiseANDExpr:
+    EqualityExpr
+  | BitwiseANDExpr '&' EqualityExpr     { $$ = new BitOperNode($1, OpBitAnd, $3); }
+;
+
+BitwiseANDExprNoIn:
+    EqualityExprNoIn
+  | BitwiseANDExprNoIn '&' EqualityExprNoIn
+                                        { $$ = new BitOperNode($1, OpBitAnd, $3); }
+;
+
+BitwiseANDExprNoBF:
+    EqualityExprNoBF
+  | BitwiseANDExprNoBF '&' EqualityExpr { $$ = new BitOperNode($1, OpBitAnd, $3); }
+;
+
+BitwiseXORExpr:
+    BitwiseANDExpr
+  | BitwiseXORExpr '^' BitwiseANDExpr   { $$ = new BitOperNode($1, OpBitXOr, $3); }
+;
+
+BitwiseXORExprNoIn:
+    BitwiseANDExprNoIn
+  | BitwiseXORExprNoIn '^' BitwiseANDExprNoIn
+                                        { $$ = new BitOperNode($1, OpBitXOr, $3); }
+;
+
+BitwiseXORExprNoBF:
+    BitwiseANDExprNoBF
+  | BitwiseXORExprNoBF '^' BitwiseANDExpr
+                                        { $$ = new BitOperNode($1, OpBitXOr, $3); }
+;
+
+BitwiseORExpr:
+    BitwiseXORExpr
+  | BitwiseORExpr '|' BitwiseXORExpr    { $$ = new BitOperNode($1, OpBitOr, $3); }
+;
+
+BitwiseORExprNoIn:
+    BitwiseXORExprNoIn
+  | BitwiseORExprNoIn '|' BitwiseXORExprNoIn
+                                        { $$ = new BitOperNode($1, OpBitOr, $3); }
+;
+
+BitwiseORExprNoBF:
+    BitwiseXORExprNoBF
+  | BitwiseORExprNoBF '|' BitwiseXORExpr
+                                        { $$ = new BitOperNode($1, OpBitOr, $3); }
+;
+
+LogicalANDExpr:
+    BitwiseORExpr
+  | LogicalANDExpr AND BitwiseORExpr    { $$ = new BinaryLogicalNode($1, OpAnd, $3); }
+;
+
+LogicalANDExprNoIn:
+    BitwiseORExprNoIn
+  | LogicalANDExprNoIn AND BitwiseORExprNoIn
+                                        { $$ = new BinaryLogicalNode($1, OpAnd, $3); }
+;
+
+LogicalANDExprNoBF:
+    BitwiseORExprNoBF
+  | LogicalANDExprNoBF AND BitwiseORExpr
+                                        { $$ = new BinaryLogicalNode($1, OpAnd, $3); }
+;
+
+LogicalORExpr:
+    LogicalANDExpr
+  | LogicalORExpr OR LogicalANDExpr     { $$ = new BinaryLogicalNode($1, OpOr, $3); }
+;
+
+LogicalORExprNoIn:
+    LogicalANDExprNoIn
+  | LogicalORExprNoIn OR LogicalANDExprNoIn
+                                        { $$ = new BinaryLogicalNode($1, OpOr, $3); }
+;
+
+LogicalORExprNoBF:
+    LogicalANDExprNoBF
+  | LogicalORExprNoBF OR LogicalANDExpr { $$ = new BinaryLogicalNode($1, OpOr, $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:
+    '{' '}'                             { $$ = 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
+                                        { $$ = new IfNode($3, $5, 0); DBG($$, @1, @4); }
+  | IF '(' Expr ')' Statement ELSE Statement
+                                        { $$ = new IfNode($3, $5, $7); DBG($$, @1, @4); }
+;
+
+IterationStatement:
+    DO Statement WHILE '(' Expr ')' ';'    { $$ = new DoWhileNode($2, $5); DBG($$, @1, @3);}
+  | DO Statement WHILE '(' Expr ')'     { $$ = new DoWhileNode($2, $5); DBG($$, @1, @3);}
+  | 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                 { $3->pushLabel(*$1); $$ = new LabelNode(*$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; }
+;
+
+FunctionDeclaration:
+    FUNCTION IDENT '(' ')' FunctionBody { $$ = new FuncDeclNode(*$2, $5); }
+  | FUNCTION IDENT '(' FormalParameterList ')' FunctionBody
+                                        { $$ = new FuncDeclNode(*$2, $4, $6); }
+;
+
+FunctionExpr:
+    FUNCTION '(' ')' FunctionBody       { $$ = new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, $4); }
+  | FUNCTION '(' FormalParameterList ')' FunctionBody
+                                        { $$ = new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, $5, $3); }
+  | FUNCTION IDENT '(' ')' FunctionBody { $$ = new FuncExprNode(*$2, $5); }
+  | FUNCTION IDENT '(' FormalParameterList ')' FunctionBody
+                                        { $$ = new FuncExprNode(*$2, $6, $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::accept(new ProgramNode(0)); }
+    | SourceElements                    { Parser::accept(new ProgramNode($1)); }
+;
+
+SourceElements:
+    SourceElement                       { $$ = new SourceElementsNode($1); }
+  | SourceElements SourceElement        { $$ = new SourceElementsNode($1, $2); }
+;
+
+SourceElement:
+    FunctionDeclaration                 { $$ = $1; }
+  | Statement                           { $$ = $1; }
+;
+ 
+%%
+
+static Node* makeAssignNode(Node* loc, Operator op, Node* expr)
+{ 
+    Node *n = loc->nodeInsideAllParens();
+
+    if (!n->isLocation())
+        return new AssignErrorNode(loc, op, expr);
+
+    if (n->isResolveNode()) {
+        ResolveNode *resolve = static_cast<ResolveNode *>(n);
+        return new AssignResolveNode(resolve->identifier(), op, expr);
+    }
+    if (n->isBracketAccessorNode()) {
+        BracketAccessorNode *bracket = static_cast<BracketAccessorNode *>(n);
+        return new AssignBracketNode(bracket->base(), bracket->subscript(), op, expr);
+    }
+    assert(n->isDotAccessorNode());
+    DotAccessorNode *dot = static_cast<DotAccessorNode *>(n);
+    return new AssignDotNode(dot->base(), dot->identifier(), op, expr);
+}
+
+static Node* makePrefixNode(Node *expr, Operator op)
+{ 
+    Node *n = expr->nodeInsideAllParens();
+
+    if (!n->isLocation())
+        return new PrefixErrorNode(expr, op);
+    
+    if (n->isResolveNode()) {
+        ResolveNode *resolve = static_cast<ResolveNode *>(n);
+        return new PrefixResolveNode(resolve->identifier(), op);
+    }
+    if (n->isBracketAccessorNode()) {
+        BracketAccessorNode *bracket = static_cast<BracketAccessorNode *>(n);
+        return new PrefixBracketNode(bracket->base(), bracket->subscript(), op);
+    }
+    assert(n->isDotAccessorNode());
+    DotAccessorNode *dot = static_cast<DotAccessorNode *>(n);
+    return new PrefixDotNode(dot->base(), dot->identifier(), op);
+}
+
+static Node* makePostfixNode(Node* expr, Operator op)
+{ 
+    Node *n = expr->nodeInsideAllParens();
+
+    if (!n->isLocation())
+        return new PostfixErrorNode(expr, op);
+    
+    if (n->isResolveNode()) {
+        ResolveNode *resolve = static_cast<ResolveNode *>(n);
+        return new PostfixResolveNode(resolve->identifier(), op);
+    }
+    if (n->isBracketAccessorNode()) {
+        BracketAccessorNode *bracket = static_cast<BracketAccessorNode *>(n);
+        return new PostfixBracketNode(bracket->base(), bracket->subscript(), op);
+    }
+    assert(n->isDotAccessorNode());
+    DotAccessorNode *dot = static_cast<DotAccessorNode *>(n);
+    return new PostfixDotNode(dot->base(), dot->identifier(), op);
+}
+
+static Node *makeFunctionCallNode(Node *func, ArgumentsNode *args)
+{
+    Node *n = func->nodeInsideAllParens();
+    
+    if (!n->isLocation())
+        return new FunctionCallValueNode(func, args);
+    else if (n->isResolveNode()) {
+        ResolveNode *resolve = static_cast<ResolveNode *>(n);
+        return new FunctionCallResolveNode(resolve->identifier(), args);
+    } else if (n->isBracketAccessorNode()) {
+        BracketAccessorNode *bracket = static_cast<BracketAccessorNode *>(n);
+        if (n != func)
+            return new FunctionCallParenBracketNode(bracket->base(), bracket->subscript(), args);
+        else
+            return new FunctionCallBracketNode(bracket->base(), bracket->subscript(), args);
+    } else {
+        assert(n->isDotAccessorNode());
+        DotAccessorNode *dot = static_cast<DotAccessorNode *>(n);
+        if (n != func)
+            return new FunctionCallParenDotNode(dot->base(), dot->identifier(), args);
+        else
+            return new FunctionCallDotNode(dot->base(), dot->identifier(), args);
+    }
+}
+
+static Node *makeTypeOfNode(Node *expr)
+{
+    Node *n = expr->nodeInsideAllParens();
+
+    if (n->isResolveNode()) {
+        ResolveNode *resolve = static_cast<ResolveNode *>(n);
+        return new TypeOfResolveNode(resolve->identifier());
+    } else
+        return new TypeOfValueNode(expr);
+}
+
+static Node *makeDeleteNode(Node *expr)
+{
+    Node *n = expr->nodeInsideAllParens();
+    
+    if (!n->isLocation())
+        return new DeleteValueNode(expr);
+    else if (n->isResolveNode()) {
+        ResolveNode *resolve = static_cast<ResolveNode *>(n);
+        return new DeleteResolveNode(resolve->identifier());
+    } else if (n->isBracketAccessorNode()) {
+        BracketAccessorNode *bracket = static_cast<BracketAccessorNode *>(n);
+        return new DeleteBracketNode(bracket->base(), bracket->subscript());
+    } else {
+        assert(n->isDotAccessorNode());
+        DotAccessorNode *dot = static_cast<DotAccessorNode *>(n);
+        return new DeleteDotNode(dot->base(), dot->identifier());
+    }
+}
+
+static bool makeGetterOrSetterPropertyNode(PropertyNode*& result, Identifier& getOrSet, Identifier& name, ParameterNode *params, FunctionBodyNode *body)
+{
+    PropertyNode::Type type;
+    
+    if (getOrSet == "get")
+        type = PropertyNode::Getter;
+    else if (getOrSet == "set")
+        type = PropertyNode::Setter;
+    else
+        return false;
+    
+    result = new PropertyNode(new PropertyNameNode(name), 
+                              new FuncExprNode(CommonIdentifiers::shared()->nullIdentifier, body, params), type);
+
+    return true;
+}
+
+/* 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::curr()->prevTerminator();
+}