JavaScriptCore:
[WebKit-https.git] / JavaScriptCore / kjs / grammar.y
1 %{
2
3 /*
4  *  This file is part of the KDE libraries
5  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
6  *
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.
11  *
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.
16  *
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
20  *
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 #include <string.h>
27 #include <stdlib.h>
28 #include "value.h"
29 #include "object.h"
30 #include "types.h"
31 #include "interpreter.h"
32 #include "nodes.h"
33 #include "lexer.h"
34 #include "internal.h"
35
36 // Not sure why, but yacc doesn't add this define along with the others.
37 #define yylloc kjsyylloc
38
39 /* default values for bison */
40 #define YYDEBUG 0
41 #define YYMAXDEPTH 0
42 #if !APPLE_CHANGES
43 #define YYERROR_VERBOSE
44 #endif
45 #define DBG(l, s, e) { l->setLoc(s.first_line, e.last_line, Parser::sid); } // location
46
47 extern int kjsyylex();
48 int kjsyyerror(const char *);
49 static bool automatic();
50
51 using namespace KJS;
52
53 %}
54
55 %union {
56   int                 ival;
57   double              dval;
58   UString             *ustr;
59   Identifier          *ident;
60   Node                *node;
61   StatementNode       *stat;
62   ParameterNode       *param;
63   FunctionBodyNode    *body;
64   FuncDeclNode        *func;
65   ProgramNode         *prog;
66   AssignExprNode      *init;
67   SourceElementsNode  *srcs;
68   StatListNode        *slist;
69   ArgumentsNode       *args;
70   ArgumentListNode    *alist;
71   VarDeclNode         *decl;
72   VarDeclListNode     *vlist;
73   CaseBlockNode       *cblk;
74   ClauseListNode      *clist;
75   CaseClauseNode      *ccl;
76   ElementNode         *elm;
77   Operator            op;
78   PropertyValueNode   *plist;
79   PropertyNode        *pnode;
80   CatchNode           *cnode;
81   FinallyNode         *fnode;
82 }
83
84 %start Program
85
86 /* expect a shift/reduce conflict from the "dangling else" problem
87    when using bison the warning can be supressed */
88 // %expect 1
89
90 /* literals */
91 %token NULLTOKEN TRUETOKEN FALSETOKEN
92 %token STRING NUMBER
93
94 /* keywords */
95 %token BREAK CASE DEFAULT FOR NEW VAR CONST 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
100
101 /* punctuators */
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 |= */
115
116 /* terminal types */
117 %token <dval> NUMBER
118 %token <ustr> STRING
119 %token <ident> IDENT
120
121 /* automatically inserted semicolon */
122 %token AUTOPLUSPLUS AUTOMINUSMINUS
123
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
133 %type <node>  ExprOpt
134
135 %type <cnode> Catch
136 %type <fnode> Finally
137
138 %type <stat>  Statement Block
139 %type <stat>  VariableStatement ConstStatement 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
145
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
153 %type <prog>  Program
154 %type <args>  Arguments
155 %type <alist> ArgumentList
156 %type <vlist> VariableDeclarationList ConstDeclarationList
157 %type <decl>  VariableDeclaration ConstDeclaration
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
165
166 %%
167
168 Literal:
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);}
181 ;
182
183 PrimaryExpr:
184     THIS                           { $$ = new ThisNode(); }
185   | IDENT                          { $$ = new ResolveNode(*$1); }
186   | Literal
187   | ArrayLiteral
188   | '(' Expr ')'                   { $$ = new GroupNode($2); }
189   | '{' '}'                        { $$ = new ObjectLiteralNode(); }
190   | '{' PropertyNameAndValueList '}'   { $$ = new ObjectLiteralNode($2); }
191 ;
192
193 ArrayLiteral:
194     '[' ElisionOpt ']'                 { $$ = new ArrayNode($2); }
195   | '[' ElementList ']'                { $$ = new ArrayNode($2); }
196   | '[' ElementList ',' ElisionOpt ']' { $$ = new ArrayNode($4, $2); }
197 ;
198
199 ElementList:
200     ElisionOpt AssignmentExpr      { $$ = new ElementNode($1, $2); }
201   | ElementList ',' ElisionOpt AssignmentExpr
202                                    { $$ = new ElementNode($1, $3, $4); }
203 ;
204
205 ElisionOpt:
206     /* nothing */                  { $$ = 0; }
207   | Elision
208 ;
209
210 Elision:
211     ','                            { $$ = 1; }
212   | Elision ','                    { $$ = $1 + 1; }
213 ;
214
215 PropertyNameAndValueList:
216     PropertyName ':' AssignmentExpr     { $$ = new PropertyValueNode($1, $3); }
217   | PropertyNameAndValueList ',' PropertyName ':' AssignmentExpr
218                                    { $$ = new PropertyValueNode($3, $5, $1); }
219 ;
220
221 PropertyName:
222     IDENT                          { $$ = new PropertyNode(*$1); }
223   | STRING                         { $$ = new PropertyNode(Identifier(*$1)); }
224   | NUMBER                         { $$ = new PropertyNode($1); }
225 ;
226
227 MemberExpr:
228     PrimaryExpr
229   | FunctionExpr
230   | MemberExpr '[' Expr ']'        { $$ = new AccessorNode1($1, $3); }
231   | MemberExpr '.' IDENT           { $$ = new AccessorNode2($1, *$3); }
232   | NEW MemberExpr Arguments       { $$ = new NewExprNode($2, $3); }
233 ;
234
235 NewExpr:
236     MemberExpr
237   | NEW NewExpr                    { $$ = new NewExprNode($2); }
238 ;
239
240 CallExpr:
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); }
245 ;
246
247 Arguments:
248     '(' ')'                        { $$ = new ArgumentsNode(); }
249   | '(' ArgumentList ')'           { $$ = new ArgumentsNode($2); }
250 ;
251
252 ArgumentList:
253     AssignmentExpr                  { $$ = new ArgumentListNode($1); }
254   | ArgumentList ',' AssignmentExpr { $$ = new ArgumentListNode($1, $3); }
255 ;
256
257 LeftHandSideExpr:
258     NewExpr
259   | CallExpr
260 ;
261
262 PostfixExpr:    /* TODO: no line terminator here */
263     LeftHandSideExpr
264   | LeftHandSideExpr PLUSPLUS      { $$ = new PostfixNode($1, OpPlusPlus); }
265   | LeftHandSideExpr MINUSMINUS    { $$ = new PostfixNode($1, OpMinusMinus); }
266 ;
267
268 UnaryExpr:
269     PostfixExpr
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); }
281 ;
282
283 MultiplicativeExpr:
284     UnaryExpr
285   | MultiplicativeExpr '*' UnaryExpr { $$ = new MultNode($1, $3, '*'); }
286   | MultiplicativeExpr '/' UnaryExpr { $$ = new MultNode($1, $3, '/'); }
287   | MultiplicativeExpr '%' UnaryExpr { $$ = new MultNode($1,$3,'%'); }
288 ;
289
290 AdditiveExpr:
291     MultiplicativeExpr
292   | AdditiveExpr '+' MultiplicativeExpr { $$ = new AddNode($1, $3, '+'); }
293   | AdditiveExpr '-' MultiplicativeExpr { $$ = new AddNode($1, $3, '-'); }
294 ;
295
296 ShiftExpr:
297     AdditiveExpr
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); }
301 ;
302
303 RelationalExpr:
304     ShiftExpr
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); }
317 ;
318
319 EqualityExpr:
320     RelationalExpr
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);}
325 ;
326
327 BitwiseANDExpr:
328     EqualityExpr
329   | BitwiseANDExpr '&' EqualityExpr { $$ = new BitOperNode($1, OpBitAnd, $3); }
330 ;
331
332 BitwiseXORExpr:
333     BitwiseANDExpr
334   | BitwiseXORExpr '^' BitwiseANDExpr { $$ = new BitOperNode($1, OpBitXOr, $3); }
335 ;
336
337 BitwiseORExpr:
338     BitwiseXORExpr
339   | BitwiseORExpr '|' BitwiseXORExpr { $$ = new BitOperNode($1, OpBitOr, $3); }
340 ;
341
342 LogicalANDExpr:
343     BitwiseORExpr
344   | LogicalANDExpr AND BitwiseORExpr
345                            { $$ = new BinaryLogicalNode($1, OpAnd, $3); }
346 ;
347
348 LogicalORExpr:
349     LogicalANDExpr
350   | LogicalORExpr OR LogicalANDExpr
351                            { $$ = new BinaryLogicalNode($1, OpOr, $3); }
352 ;
353
354 ConditionalExpr:
355     LogicalORExpr
356   | LogicalORExpr '?' AssignmentExpr ':' AssignmentExpr
357                            { $$ = new ConditionalNode($1, $3, $5); }
358 ;
359
360 AssignmentExpr:
361     ConditionalExpr
362   | LeftHandSideExpr AssignmentOperator AssignmentExpr
363                            { $$ = new AssignNode($1, $2, $3);}
364 ;
365
366 AssignmentOperator:
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; }
379 ;
380
381 Expr:
382     AssignmentExpr
383   | Expr ',' AssignmentExpr        { $$ = new CommaNode($1, $3); }
384 ;
385
386 Statement:
387     Block
388   | VariableStatement
389   | ConstStatement
390   | EmptyStatement
391   | ExprStatement
392   | IfStatement
393   | IterationStatement
394   | ContinueStatement
395   | BreakStatement
396   | ReturnStatement
397   | WithStatement
398   | SwitchStatement
399   | LabelledStatement
400   | ThrowStatement
401   | TryStatement
402 ;
403
404 Block:
405     '{' '}'                        { $$ = new BlockNode(0); DBG($$, @2, @2); }
406   | '{' SourceElements '}'          { $$ = new BlockNode($2); DBG($$, @3, @3); }
407 ;
408
409 StatementList:
410     Statement                      { $$ = new StatListNode($1); }
411   | StatementList Statement        { $$ = new StatListNode($1, $2); }
412 ;
413
414 VariableStatement:
415     VAR VariableDeclarationList ';' { $$ = new VarStatementNode($2);
416                                       DBG($$, @1, @3); }
417   | VAR VariableDeclarationList error { if (automatic()) {
418                                           $$ = new VarStatementNode($2);
419                                           DBG($$, @1, @2);
420                                         } else {
421                                           YYABORT;
422                                         }
423                                       }
424 ;
425
426 VariableDeclarationList:
427     VariableDeclaration            { $$ = new VarDeclListNode($1); }
428   | VariableDeclarationList ',' VariableDeclaration
429                                    { $$ = new VarDeclListNode($1, $3); }
430 ;
431
432 VariableDeclaration:
433     IDENT                          { $$ = new VarDeclNode(*$1, 0, VarDeclNode::Variable); }
434   | IDENT Initializer              { $$ = new VarDeclNode(*$1, $2, VarDeclNode::Variable); }
435 ;
436
437 ConstStatement:
438     CONST ConstDeclarationList ';' { $$ = new VarStatementNode($2);
439                                       DBG($$, @1, @3); }
440   | CONST ConstDeclarationList error { if (automatic()) {
441                                           $$ = new VarStatementNode($2);
442                                           DBG($$, @1, @2);
443                                         } else {
444                                           YYABORT;
445                                         }
446                                       }
447 ;
448
449 ConstDeclarationList:
450     ConstDeclaration            { $$ = new VarDeclListNode($1); }
451   | ConstDeclarationList ',' VariableDeclaration
452                                    { $$ = new VarDeclListNode($1, $3); }
453 ;
454
455 ConstDeclaration:
456     IDENT                          { $$ = new VarDeclNode(*$1, 0, VarDeclNode::Constant); }
457   | IDENT Initializer              { $$ = new VarDeclNode(*$1, $2, VarDeclNode::Constant); }
458 ;
459
460 Initializer:
461     '=' AssignmentExpr             { $$ = new AssignExprNode($2); }
462 ;
463
464 EmptyStatement:
465     ';'                            { $$ = new EmptyStatementNode(); }
466 ;
467
468 ExprStatement:
469     Expr ';'                       { $$ = new ExprStatementNode($1);
470                                      DBG($$, @1, @2); }
471   | Expr error                     { if (automatic()) {
472                                        $$ = new ExprStatementNode($1);
473                                        DBG($$, @1, @1);
474                                      } else
475                                        YYABORT; }
476 ;
477
478 IfStatement: /* shift/reduce conflict due to dangling else */
479     IF '(' Expr ')' Statement      { $$ = new IfNode($3,$5,0);DBG($$,@1,@4); }
480   | IF '(' Expr ')' Statement ELSE Statement
481                                    { $$ = new IfNode($3,$5,$7);DBG($$,@1,@4); }
482 ;
483
484 IterationStatement:
485     DO Statement WHILE '(' Expr ')' { $$=new DoWhileNode($2,$5);DBG($$,@1,@3);}
486   | WHILE '(' Expr ')' Statement   { $$ = new WhileNode($3,$5);DBG($$,@1,@4); }
487   | FOR '(' ExprOpt ';' ExprOpt ';' ExprOpt ')'
488             Statement              { $$ = new ForNode($3,$5,$7,$9);
489                                      DBG($$,@1,@8); }
490   | FOR '(' VAR VariableDeclarationList ';' ExprOpt ';' ExprOpt ')'
491             Statement              { $$ = new ForNode($4,$6,$8,$10);
492                                      DBG($$,@1,@9); }
493   | FOR '(' LeftHandSideExpr IN Expr ')'
494             Statement              { $$ = new ForInNode($3, $5, $7);
495                                      DBG($$,@1,@6); }
496   | FOR '(' VAR IDENT IN Expr ')'
497             Statement              { $$ = new ForInNode(*$4,0,$6,$8);
498                                      DBG($$,@1,@7); }
499   | FOR '(' VAR IDENT Initializer IN Expr ')'
500             Statement              { $$ = new ForInNode(*$4,$5,$7,$9);
501                                      DBG($$,@1,@8); }
502 ;
503
504 ExprOpt:
505     /* nothing */                  { $$ = 0; }
506   | Expr
507 ;
508
509 ContinueStatement:
510     CONTINUE ';'                   { $$ = new ContinueNode(); DBG($$,@1,@2); }
511   | CONTINUE error                 { if (automatic()) {
512                                        $$ = new ContinueNode(); DBG($$,@1,@2);
513                                      } else
514                                        YYABORT; }
515   | CONTINUE IDENT ';'             { $$ = new ContinueNode(*$2); DBG($$,@1,@3); }
516   | CONTINUE IDENT error           { if (automatic()) {
517                                        $$ = new ContinueNode(*$2);DBG($$,@1,@2);
518                                      } else
519                                        YYABORT; }
520 ;
521
522 BreakStatement:
523     BREAK ';'                      { $$ = new BreakNode();DBG($$,@1,@2); }
524   | BREAK error                    { if (automatic()) {
525                                        $$ = new BreakNode(); DBG($$,@1,@1);
526                                      } else
527                                        YYABORT; }
528   | BREAK IDENT ';'                { $$ = new BreakNode(*$2); DBG($$,@1,@3); }
529   | BREAK IDENT error              { if (automatic()) {
530                                        $$ = new BreakNode(*$2); DBG($$,@1,@2);
531                                      } else
532                                        YYABORT;
533                                    }
534 ;
535
536 ReturnStatement:
537     RETURN ';'                     { $$ = new ReturnNode(0); DBG($$,@1,@2); }
538   | RETURN error                   { if (automatic()) {
539                                        $$ = new ReturnNode(0); DBG($$,@1,@1);
540                                      } else
541                                        YYABORT; }
542   | RETURN Expr ';'                { $$ = new ReturnNode($2); }
543   | RETURN Expr error              { if (automatic())
544                                        $$ = new ReturnNode($2);
545                                      else
546                                        YYABORT; }
547 ;
548
549 WithStatement:
550     WITH '(' Expr ')' Statement    { $$ = new WithNode($3,$5);
551                                      DBG($$, @1, @4); }
552 ;
553
554 SwitchStatement:
555     SWITCH '(' Expr ')' CaseBlock  { $$ = new SwitchNode($3, $5);
556                                      DBG($$, @1, @4); }
557 ;
558
559 CaseBlock:
560     '{' CaseClausesOpt '}'         { $$ = new CaseBlockNode($2, 0, 0); }
561   | '{' CaseClausesOpt DefaultClause CaseClausesOpt '}'
562                                    { $$ = new CaseBlockNode($2, $3, $4); }
563 ;
564
565 CaseClausesOpt:
566     /* nothing */                  { $$ = 0; }
567   | CaseClauses
568 ;
569
570 CaseClauses:
571     CaseClause                     { $$ = new ClauseListNode($1); }
572   | CaseClauses CaseClause         { $$ = new ClauseListNode($1, $2); }
573 ;
574
575 CaseClause:
576     CASE Expr ':'                  { $$ = new CaseClauseNode($2); }
577   | CASE Expr ':' StatementList    { $$ = new CaseClauseNode($2, $4); }
578 ;
579
580 DefaultClause:
581     DEFAULT ':'                    { $$ = new CaseClauseNode(0); }
582   | DEFAULT ':' StatementList      { $$ = new CaseClauseNode(0, $3); }
583 ;
584
585 LabelledStatement:
586     IDENT ':' Statement            { $3->pushLabel(*$1);
587                                      $$ = new LabelNode(*$1, $3); }
588 ;
589
590 ThrowStatement:
591     THROW Expr ';'                 { $$ = new ThrowNode($2); }
592   | THROW Expr error               { if (automatic()) $$ = new ThrowNode($2); else YYABORT; }
593 ;
594
595 TryStatement:
596     TRY Block Catch                { $$ = new TryNode($2, $3); }
597   | TRY Block Finally              { $$ = new TryNode($2, $3); }
598   | TRY Block Catch Finally        { $$ = new TryNode($2, $3, $4); }
599 ;
600
601 Catch:
602     CATCH '(' IDENT ')' Block      { $$ = new CatchNode(*$3, $5); }
603 ;
604
605 Finally:
606     FINALLY Block                  { $$ = new FinallyNode($2); }
607 ;
608
609 FunctionDeclaration:
610     FUNCTION IDENT '(' ')' FunctionBody    { $$ = new FuncDeclNode(*$2, $5); }
611   | FUNCTION IDENT '(' FormalParameterList ')' FunctionBody
612                                    { $$ = new FuncDeclNode(*$2, $4, $6); }
613
614 FunctionExpr:
615     FUNCTION '(' ')' FunctionBody  { $$ = new FuncExprNode($4); }
616   | FUNCTION '(' FormalParameterList ')' FunctionBody
617                                    { $$ = new FuncExprNode($3, $5); }
618
619 ;
620
621 FormalParameterList:
622     IDENT                          { $$ = new ParameterNode(*$1); }
623   | FormalParameterList ',' IDENT  { $$ = new ParameterNode($1, *$3); }
624 ;
625
626 FunctionBody:
627     '{' '}'  /* TODO: spec ??? */  { $$ = new FunctionBodyNode(0);
628                                      DBG($$, @1, @2);}
629   | '{' SourceElements '}'         { $$ = new FunctionBodyNode($2);
630                                      DBG($$, @1, @3);}
631 ;
632
633 Program:
634     /* nothing, empty script */      { $$ = new ProgramNode(0);
635                                      Parser::progNode = $$; }
636     | SourceElements                 { $$ = new ProgramNode($1);
637                                      Parser::progNode = $$; }
638 ;
639
640 SourceElements:
641     SourceElement                  { $$ = new SourceElementsNode($1); }
642   | SourceElements SourceElement   { $$ = new SourceElementsNode($1, $2); }
643 ;
644
645 SourceElement:
646     Statement                      { $$ = $1; }
647   | FunctionDeclaration            { $$ = $1; }
648 ;
649
650 %%
651
652 int yyerror (const char * /* s */)  /* Called by yyparse on error */
653 {
654   // fprintf(stderr, "ERROR: %s at line %d\n",
655   //      s, KJS::Lexer::curr()->lineNo());
656   return 1;
657 }
658
659 /* may we automatically insert a semicolon ? */
660 bool automatic()
661 {
662   if (yychar == '}' || yychar == 0)
663     return true;
664   else if (Lexer::curr()->prevTerminator())
665     return true;
666
667   return false;
668 }