Reviewed by John.
[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 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 %type <node>  CallExpr
135
136 %type <cnode> Catch
137 %type <fnode> Finally
138
139 %type <stat>  Statement Block
140 %type <stat>  VariableStatement EmptyStatement ExprStatement
141 %type <stat>  IfStatement IterationStatement ContinueStatement
142 %type <stat>  BreakStatement ReturnStatement WithStatement
143 %type <stat>  SwitchStatement LabelledStatement
144 %type <stat>  ThrowStatement TryStatement
145 %type <stat>  SourceElement
146
147 %type <slist> StatementList
148 %type <init>  Initializer
149 %type <func>  FunctionDeclaration
150 %type <body>  FunctionBody
151 %type <srcs>  SourceElements
152 %type <param> FormalParameterList
153 %type <op>    AssignmentOperator
154 %type <prog>  Program
155 %type <args>  Arguments
156 %type <alist> ArgumentList
157 %type <vlist> VariableDeclarationList
158 %type <decl>  VariableDeclaration
159 %type <cblk>  CaseBlock
160 %type <ccl>   CaseClause DefaultClause
161 %type <clist> CaseClauses  CaseClausesOpt
162 %type <ival>  Elision ElisionOpt
163 %type <elm>   ElementList
164 %type <plist> PropertyNameAndValueList
165 %type <pnode> PropertyName
166
167 %%
168
169 Literal:
170     NULLTOKEN                      { $$ = new NullNode(); }
171   | TRUETOKEN                      { $$ = new BooleanNode(true); }
172   | FALSETOKEN                     { $$ = new BooleanNode(false); }
173   | NUMBER                         { $$ = new NumberNode($1); }
174   | STRING                         { $$ = new StringNode($1); }
175   | '/'       /* a RegExp ? */     { Lexer *l = Lexer::curr();
176                                      if (!l->scanRegExp()) YYABORT;
177                                      $$ = new RegExpNode(l->pattern,l->flags);}
178   | DIVEQUAL /* a RegExp starting with /= ! */
179                                    { Lexer *l = Lexer::curr();
180                                      if (!l->scanRegExp()) YYABORT;
181                                      $$ = new RegExpNode(UString('=')+l->pattern,l->flags);}
182 ;
183
184 PrimaryExpr:
185     THIS                           { $$ = new ThisNode(); }
186   | IDENT                          { $$ = new ResolveNode(*$1); }
187   | Literal
188   | ArrayLiteral
189   | '(' Expr ')'                   { $$ = new GroupNode($2); }
190   | '{' '}'                        { $$ = new ObjectLiteralNode(); }
191   | '{' PropertyNameAndValueList '}'   { $$ = new ObjectLiteralNode($2); }
192 ;
193
194 ArrayLiteral:
195     '[' ElisionOpt ']'                 { $$ = new ArrayNode($2); }
196   | '[' ElementList ']'                { $$ = new ArrayNode($2); }
197   | '[' ElementList ',' ElisionOpt ']' { $$ = new ArrayNode($4, $2); }
198 ;
199
200 ElementList:
201     ElisionOpt AssignmentExpr      { $$ = new ElementNode($1, $2); }
202   | ElementList ',' ElisionOpt AssignmentExpr
203                                    { $$ = new ElementNode($1, $3, $4); }
204 ;
205
206 ElisionOpt:
207     /* nothing */                  { $$ = 0; }
208   | Elision
209 ;
210
211 Elision:
212     ','                            { $$ = 1; }
213   | Elision ','                    { $$ = $1 + 1; }
214 ;
215
216 PropertyNameAndValueList:
217     PropertyName ':' AssignmentExpr     { $$ = new PropertyValueNode($1, $3); }
218   | PropertyNameAndValueList ',' PropertyName ':' AssignmentExpr
219                                    { $$ = new PropertyValueNode($3, $5, $1); }
220 ;
221
222 PropertyName:
223     IDENT                          { $$ = new PropertyNode(*$1); }
224   | STRING                         { $$ = new PropertyNode(Identifier(*$1)); }
225   | NUMBER                         { $$ = new PropertyNode($1); }
226 ;
227
228 MemberExpr:
229     PrimaryExpr
230   | FunctionExpr
231   | MemberExpr '[' Expr ']'        { $$ = new AccessorNode1($1, $3); }
232   | MemberExpr '.' IDENT           { $$ = new AccessorNode2($1, *$3); }
233   | NEW MemberExpr Arguments       { $$ = new NewExprNode($2, $3); }
234 ;
235
236 NewExpr:
237     MemberExpr
238   | NEW NewExpr                    { $$ = new NewExprNode($2); }
239 ;
240
241 CallExpr:
242     MemberExpr Arguments           { $$ = new FunctionCallNode($1, $2); }
243   | CallExpr Arguments             { $$ = new FunctionCallNode($1, $2); }
244   | CallExpr '[' Expr ']'          { $$ = new AccessorNode1($1, $3); }
245   | CallExpr '.' IDENT             { $$ = new AccessorNode2($1, *$3); }
246 ;
247
248 Arguments:
249     '(' ')'                        { $$ = new ArgumentsNode(); }
250   | '(' ArgumentList ')'           { $$ = new ArgumentsNode($2); }
251 ;
252
253 ArgumentList:
254     AssignmentExpr                  { $$ = new ArgumentListNode($1); }
255   | ArgumentList ',' AssignmentExpr { $$ = new ArgumentListNode($1, $3); }
256 ;
257
258 LeftHandSideExpr:
259     NewExpr
260   | CallExpr
261 ;
262
263 PostfixExpr:    /* TODO: no line terminator here */
264     LeftHandSideExpr
265   | LeftHandSideExpr PLUSPLUS      { $$ = new PostfixNode($1, OpPlusPlus); }
266   | LeftHandSideExpr MINUSMINUS    { $$ = new PostfixNode($1, OpMinusMinus); }
267 ;
268
269 UnaryExpr:
270     PostfixExpr
271   | DELETE UnaryExpr               { $$ = new DeleteNode($2); }
272   | VOID UnaryExpr                 { $$ = new VoidNode($2); }
273   | TYPEOF UnaryExpr               { $$ = new TypeOfNode($2); }
274   | PLUSPLUS UnaryExpr             { $$ = new PrefixNode(OpPlusPlus, $2); }
275   | AUTOPLUSPLUS UnaryExpr         { $$ = new PrefixNode(OpPlusPlus, $2); }
276   | MINUSMINUS UnaryExpr           { $$ = new PrefixNode(OpMinusMinus, $2); }
277   | AUTOMINUSMINUS UnaryExpr       { $$ = new PrefixNode(OpMinusMinus, $2); }
278   | '+' UnaryExpr                  { $$ = new UnaryPlusNode($2); }
279   | '-' UnaryExpr                  { $$ = new NegateNode($2); }
280   | '~' UnaryExpr                  { $$ = new BitwiseNotNode($2); }
281   | '!' UnaryExpr                  { $$ = new LogicalNotNode($2); }
282 ;
283
284 MultiplicativeExpr:
285     UnaryExpr
286   | MultiplicativeExpr '*' UnaryExpr { $$ = new MultNode($1, $3, '*'); }
287   | MultiplicativeExpr '/' UnaryExpr { $$ = new MultNode($1, $3, '/'); }
288   | MultiplicativeExpr '%' UnaryExpr { $$ = new MultNode($1,$3,'%'); }
289 ;
290
291 AdditiveExpr:
292     MultiplicativeExpr
293   | AdditiveExpr '+' MultiplicativeExpr { $$ = new AddNode($1, $3, '+'); }
294   | AdditiveExpr '-' MultiplicativeExpr { $$ = new AddNode($1, $3, '-'); }
295 ;
296
297 ShiftExpr:
298     AdditiveExpr
299   | ShiftExpr LSHIFT AdditiveExpr  { $$ = new ShiftNode($1, OpLShift, $3); }
300   | ShiftExpr RSHIFT AdditiveExpr  { $$ = new ShiftNode($1, OpRShift, $3); }
301   | ShiftExpr URSHIFT AdditiveExpr { $$ = new ShiftNode($1, OpURShift, $3); }
302 ;
303
304 RelationalExpr:
305     ShiftExpr
306   | RelationalExpr '<' ShiftExpr
307                            { $$ = new RelationalNode($1, OpLess, $3); }
308   | RelationalExpr '>' ShiftExpr
309                            { $$ = new RelationalNode($1, OpGreater, $3); }
310   | RelationalExpr LE ShiftExpr
311                            { $$ = new RelationalNode($1, OpLessEq, $3); }
312   | RelationalExpr GE ShiftExpr
313                            { $$ = new RelationalNode($1, OpGreaterEq, $3); }
314   | RelationalExpr INSTANCEOF ShiftExpr
315                            { $$ = new RelationalNode($1, OpInstanceOf, $3); }
316   | RelationalExpr IN ShiftExpr
317                            { $$ = new RelationalNode($1, OpIn, $3); }
318 ;
319
320 EqualityExpr:
321     RelationalExpr
322   | EqualityExpr EQEQ RelationalExpr   { $$ = new EqualNode($1, OpEqEq, $3); }
323   | EqualityExpr NE RelationalExpr     { $$ = new EqualNode($1, OpNotEq, $3); }
324   | EqualityExpr STREQ RelationalExpr  { $$ = new EqualNode($1, OpStrEq, $3); }
325   | EqualityExpr STRNEQ RelationalExpr { $$ = new EqualNode($1, OpStrNEq, $3);}
326 ;
327
328 BitwiseANDExpr:
329     EqualityExpr
330   | BitwiseANDExpr '&' EqualityExpr { $$ = new BitOperNode($1, OpBitAnd, $3); }
331 ;
332
333 BitwiseXORExpr:
334     BitwiseANDExpr
335   | BitwiseXORExpr '^' BitwiseANDExpr { $$ = new BitOperNode($1, OpBitXOr, $3); }
336 ;
337
338 BitwiseORExpr:
339     BitwiseXORExpr
340   | BitwiseORExpr '|' BitwiseXORExpr { $$ = new BitOperNode($1, OpBitOr, $3); }
341 ;
342
343 LogicalANDExpr:
344     BitwiseORExpr
345   | LogicalANDExpr AND BitwiseORExpr
346                            { $$ = new BinaryLogicalNode($1, OpAnd, $3); }
347 ;
348
349 LogicalORExpr:
350     LogicalANDExpr
351   | LogicalORExpr OR LogicalANDExpr
352                            { $$ = new BinaryLogicalNode($1, OpOr, $3); }
353 ;
354
355 ConditionalExpr:
356     LogicalORExpr
357   | LogicalORExpr '?' AssignmentExpr ':' AssignmentExpr
358                            { $$ = new ConditionalNode($1, $3, $5); }
359 ;
360
361 AssignmentExpr:
362     ConditionalExpr
363   | LeftHandSideExpr AssignmentOperator AssignmentExpr
364                            { $$ = new AssignNode($1, $2, $3);}
365 ;
366
367 AssignmentOperator:
368     '='                            { $$ = OpEqual; }
369   | PLUSEQUAL                      { $$ = OpPlusEq; }
370   | MINUSEQUAL                     { $$ = OpMinusEq; }
371   | MULTEQUAL                      { $$ = OpMultEq; }
372   | DIVEQUAL                       { $$ = OpDivEq; }
373   | LSHIFTEQUAL                    { $$ = OpLShift; }
374   | RSHIFTEQUAL                    { $$ = OpRShift; }
375   | URSHIFTEQUAL                   { $$ = OpURShift; }
376   | ANDEQUAL                       { $$ = OpAndEq; }
377   | XOREQUAL                       { $$ = OpXOrEq; }
378   | OREQUAL                        { $$ = OpOrEq; }
379   | MODEQUAL                       { $$ = OpModEq; }
380 ;
381
382 Expr:
383     AssignmentExpr
384   | Expr ',' AssignmentExpr        { $$ = new CommaNode($1, $3); }
385 ;
386
387 Statement:
388     Block
389   | VariableStatement
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); }
434   | IDENT Initializer              { $$ = new VarDeclNode(*$1, $2); }
435 ;
436
437 Initializer:
438     '=' AssignmentExpr             { $$ = new AssignExprNode($2); }
439 ;
440
441 EmptyStatement:
442     ';'                            { $$ = new EmptyStatementNode(); }
443 ;
444
445 ExprStatement:
446     Expr ';'                       { $$ = new ExprStatementNode($1);
447                                      DBG($$, @1, @2); }
448   | Expr error                     { if (automatic()) {
449                                        $$ = new ExprStatementNode($1);
450                                        DBG($$, @1, @1);
451                                      } else
452                                        YYABORT; }
453 ;
454
455 IfStatement: /* shift/reduce conflict due to dangling else */
456     IF '(' Expr ')' Statement      { $$ = new IfNode($3,$5,0);DBG($$,@1,@4); }
457   | IF '(' Expr ')' Statement ELSE Statement
458                                    { $$ = new IfNode($3,$5,$7);DBG($$,@1,@4); }
459 ;
460
461 IterationStatement:
462     DO Statement WHILE '(' Expr ')' { $$=new DoWhileNode($2,$5);DBG($$,@1,@3);}
463   | WHILE '(' Expr ')' Statement   { $$ = new WhileNode($3,$5);DBG($$,@1,@4); }
464   | FOR '(' ExprOpt ';' ExprOpt ';' ExprOpt ')'
465             Statement              { $$ = new ForNode($3,$5,$7,$9);
466                                      DBG($$,@1,@8); }
467   | FOR '(' VAR VariableDeclarationList ';' ExprOpt ';' ExprOpt ')'
468             Statement              { $$ = new ForNode($4,$6,$8,$10);
469                                      DBG($$,@1,@9); }
470   | FOR '(' LeftHandSideExpr IN Expr ')'
471             Statement              { $$ = new ForInNode($3, $5, $7);
472                                      DBG($$,@1,@6); }
473   | FOR '(' VAR IDENT IN Expr ')'
474             Statement              { $$ = new ForInNode(*$4,0,$6,$8);
475                                      DBG($$,@1,@7); }
476   | FOR '(' VAR IDENT Initializer IN Expr ')'
477             Statement              { $$ = new ForInNode(*$4,$5,$7,$9);
478                                      DBG($$,@1,@8); }
479 ;
480
481 ExprOpt:
482     /* nothing */                  { $$ = 0; }
483   | Expr
484 ;
485
486 ContinueStatement:
487     CONTINUE ';'                   { $$ = new ContinueNode(); DBG($$,@1,@2); }
488   | CONTINUE error                 { if (automatic()) {
489                                        $$ = new ContinueNode(); DBG($$,@1,@2);
490                                      } else
491                                        YYABORT; }
492   | CONTINUE IDENT ';'             { $$ = new ContinueNode(*$2); DBG($$,@1,@3); }
493   | CONTINUE IDENT error           { if (automatic()) {
494                                        $$ = new ContinueNode(*$2);DBG($$,@1,@2);
495                                      } else
496                                        YYABORT; }
497 ;
498
499 BreakStatement:
500     BREAK ';'                      { $$ = new BreakNode();DBG($$,@1,@2); }
501   | BREAK error                    { if (automatic()) {
502                                        $$ = new BreakNode(); DBG($$,@1,@1);
503                                      } else
504                                        YYABORT; }
505   | BREAK IDENT ';'                { $$ = new BreakNode(*$2); DBG($$,@1,@3); }
506   | BREAK IDENT error              { if (automatic()) {
507                                        $$ = new BreakNode(*$2); DBG($$,@1,@2);
508                                      } else
509                                        YYABORT;
510                                    }
511 ;
512
513 ReturnStatement:
514     RETURN ';'                     { $$ = new ReturnNode(0); DBG($$,@1,@2); }
515   | RETURN error                   { if (automatic()) {
516                                        $$ = new ReturnNode(0); DBG($$,@1,@1);
517                                      } else
518                                        YYABORT; }
519   | RETURN Expr ';'                { $$ = new ReturnNode($2); }
520   | RETURN Expr error              { if (automatic())
521                                        $$ = new ReturnNode($2);
522                                      else
523                                        YYABORT; }
524 ;
525
526 WithStatement:
527     WITH '(' Expr ')' Statement    { $$ = new WithNode($3,$5);
528                                      DBG($$, @1, @4); }
529 ;
530
531 SwitchStatement:
532     SWITCH '(' Expr ')' CaseBlock  { $$ = new SwitchNode($3, $5);
533                                      DBG($$, @1, @4); }
534 ;
535
536 CaseBlock:
537     '{' CaseClausesOpt '}'         { $$ = new CaseBlockNode($2, 0, 0); }
538   | '{' CaseClausesOpt DefaultClause CaseClausesOpt '}'
539                                    { $$ = new CaseBlockNode($2, $3, $4); }
540 ;
541
542 CaseClausesOpt:
543     /* nothing */                  { $$ = 0; }
544   | CaseClauses
545 ;
546
547 CaseClauses:
548     CaseClause                     { $$ = new ClauseListNode($1); }
549   | CaseClauses CaseClause         { $$ = new ClauseListNode($1, $2); }
550 ;
551
552 CaseClause:
553     CASE Expr ':'                  { $$ = new CaseClauseNode($2); }
554   | CASE Expr ':' StatementList    { $$ = new CaseClauseNode($2, $4); }
555 ;
556
557 DefaultClause:
558     DEFAULT ':'                    { $$ = new CaseClauseNode(0); }
559   | DEFAULT ':' StatementList      { $$ = new CaseClauseNode(0, $3); }
560 ;
561
562 LabelledStatement:
563     IDENT ':' Statement            { $3->pushLabel(*$1);
564                                      $$ = new LabelNode(*$1, $3); }
565 ;
566
567 ThrowStatement:
568     THROW Expr ';'                 { $$ = new ThrowNode($2); }
569   | THROW Expr error               { if (automatic()) $$ = new ThrowNode($2); else YYABORT; }
570 ;
571
572 TryStatement:
573     TRY Block Catch                { $$ = new TryNode($2, $3); }
574   | TRY Block Finally              { $$ = new TryNode($2, $3); }
575   | TRY Block Catch Finally        { $$ = new TryNode($2, $3, $4); }
576 ;
577
578 Catch:
579     CATCH '(' IDENT ')' Block      { $$ = new CatchNode(*$3, $5); }
580 ;
581
582 Finally:
583     FINALLY Block                  { $$ = new FinallyNode($2); }
584 ;
585
586 FunctionDeclaration:
587     FUNCTION IDENT '(' ')' FunctionBody    { $$ = new FuncDeclNode(*$2, $5); }
588   | FUNCTION IDENT '(' FormalParameterList ')' FunctionBody
589                                    { $$ = new FuncDeclNode(*$2, $4, $6); }
590
591 FunctionExpr:
592     FUNCTION '(' ')' FunctionBody  { $$ = new FuncExprNode($4); }
593   | FUNCTION '(' FormalParameterList ')' FunctionBody
594                                    { $$ = new FuncExprNode($3, $5); }
595
596 ;
597
598 FormalParameterList:
599     IDENT                          { $$ = new ParameterNode(*$1); }
600   | FormalParameterList ',' IDENT  { $$ = new ParameterNode($1, *$3); }
601 ;
602
603 FunctionBody:
604     '{' '}'  /* TODO: spec ??? */  { $$ = new FunctionBodyNode(0);
605                                      DBG($$, @1, @2);}
606   | '{' SourceElements '}'         { $$ = new FunctionBodyNode($2);
607                                      DBG($$, @1, @3);}
608 ;
609
610 Program:
611     /* nothing, empty script */      { $$ = new ProgramNode(0);
612                                      Parser::progNode = $$; }
613     | SourceElements                 { $$ = new ProgramNode($1);
614                                      Parser::progNode = $$; }
615 ;
616
617 SourceElements:
618     SourceElement                  { $$ = new SourceElementsNode($1); }
619   | SourceElements SourceElement   { $$ = new SourceElementsNode($1, $2); }
620 ;
621
622 SourceElement:
623     Statement                      { $$ = $1; }
624   | FunctionDeclaration            { $$ = $1; }
625 ;
626
627 %%
628
629 int yyerror (const char * /* s */)  /* Called by yyparse on error */
630 {
631   // fprintf(stderr, "ERROR: %s at line %d\n",
632   //      s, KJS::Lexer::curr()->lineNo());
633   return 1;
634 }
635
636 /* may we automatically insert a semicolon ? */
637 bool automatic()
638 {
639   if (yychar == '}' || yychar == 0)
640     return true;
641   else if (Lexer::curr()->prevTerminator())
642     return true;
643
644   return false;
645 }