mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-24 02:42:48 +00:00
942 lines
No EOL
35 KiB
Text
942 lines
No EOL
35 KiB
Text
%{
|
|
|
|
/*
|
|
* 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-kjs.h>
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#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 <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 ImportStatement
|
|
%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
|
|
%type <pkgn> PackageName
|
|
%type <ident> Keywords
|
|
%type <ident> 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; |