4 * This file is part of the KDE libraries
5 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include "interpreter.h"
36 // Not sure why, but yacc doesn't add this define along with the others.
37 #define yylloc kjsyylloc
39 /* default values for bison */
43 #define YYERROR_VERBOSE
45 #define DBG(l, s, e) { l->setLoc(s.first_line, e.last_line, Parser::sid); } // location
47 extern int kjsyylex();
48 int kjsyyerror(const char *);
49 static bool automatic();
63 FunctionBodyNode *body;
67 SourceElementsNode *srcs;
70 ArgumentListNode *alist;
72 VarDeclListNode *vlist;
74 ClauseListNode *clist;
78 PropertyValueNode *plist;
86 /* expect a shift/reduce conflict from the "dangling else" problem
87 when using bison the warning can be supressed */
91 %token NULLTOKEN TRUETOKEN FALSETOKEN
95 %token BREAK CASE DEFAULT FOR NEW VAR CONTINUE
96 %token FUNCTION RETURN VOID DELETE
97 %token IF THIS DO WHILE ELSE IN INSTANCEOF TYPEOF
98 %token SWITCH WITH RESERVED
99 %token THROW TRY CATCH FINALLY
102 %token EQEQ NE /* == and != */
103 %token STREQ STRNEQ /* === and !== */
104 %token LE GE /* < and > */
105 %token OR AND /* || and && */
106 %token PLUSPLUS MINUSMINUS /* ++ and -- */
107 %token LSHIFT /* << */
108 %token RSHIFT URSHIFT /* >> and >>> */
109 %token PLUSEQUAL MINUSEQUAL /* += and -= */
110 %token MULTEQUAL DIVEQUAL /* *= and /= */
111 %token LSHIFTEQUAL /* <<= */
112 %token RSHIFTEQUAL URSHIFTEQUAL /* >>= and >>>= */
113 %token ANDEQUAL MODEQUAL /* &= and %= */
114 %token XOREQUAL OREQUAL /* ^= and |= */
121 /* automatically inserted semicolon */
122 %token AUTOPLUSPLUS AUTOMINUSMINUS
124 /* non-terminal types */
125 %type <node> Literal PrimaryExpr Expr MemberExpr FunctionExpr NewExpr CallExpr
126 %type <node> ArrayLiteral
127 %type <node> LeftHandSideExpr PostfixExpr UnaryExpr
128 %type <node> MultiplicativeExpr AdditiveExpr
129 %type <node> ShiftExpr RelationalExpr EqualityExpr
130 %type <node> BitwiseANDExpr BitwiseXORExpr BitwiseORExpr
131 %type <node> LogicalANDExpr LogicalORExpr
132 %type <node> ConditionalExpr AssignmentExpr
136 %type <fnode> Finally
138 %type <stat> Statement Block
139 %type <stat> VariableStatement EmptyStatement ExprStatement
140 %type <stat> IfStatement IterationStatement ContinueStatement
141 %type <stat> BreakStatement ReturnStatement WithStatement
142 %type <stat> SwitchStatement LabelledStatement
143 %type <stat> ThrowStatement TryStatement
144 %type <stat> SourceElement
146 %type <slist> StatementList
147 %type <init> Initializer
148 %type <func> FunctionDeclaration
149 %type <body> FunctionBody
150 %type <srcs> SourceElements
151 %type <param> FormalParameterList
152 %type <op> AssignmentOperator
154 %type <args> Arguments
155 %type <alist> ArgumentList
156 %type <vlist> VariableDeclarationList
157 %type <decl> VariableDeclaration
158 %type <cblk> CaseBlock
159 %type <ccl> CaseClause DefaultClause
160 %type <clist> CaseClauses CaseClausesOpt
161 %type <ival> Elision ElisionOpt
162 %type <elm> ElementList
163 %type <plist> PropertyNameAndValueList
164 %type <pnode> PropertyName
169 NULLTOKEN { $$ = new NullNode(); }
170 | TRUETOKEN { $$ = new BooleanNode(true); }
171 | FALSETOKEN { $$ = new BooleanNode(false); }
172 | NUMBER { $$ = new NumberNode($1); }
173 | STRING { $$ = new StringNode($1); }
174 | '/' /* a RegExp ? */ { Lexer *l = Lexer::curr();
175 if (!l->scanRegExp()) YYABORT;
176 $$ = new RegExpNode(l->pattern,l->flags);}
177 | DIVEQUAL /* a RegExp starting with /= ! */
178 { Lexer *l = Lexer::curr();
179 if (!l->scanRegExp()) YYABORT;
180 $$ = new RegExpNode(UString('=')+l->pattern,l->flags);}
184 THIS { $$ = new ThisNode(); }
185 | IDENT { $$ = new ResolveNode(*$1); }
188 | '(' Expr ')' { $$ = new GroupNode($2); }
189 | '{' '}' { $$ = new ObjectLiteralNode(); }
190 | '{' PropertyNameAndValueList '}' { $$ = new ObjectLiteralNode($2); }
194 '[' ElisionOpt ']' { $$ = new ArrayNode($2); }
195 | '[' ElementList ']' { $$ = new ArrayNode($2); }
196 | '[' ElementList ',' ElisionOpt ']' { $$ = new ArrayNode($4, $2); }
200 ElisionOpt AssignmentExpr { $$ = new ElementNode($1, $2); }
201 | ElementList ',' ElisionOpt AssignmentExpr
202 { $$ = new ElementNode($1, $3, $4); }
206 /* nothing */ { $$ = 0; }
212 | Elision ',' { $$ = $1 + 1; }
215 PropertyNameAndValueList:
216 PropertyName ':' AssignmentExpr { $$ = new PropertyValueNode($1, $3); }
217 | PropertyNameAndValueList ',' PropertyName ':' AssignmentExpr
218 { $$ = new PropertyValueNode($3, $5, $1); }
222 IDENT { $$ = new PropertyNode(*$1); }
223 | STRING { $$ = new PropertyNode(Identifier(*$1)); }
224 | NUMBER { $$ = new PropertyNode($1); }
230 | MemberExpr '[' Expr ']' { $$ = new AccessorNode1($1, $3); }
231 | MemberExpr '.' IDENT { $$ = new AccessorNode2($1, *$3); }
232 | NEW MemberExpr Arguments { $$ = new NewExprNode($2, $3); }
237 | NEW NewExpr { $$ = new NewExprNode($2); }
241 MemberExpr Arguments { $$ = new FunctionCallNode($1, $2); }
242 | CallExpr Arguments { $$ = new FunctionCallNode($1, $2); }
243 | CallExpr '[' Expr ']' { $$ = new AccessorNode1($1, $3); }
244 | CallExpr '.' IDENT { $$ = new AccessorNode2($1, *$3); }
248 '(' ')' { $$ = new ArgumentsNode(); }
249 | '(' ArgumentList ')' { $$ = new ArgumentsNode($2); }
253 AssignmentExpr { $$ = new ArgumentListNode($1); }
254 | ArgumentList ',' AssignmentExpr { $$ = new ArgumentListNode($1, $3); }
262 PostfixExpr: /* TODO: no line terminator here */
264 | LeftHandSideExpr PLUSPLUS { $$ = new PostfixNode($1, OpPlusPlus); }
265 | LeftHandSideExpr MINUSMINUS { $$ = new PostfixNode($1, OpMinusMinus); }
270 | DELETE UnaryExpr { $$ = new DeleteNode($2); }
271 | VOID UnaryExpr { $$ = new VoidNode($2); }
272 | TYPEOF UnaryExpr { $$ = new TypeOfNode($2); }
273 | PLUSPLUS UnaryExpr { $$ = new PrefixNode(OpPlusPlus, $2); }
274 | AUTOPLUSPLUS UnaryExpr { $$ = new PrefixNode(OpPlusPlus, $2); }
275 | MINUSMINUS UnaryExpr { $$ = new PrefixNode(OpMinusMinus, $2); }
276 | AUTOMINUSMINUS UnaryExpr { $$ = new PrefixNode(OpMinusMinus, $2); }
277 | '+' UnaryExpr { $$ = new UnaryPlusNode($2); }
278 | '-' UnaryExpr { $$ = new NegateNode($2); }
279 | '~' UnaryExpr { $$ = new BitwiseNotNode($2); }
280 | '!' UnaryExpr { $$ = new LogicalNotNode($2); }
285 | MultiplicativeExpr '*' UnaryExpr { $$ = new MultNode($1, $3, '*'); }
286 | MultiplicativeExpr '/' UnaryExpr { $$ = new MultNode($1, $3, '/'); }
287 | MultiplicativeExpr '%' UnaryExpr { $$ = new MultNode($1,$3,'%'); }
292 | AdditiveExpr '+' MultiplicativeExpr { $$ = new AddNode($1, $3, '+'); }
293 | AdditiveExpr '-' MultiplicativeExpr { $$ = new AddNode($1, $3, '-'); }
298 | ShiftExpr LSHIFT AdditiveExpr { $$ = new ShiftNode($1, OpLShift, $3); }
299 | ShiftExpr RSHIFT AdditiveExpr { $$ = new ShiftNode($1, OpRShift, $3); }
300 | ShiftExpr URSHIFT AdditiveExpr { $$ = new ShiftNode($1, OpURShift, $3); }
305 | RelationalExpr '<' ShiftExpr
306 { $$ = new RelationalNode($1, OpLess, $3); }
307 | RelationalExpr '>' ShiftExpr
308 { $$ = new RelationalNode($1, OpGreater, $3); }
309 | RelationalExpr LE ShiftExpr
310 { $$ = new RelationalNode($1, OpLessEq, $3); }
311 | RelationalExpr GE ShiftExpr
312 { $$ = new RelationalNode($1, OpGreaterEq, $3); }
313 | RelationalExpr INSTANCEOF ShiftExpr
314 { $$ = new RelationalNode($1, OpInstanceOf, $3); }
315 | RelationalExpr IN ShiftExpr
316 { $$ = new RelationalNode($1, OpIn, $3); }
321 | EqualityExpr EQEQ RelationalExpr { $$ = new EqualNode($1, OpEqEq, $3); }
322 | EqualityExpr NE RelationalExpr { $$ = new EqualNode($1, OpNotEq, $3); }
323 | EqualityExpr STREQ RelationalExpr { $$ = new EqualNode($1, OpStrEq, $3); }
324 | EqualityExpr STRNEQ RelationalExpr { $$ = new EqualNode($1, OpStrNEq, $3);}
329 | BitwiseANDExpr '&' EqualityExpr { $$ = new BitOperNode($1, OpBitAnd, $3); }
334 | BitwiseXORExpr '^' BitwiseANDExpr { $$ = new BitOperNode($1, OpBitXOr, $3); }
339 | BitwiseORExpr '|' BitwiseXORExpr { $$ = new BitOperNode($1, OpBitOr, $3); }
344 | LogicalANDExpr AND BitwiseORExpr
345 { $$ = new BinaryLogicalNode($1, OpAnd, $3); }
350 | LogicalORExpr OR LogicalANDExpr
351 { $$ = new BinaryLogicalNode($1, OpOr, $3); }
356 | LogicalORExpr '?' AssignmentExpr ':' AssignmentExpr
357 { $$ = new ConditionalNode($1, $3, $5); }
362 | LeftHandSideExpr AssignmentOperator AssignmentExpr
363 { $$ = new AssignNode($1, $2, $3);}
367 '=' { $$ = OpEqual; }
368 | PLUSEQUAL { $$ = OpPlusEq; }
369 | MINUSEQUAL { $$ = OpMinusEq; }
370 | MULTEQUAL { $$ = OpMultEq; }
371 | DIVEQUAL { $$ = OpDivEq; }
372 | LSHIFTEQUAL { $$ = OpLShift; }
373 | RSHIFTEQUAL { $$ = OpRShift; }
374 | URSHIFTEQUAL { $$ = OpURShift; }
375 | ANDEQUAL { $$ = OpAndEq; }
376 | XOREQUAL { $$ = OpXOrEq; }
377 | OREQUAL { $$ = OpOrEq; }
378 | MODEQUAL { $$ = OpModEq; }
383 | Expr ',' AssignmentExpr { $$ = new CommaNode($1, $3); }
404 '{' '}' { $$ = new BlockNode(0); DBG($$, @2, @2); }
405 | '{' SourceElements '}' { $$ = new BlockNode($2); DBG($$, @3, @3); }
409 Statement { $$ = new StatListNode($1); }
410 | StatementList Statement { $$ = new StatListNode($1, $2); }
414 VAR VariableDeclarationList ';' { $$ = new VarStatementNode($2);
416 | VAR VariableDeclarationList error { if (automatic()) {
417 $$ = new VarStatementNode($2);
425 VariableDeclarationList:
426 VariableDeclaration { $$ = new VarDeclListNode($1); }
427 | VariableDeclarationList ',' VariableDeclaration
428 { $$ = new VarDeclListNode($1, $3); }
432 IDENT { $$ = new VarDeclNode(*$1, 0); }
433 | IDENT Initializer { $$ = new VarDeclNode(*$1, $2); }
437 '=' AssignmentExpr { $$ = new AssignExprNode($2); }
441 ';' { $$ = new EmptyStatementNode(); }
445 Expr ';' { $$ = new ExprStatementNode($1);
447 | Expr error { if (automatic()) {
448 $$ = new ExprStatementNode($1);
454 IfStatement: /* shift/reduce conflict due to dangling else */
455 IF '(' Expr ')' Statement { $$ = new IfNode($3,$5,0);DBG($$,@1,@4); }
456 | IF '(' Expr ')' Statement ELSE Statement
457 { $$ = new IfNode($3,$5,$7);DBG($$,@1,@4); }
461 DO Statement WHILE '(' Expr ')' { $$=new DoWhileNode($2,$5);DBG($$,@1,@3);}
462 | WHILE '(' Expr ')' Statement { $$ = new WhileNode($3,$5);DBG($$,@1,@4); }
463 | FOR '(' ExprOpt ';' ExprOpt ';' ExprOpt ')'
464 Statement { $$ = new ForNode($3,$5,$7,$9);
466 | FOR '(' VAR VariableDeclarationList ';' ExprOpt ';' ExprOpt ')'
467 Statement { $$ = new ForNode($4,$6,$8,$10);
469 | FOR '(' LeftHandSideExpr IN Expr ')'
470 Statement { $$ = new ForInNode($3, $5, $7);
472 | FOR '(' VAR IDENT IN Expr ')'
473 Statement { $$ = new ForInNode(*$4,0,$6,$8);
475 | FOR '(' VAR IDENT Initializer IN Expr ')'
476 Statement { $$ = new ForInNode(*$4,$5,$7,$9);
481 /* nothing */ { $$ = 0; }
486 CONTINUE ';' { $$ = new ContinueNode(); DBG($$,@1,@2); }
487 | CONTINUE error { if (automatic()) {
488 $$ = new ContinueNode(); DBG($$,@1,@2);
491 | CONTINUE IDENT ';' { $$ = new ContinueNode(*$2); DBG($$,@1,@3); }
492 | CONTINUE IDENT error { if (automatic()) {
493 $$ = new ContinueNode(*$2);DBG($$,@1,@2);
499 BREAK ';' { $$ = new BreakNode();DBG($$,@1,@2); }
500 | BREAK error { if (automatic()) {
501 $$ = new BreakNode(); DBG($$,@1,@1);
504 | BREAK IDENT ';' { $$ = new BreakNode(*$2); DBG($$,@1,@3); }
505 | BREAK IDENT error { if (automatic()) {
506 $$ = new BreakNode(*$2); DBG($$,@1,@2);
513 RETURN ';' { $$ = new ReturnNode(0); DBG($$,@1,@2); }
514 | RETURN error { if (automatic()) {
515 $$ = new ReturnNode(0); DBG($$,@1,@1);
518 | RETURN Expr ';' { $$ = new ReturnNode($2); }
519 | RETURN Expr error { if (automatic())
520 $$ = new ReturnNode($2);
526 WITH '(' Expr ')' Statement { $$ = new WithNode($3,$5);
531 SWITCH '(' Expr ')' CaseBlock { $$ = new SwitchNode($3, $5);
536 '{' CaseClausesOpt '}' { $$ = new CaseBlockNode($2, 0, 0); }
537 | '{' CaseClausesOpt DefaultClause CaseClausesOpt '}'
538 { $$ = new CaseBlockNode($2, $3, $4); }
542 /* nothing */ { $$ = 0; }
547 CaseClause { $$ = new ClauseListNode($1); }
548 | CaseClauses CaseClause { $$ = new ClauseListNode($1, $2); }
552 CASE Expr ':' { $$ = new CaseClauseNode($2); }
553 | CASE Expr ':' StatementList { $$ = new CaseClauseNode($2, $4); }
557 DEFAULT ':' { $$ = new CaseClauseNode(0); }
558 | DEFAULT ':' StatementList { $$ = new CaseClauseNode(0, $3); }
562 IDENT ':' Statement { $3->pushLabel(*$1);
563 $$ = new LabelNode(*$1, $3); }
567 THROW Expr ';' { $$ = new ThrowNode($2); }
568 | THROW Expr error { if (automatic()) $$ = new ThrowNode($2); else YYABORT; }
572 TRY Block Catch { $$ = new TryNode($2, $3); }
573 | TRY Block Finally { $$ = new TryNode($2, $3); }
574 | TRY Block Catch Finally { $$ = new TryNode($2, $3, $4); }
578 CATCH '(' IDENT ')' Block { $$ = new CatchNode(*$3, $5); }
582 FINALLY Block { $$ = new FinallyNode($2); }
586 FUNCTION IDENT '(' ')' FunctionBody { $$ = new FuncDeclNode(*$2, $5); }
587 | FUNCTION IDENT '(' FormalParameterList ')' FunctionBody
588 { $$ = new FuncDeclNode(*$2, $4, $6); }
591 FUNCTION '(' ')' FunctionBody { $$ = new FuncExprNode($4); }
592 | FUNCTION '(' FormalParameterList ')' FunctionBody
593 { $$ = new FuncExprNode($3, $5); }
598 IDENT { $$ = new ParameterNode(*$1); }
599 | FormalParameterList ',' IDENT { $$ = new ParameterNode($1, *$3); }
603 '{' '}' /* TODO: spec ??? */ { $$ = new FunctionBodyNode(0);
605 | '{' SourceElements '}' { $$ = new FunctionBodyNode($2);
610 /* nothing, empty script */ { $$ = new ProgramNode(0);
611 Parser::progNode = $$; }
612 | SourceElements { $$ = new ProgramNode($1);
613 Parser::progNode = $$; }
617 SourceElement { $$ = new SourceElementsNode($1); }
618 | SourceElements SourceElement { $$ = new SourceElementsNode($1, $2); }
622 Statement { $$ = $1; }
623 | FunctionDeclaration { $$ = $1; }
628 int yyerror (const char * /* s */) /* Called by yyparse on error */
630 // fprintf(stderr, "ERROR: %s at line %d\n",
631 // s, KJS::Lexer::curr()->lineNo());
635 /* may we automatically insert a semicolon ? */
638 if (yychar == '}' || yychar == 0)
640 else if (Lexer::curr()->prevTerminator())