cf0dc173672930493bdae9611f50a16cf31d52b8
[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
135 %type <cnode> Catch
136 %type <fnode> Finally
137
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
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
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
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   | EmptyStatement
390   | ExprStatement
391   | IfStatement
392   | IterationStatement
393   | ContinueStatement
394   | BreakStatement
395   | ReturnStatement
396   | WithStatement
397   | SwitchStatement
398   | LabelledStatement
399   | ThrowStatement
400   | TryStatement
401 ;
402
403 Block:
404     '{' '}'                        { $$ = new BlockNode(0); DBG($$, @2, @2); }
405   | '{' SourceElements '}'          { $$ = new BlockNode($2); DBG($$, @3, @3); }
406 ;
407
408 StatementList:
409     Statement                      { $$ = new StatListNode($1); }
410   | StatementList Statement        { $$ = new StatListNode($1, $2); }
411 ;
412
413 VariableStatement:
414     VAR VariableDeclarationList ';' { $$ = new VarStatementNode($2);
415                                       DBG($$, @1, @3); }
416   | VAR VariableDeclarationList error { if (automatic()) {
417                                           $$ = new VarStatementNode($2);
418                                           DBG($$, @1, @2);
419                                         } else {
420                                           YYABORT;
421                                         }
422                                       }
423 ;
424
425 VariableDeclarationList:
426     VariableDeclaration            { $$ = new VarDeclListNode($1); }
427   | VariableDeclarationList ',' VariableDeclaration
428                                    { $$ = new VarDeclListNode($1, $3); }
429 ;
430
431 VariableDeclaration:
432     IDENT                          { $$ = new VarDeclNode(*$1, 0); }
433   | IDENT Initializer              { $$ = new VarDeclNode(*$1, $2); }
434 ;
435
436 Initializer:
437     '=' AssignmentExpr             { $$ = new AssignExprNode($2); }
438 ;
439
440 EmptyStatement:
441     ';'                            { $$ = new EmptyStatementNode(); }
442 ;
443
444 ExprStatement:
445     Expr ';'                       { $$ = new ExprStatementNode($1);
446                                      DBG($$, @1, @2); }
447   | Expr error                     { if (automatic()) {
448                                        $$ = new ExprStatementNode($1);
449                                        DBG($$, @1, @1);
450                                      } else
451                                        YYABORT; }
452 ;
453
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); }
458 ;
459
460 IterationStatement:
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);
465                                      DBG($$,@1,@8); }
466   | FOR '(' VAR VariableDeclarationList ';' ExprOpt ';' ExprOpt ')'
467             Statement              { $$ = new ForNode($4,$6,$8,$10);
468                                      DBG($$,@1,@9); }
469   | FOR '(' LeftHandSideExpr IN Expr ')'
470             Statement              { $$ = new ForInNode($3, $5, $7);
471                                      DBG($$,@1,@6); }
472   | FOR '(' VAR IDENT IN Expr ')'
473             Statement              { $$ = new ForInNode(*$4,0,$6,$8);
474                                      DBG($$,@1,@7); }
475   | FOR '(' VAR IDENT Initializer IN Expr ')'
476             Statement              { $$ = new ForInNode(*$4,$5,$7,$9);
477                                      DBG($$,@1,@8); }
478 ;
479
480 ExprOpt:
481     /* nothing */                  { $$ = 0; }
482   | Expr
483 ;
484
485 ContinueStatement:
486     CONTINUE ';'                   { $$ = new ContinueNode(); DBG($$,@1,@2); }
487   | CONTINUE error                 { if (automatic()) {
488                                        $$ = new ContinueNode(); DBG($$,@1,@2);
489                                      } else
490                                        YYABORT; }
491   | CONTINUE IDENT ';'             { $$ = new ContinueNode(*$2); DBG($$,@1,@3); }
492   | CONTINUE IDENT error           { if (automatic()) {
493                                        $$ = new ContinueNode(*$2);DBG($$,@1,@2);
494                                      } else
495                                        YYABORT; }
496 ;
497
498 BreakStatement:
499     BREAK ';'                      { $$ = new BreakNode();DBG($$,@1,@2); }
500   | BREAK error                    { if (automatic()) {
501                                        $$ = new BreakNode(); DBG($$,@1,@1);
502                                      } else
503                                        YYABORT; }
504   | BREAK IDENT ';'                { $$ = new BreakNode(*$2); DBG($$,@1,@3); }
505   | BREAK IDENT error              { if (automatic()) {
506                                        $$ = new BreakNode(*$2); DBG($$,@1,@2);
507                                      } else
508                                        YYABORT;
509                                    }
510 ;
511
512 ReturnStatement:
513     RETURN ';'                     { $$ = new ReturnNode(0); DBG($$,@1,@2); }
514   | RETURN error                   { if (automatic()) {
515                                        $$ = new ReturnNode(0); DBG($$,@1,@1);
516                                      } else
517                                        YYABORT; }
518   | RETURN Expr ';'                { $$ = new ReturnNode($2); }
519   | RETURN Expr error              { if (automatic())
520                                        $$ = new ReturnNode($2);
521                                      else
522                                        YYABORT; }
523 ;
524
525 WithStatement:
526     WITH '(' Expr ')' Statement    { $$ = new WithNode($3,$5);
527                                      DBG($$, @1, @4); }
528 ;
529
530 SwitchStatement:
531     SWITCH '(' Expr ')' CaseBlock  { $$ = new SwitchNode($3, $5);
532                                      DBG($$, @1, @4); }
533 ;
534
535 CaseBlock:
536     '{' CaseClausesOpt '}'         { $$ = new CaseBlockNode($2, 0, 0); }
537   | '{' CaseClausesOpt DefaultClause CaseClausesOpt '}'
538                                    { $$ = new CaseBlockNode($2, $3, $4); }
539 ;
540
541 CaseClausesOpt:
542     /* nothing */                  { $$ = 0; }
543   | CaseClauses
544 ;
545
546 CaseClauses:
547     CaseClause                     { $$ = new ClauseListNode($1); }
548   | CaseClauses CaseClause         { $$ = new ClauseListNode($1, $2); }
549 ;
550
551 CaseClause:
552     CASE Expr ':'                  { $$ = new CaseClauseNode($2); }
553   | CASE Expr ':' StatementList    { $$ = new CaseClauseNode($2, $4); }
554 ;
555
556 DefaultClause:
557     DEFAULT ':'                    { $$ = new CaseClauseNode(0); }
558   | DEFAULT ':' StatementList      { $$ = new CaseClauseNode(0, $3); }
559 ;
560
561 LabelledStatement:
562     IDENT ':' Statement            { $3->pushLabel(*$1);
563                                      $$ = new LabelNode(*$1, $3); }
564 ;
565
566 ThrowStatement:
567     THROW Expr ';'                 { $$ = new ThrowNode($2); }
568   | THROW Expr error               { if (automatic()) $$ = new ThrowNode($2); else YYABORT; }
569 ;
570
571 TryStatement:
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); }
575 ;
576
577 Catch:
578     CATCH '(' IDENT ')' Block      { $$ = new CatchNode(*$3, $5); }
579 ;
580
581 Finally:
582     FINALLY Block                  { $$ = new FinallyNode($2); }
583 ;
584
585 FunctionDeclaration:
586     FUNCTION IDENT '(' ')' FunctionBody    { $$ = new FuncDeclNode(*$2, $5); }
587   | FUNCTION IDENT '(' FormalParameterList ')' FunctionBody
588                                    { $$ = new FuncDeclNode(*$2, $4, $6); }
589
590 FunctionExpr:
591     FUNCTION '(' ')' FunctionBody  { $$ = new FuncExprNode($4); }
592   | FUNCTION '(' FormalParameterList ')' FunctionBody
593                                    { $$ = new FuncExprNode($3, $5); }
594
595 ;
596
597 FormalParameterList:
598     IDENT                          { $$ = new ParameterNode(*$1); }
599   | FormalParameterList ',' IDENT  { $$ = new ParameterNode($1, *$3); }
600 ;
601
602 FunctionBody:
603     '{' '}'  /* TODO: spec ??? */  { $$ = new FunctionBodyNode(0);
604                                      DBG($$, @1, @2);}
605   | '{' SourceElements '}'         { $$ = new FunctionBodyNode($2);
606                                      DBG($$, @1, @3);}
607 ;
608
609 Program:
610     /* nothing, empty script */      { $$ = new ProgramNode(0);
611                                      Parser::progNode = $$; }
612     | SourceElements                 { $$ = new ProgramNode($1);
613                                      Parser::progNode = $$; }
614 ;
615
616 SourceElements:
617     SourceElement                  { $$ = new SourceElementsNode($1); }
618   | SourceElements SourceElement   { $$ = new SourceElementsNode($1, $2); }
619 ;
620
621 SourceElement:
622     Statement                      { $$ = $1; }
623   | FunctionDeclaration            { $$ = $1; }
624 ;
625
626 %%
627
628 int yyerror (const char * /* s */)  /* Called by yyparse on error */
629 {
630   // fprintf(stderr, "ERROR: %s at line %d\n",
631   //      s, KJS::Lexer::curr()->lineNo());
632   return 1;
633 }
634
635 /* may we automatically insert a semicolon ? */
636 bool automatic()
637 {
638   if (yychar == '}' || yychar == 0)
639     return true;
640   else if (Lexer::curr()->prevTerminator())
641     return true;
642
643   return false;
644 }