small cleanup
[swftools.git] / lib / as3 / parser.y
1 /* parser.lex
2
3    Routines for compiling Flash2 AVM2 ABC Actionscript
4
5    Extension module for the rfxswf library.
6    Part of the swftools package.
7
8    Copyright (c) 2008 Matthias Kramm <kramm@quiss.org>
9  
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
23 %{
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <memory.h>
27 #include "abc.h"
28 #include "pool.h"
29 #include "files.h"
30 #include "tokenizer.h"
31 #include "registry.h"
32 #include "code.h"
33 #include "opcodes.h"
34
35 %}
36
37 //%glr-parser
38 //%expect-rr 1
39 %error-verbose
40
41 %union tokenunion {
42     tokenptr_t token;
43
44     classinfo_t*classinfo;
45     classinfo_list_t*classinfo_list;
46
47     int number_int;
48     unsigned int number_uint;
49     double number_float;
50     code_t*code;
51     typedcode_t value;
52     typedcode_list_t*value_list;
53     param_t* param;
54     param_list_t* param_list;
55     writeable_t writeable;
56     char*string;
57 }
58
59
60 %token<token> T_IDENTIFIER
61 %token<string> T_STRING
62 %token<token> T_REGEXP
63 %token<token> T_EMPTY
64 %token<number_int> T_INT
65 %token<number_uint> T_UINT
66 %token<number_uint> T_BYTE
67 %token<number_uint> T_SHORT
68 %token<number_float> T_FLOAT
69
70 %token<token> KW_IMPLEMENTS
71 %token<token> KW_NAMESPACE "namespace"
72 %token<token> KW_PACKAGE "package"
73 %token<token> KW_PROTECTED
74 %token<token> KW_PUBLIC
75 %token<token> KW_PRIVATE
76 %token<token> KW_USE "use"
77 %token<token> KW_INTERNAL
78 %token<token> KW_NEW "new"
79 %token<token> KW_NATIVE
80 %token<token> KW_FUNCTION "function"
81 %token<token> KW_FOR "for"
82 %token<token> KW_CLASS "class"
83 %token<token> KW_CONST "const"
84 %token<token> KW_SET "set"
85 %token<token> KW_STATIC
86 %token<token> KW_IMPORT "import"
87 %token<token> KW_RETURN "return"
88 %token<token> KW_INTERFACE "interface"
89 %token<token> KW_NULL "null"
90 %token<token> KW_VAR "var"
91 %token<token> KW_DYNAMIC
92 %token<token> KW_OVERRIDE
93 %token<token> KW_FINAL
94 %token<token> KW_GET "get"
95 %token<token> KW_EXTENDS
96 %token<token> KW_FALSE "false"
97 %token<token> KW_TRUE "true"
98 %token<token> KW_BOOLEAN "Boolean"
99 %token<token> KW_UINT "uint"
100 %token<token> KW_INT "int"
101 %token<token> KW_WHILE "while"
102 %token<token> KW_NUMBER "Number"
103 %token<token> KW_STRING "String"
104 %token<token> KW_IF "if"
105 %token<token> KW_ELSE  "else"
106 %token<token> KW_BREAK   "break"
107 %token<token> KW_IS "is"
108 %token<token> KW_AS "as"
109
110 %token<token> T_EQEQ "=="
111 %token<token> T_EQEQEQ "==="
112 %token<token> T_NE "!="
113 %token<token> T_LE "<="
114 %token<token> T_GE ">="
115 %token<token> T_DIVBY "/=" 
116 %token<token> T_MODBY "%="
117 %token<token> T_PLUSBY "+=" 
118 %token<token> T_MINUSBY "-="
119 %token<token> T_SHRBY ">>="
120 %token<token> T_SHLBY "<<="
121 %token<token> T_USHRBY ">>>="
122 %token<token> T_OROR "||"
123 %token<token> T_ANDAND "&&"
124 %token<token> T_COLONCOLON "::"
125 %token<token> T_MINUSMINUS "--"
126 %token<token> T_PLUSPLUS "++"
127 %token<token> T_DOTDOT ".."
128 %token<token> T_SHL "<<"
129 %token<token> T_USHR ">>>"
130 %token<token> T_SHR ">>"
131 %token<token> T_SEMICOLON ';'
132 %token<token> T_STAR '*'
133 %token<token> T_DOT '.'
134
135 %type <token> X_IDENTIFIER
136 %type <code> CODE
137 %type <code> CODEPIECE
138 %type <code> CODEBLOCK MAYBECODE
139 %type <token> PACKAGE_DECLARATION
140 %type <token> FUNCTION_DECLARATION
141 %type <code> VARIABLE_DECLARATION
142 %type <token> CLASS_DECLARATION
143 %type <token> NAMESPACE_DECLARATION
144 %type <token> INTERFACE_DECLARATION
145 %type <code> VOIDEXPRESSION
146 %type <value> EXPRESSION
147 %type <value> MAYBEEXPRESSION
148 %type <value> E
149 %type <writeable> LH
150 %type <value> CONSTANT
151 %type <code> FOR IF WHILE MAYBEELSE BREAK RETURN
152 %type <token> USE_NAMESPACE
153 %type <code> ASSIGNMENT FOR_INIT
154 %type <token> IMPORT
155 %type <classinfo> MAYBETYPE
156 %type <token> GETSET
157 %type <param> PARAM
158 %type <param_list> PARAM_LIST
159 %type <param_list> MAYBE_PARAM_LIST
160 %type <token> MODIFIERS
161 %type <token> MODIFIER_LIST
162 %type <classinfo_list> IMPLEMENTS_LIST
163 %type <classinfo> EXTENDS
164 %type <classinfo_list> EXTENDS_LIST
165 %type <classinfo> CLASS PACKAGEANDCLASS QNAME
166 %type <classinfo_list> QNAME_LIST
167 %type <classinfo> TYPE
168 %type <token> VAR
169 //%type <token> VARIABLE
170 %type <value> VAR_READ
171 %type <value> NEW
172 //%type <token> T_IDENTIFIER
173 %type <token> MODIFIER
174 %type <token> PACKAGE
175 %type <value> FUNCTIONCALL
176 %type <value_list> MAYBE_EXPRESSION_LIST EXPRESSION_LIST MAYBE_PARAM_VALUES
177
178 // precedence: from low to high
179 // http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000012.html
180
181 %left prec_none
182 %right '?' ':'
183 %nonassoc '='
184 %nonassoc "/=" "%="
185 %nonassoc "+=" "-="
186 %nonassoc ">>="
187 %nonassoc "<<="
188 %nonassoc ">>>="
189 %nonassoc "||"
190 %nonassoc "&&"
191 %nonassoc '|'
192 %nonassoc '^'
193 %nonassoc '&'
194 %nonassoc "!=" "==" "===" "<=" '<' ">=" '>' // TODO: support "a < b < c" syntax?
195 %nonassoc "is"
196 %left '-'
197 %left '+'
198 %left "<<"
199 %left ">>>"
200 %left ">>"
201 %left '%'
202 %left '/'
203 %left '*'
204 %left '!'
205 %left '~'
206 %left "--" "++"
207 %left '['
208 %nonassoc "as"
209 %left '.' ".." "::"
210 %nonassoc T_IDENTIFIER
211 %left below_semicolon
212 %left ';'
213 %nonassoc "else"
214 %left '('
215
216 // needed for "return" precedence:
217 %nonassoc T_STRING T_REGEXP
218 %nonassoc T_INT T_UINT T_BYTE T_SHORT T_FLOAT
219 %nonassoc "new" "false" "true" "null"
220
221 %left prec_highest
222
223      
224 %{
225
226 static int yyerror(char*s)
227 {
228    syntaxerror("%s", s); 
229 }
230 static token_t* concat2(token_t* t1, token_t* t2)
231 {
232     NEW(token_t,t);
233     int l1 = strlen(t1->text);
234     int l2 = strlen(t2->text);
235     t->text = malloc(l1+l2+1);
236     memcpy(t->text   , t1->text, l1);
237     memcpy(t->text+l1, t2->text, l2);
238     t->text[l1+l2] = 0;
239     return t;
240 }
241 static token_t* concat3(token_t* t1, token_t* t2, token_t* t3)
242 {
243     NEW(token_t,t);
244     int l1 = strlen(t1->text);
245     int l2 = strlen(t2->text);
246     int l3 = strlen(t3->text);
247     t->text = malloc(l1+l2+l3+1);
248     memcpy(t->text   , t1->text, l1);
249     memcpy(t->text+l1, t2->text, l2);
250     memcpy(t->text+l1+l2, t3->text, l3);
251     t->text[l1+l2+l3] = 0;
252     return t;
253 }
254 static char* concat3str(const char* t1, const char* t2, const char* t3)
255 {
256     int l1 = strlen(t1);
257     int l2 = strlen(t2);
258     int l3 = strlen(t3);
259     char*text = malloc(l1+l2+l3+1);
260     memcpy(text   , t1, l1);
261     memcpy(text+l1, t2, l2);
262     memcpy(text+l1+l2, t3, l3);
263     text[l1+l2+l3] = 0;
264     return text;
265 }
266
267 typedef struct _import {
268     char*package;
269 } import_t;
270
271 DECLARE_LIST(import);
272
273 typedef struct _state {
274     abc_file_t*file;
275     abc_script_t*init;
276
277     int level;
278
279     char*package;     
280     char*function;
281     /* code that needs to be executed at the start of
282        a method (like initializing local registers) */
283     code_t*initcode;
284
285     abc_method_body_t*m;
286     
287     import_list_t*wildcard_imports;
288     dict_t*imports;
289     char has_own_imports;
290    
291     /* class data */
292     char*classname;
293     abc_class_t*cls;
294
295     array_t*vars;
296     int local_var_base;
297 } state_t;
298
299 static state_t* state = 0;
300
301 DECLARE_LIST(state);
302
303 #define MULTINAME(m,x) multiname_t m;namespace_t m##_ns;registry_fill_multiname(&m, &m##_ns, x);
304
305 static state_list_t*state_stack=0;
306
307 static void new_state()
308 {
309     NEW(state_t, s);
310     NEW(state_list_t, sl);
311
312     state_t*oldstate = state;
313     if(state)
314         memcpy(s, state, sizeof(state_t)); //shallow copy
315     sl->next = state_stack;
316     sl->state = s;
317     if(oldstate) {
318         s->local_var_base = array_length(oldstate->vars) + oldstate->local_var_base;
319     }
320     if(!s->imports) {
321         s->imports = dict_new();
322     }
323     state_stack = sl;
324     state = s;
325     state->level++;
326     state->vars = array_new();
327     state->initcode = 0;
328     state->has_own_imports = 0;
329 }
330 static void state_has_imports()
331 {
332     state->wildcard_imports = list_clone(state->wildcard_imports);
333     state->imports = dict_clone(state->imports);
334     state->has_own_imports = 1;
335 }
336
337 static void old_state()
338 {
339     if(!state_stack || !state_stack->next)
340         syntaxerror("invalid nesting");
341     state_t*oldstate = state;
342     state_list_t*old = state_stack;
343     state_stack = state_stack->next;
344     free(old);
345     state = state_stack->state;
346     /*if(state->initcode) {
347         printf("residual initcode\n");
348         code_dump(state->initcode, 0, 0, "", stdout);
349     }*/
350     if(oldstate->has_own_imports) {
351         list_free(oldstate->wildcard_imports);
352         dict_destroy(oldstate->imports);oldstate->imports=0;
353     }
354     state->initcode = code_append(state->initcode, oldstate->initcode);
355 }
356 void initialize_state()
357 {
358     new_state();
359
360     state->file = abc_file_new();
361     state->file->flags &= ~ABCFILE_LAZY;
362     
363     state->init = abc_initscript(state->file, 0, 0);
364     abc_method_body_t*m = state->init->method->body;
365     __ getlocal_0(m);
366     __ pushscope(m);
367     __ findpropstrict(m, "[package]::trace");
368     __ pushstring(m, "[entering global init function]");
369     __ callpropvoid(m, "[package]::trace", 1);
370 }
371 void* finalize_state()
372 {
373     if(state->level!=1) {
374         syntaxerror("unexpected end of file");
375     }
376     abc_method_body_t*m = state->init->method->body;
377     //__ popscope(m);
378     
379     __ findpropstrict(m, "[package]::trace");
380     __ pushstring(m, "[leaving global init function]");
381     __ callpropvoid(m, "[package]::trace", 1);
382     __ returnvoid(m);
383     return state->file;
384 }
385
386
387 static void startpackage(token_t*t) 
388 {
389     if(state->package) {
390         syntaxerror("Packages can not be nested."); 
391     } 
392     new_state();
393     char*name = t?t->text:"";
394     /*printf("entering package \"%s\"\n", name);*/
395     state->package = name;
396 }
397 static void endpackage()
398 {
399     /*printf("leaving package \"%s\"\n", state->package);*/
400     old_state();
401 }
402
403 char*globalclass=0;
404 static void startclass(token_t*modifiers, token_t*name, classinfo_t*extends, classinfo_list_t*implements, char interface)
405 {
406     if(state->cls) {
407         syntaxerror("inner classes now allowed"); 
408     }
409     new_state();
410     state->classname = name->text;
411
412     token_list_t*t=0;
413     classinfo_list_t*mlist=0;
414     /*printf("entering class %s\n", name->text);
415     printf("  modifiers: ");for(t=modifiers->tokens;t;t=t->next) printf("%s ", t->token->text);printf("\n");
416     if(extends) 
417         printf("  extends: %s.%s\n", extends->package, extends->name);
418     printf("  implements (%d): ", list_length(implements));
419     for(mlist=implements;mlist;mlist=mlist->next)  {
420         printf("%s ", mlist->classinfo?mlist->classinfo->name:0);
421     }
422     printf("\n");
423     */
424
425     char public=0,internal=0,final=0,sealed=1;
426     for(t=modifiers->tokens;t;t=t->next) {
427         if(t->token->type == KW_INTERNAL) {
428             /* the programmer is being explicit- 
429                being internal is the default anyway */
430             internal = 1;
431         } else if(t->token->type == KW_PUBLIC) {
432             public = 1;
433         } else if(t->token->type == KW_FINAL) {
434             final = 1;
435         } else {
436             syntaxerror("modifier \"%s\" not supported in class declaration", t->token->text);
437         }
438     }
439     if(public&&internal)
440         syntaxerror("public and internal not supported at the same time.");
441
442     /* create the class name, together with the proper attributes */
443     int access=0;
444     char*package=0;
445
446     if(!public && !state->package) {
447         access = ACCESS_PRIVATE; package = current_filename;
448     } else if(!public && state->package) {
449         access = ACCESS_PACKAGEINTERNAL; package = state->package;
450     } else if(state->package) {
451         access = ACCESS_PACKAGE; package = state->package;
452     } else {
453         syntaxerror("public classes only allowed inside a package");
454     }
455
456     if(registry_findclass(package, state->classname)) {
457         syntaxerror("Package \"%s\" already contains a class called \"%s\"", package, state->classname);
458     }
459     
460     classinfo_t* classname = classinfo_register(access, package, state->classname);
461
462     MULTINAME(classname2,classname);
463     
464     multiname_t*extends2 = sig2mname(extends);
465
466     state->cls = abc_class_new(state->file, &classname2, extends2);
467     if(final) abc_class_final(state->cls);
468     if(sealed) abc_class_sealed(state->cls);
469     if(interface) abc_class_interface(state->cls);
470
471     for(mlist=implements;mlist;mlist=mlist->next) {
472         MULTINAME(m, mlist->classinfo);
473         abc_class_add_interface(state->cls, &m);
474     }
475
476     /* now write the construction code for this class */
477     int slotindex = abc_initscript_addClassTrait(state->init, &classname2, state->cls);
478
479     abc_method_body_t*m = state->init->method->body;
480     __ getglobalscope(m);
481     classinfo_t*s = extends;
482
483     int count=0;
484     
485     while(s) {
486         //TODO: take a look at the current scope stack, maybe 
487         //      we can re-use something
488         s = s->superclass;
489         if(!s) 
490         break;
491        
492         multiname_t*s2 = sig2mname(s);
493         __ getlex2(m, s2);
494         multiname_destroy(s2);
495
496         __ pushscope(m); count++;
497         m->code = m->code->prev->prev; // invert
498     }
499     /* continue appending after last op end */
500     while(m->code && m->code->next) m->code = m->code->next; 
501
502     /* TODO: if this is one of *our* classes, we can also 
503              do a getglobalscope/getslot <nr> (which references
504              the init function's slots) */
505     if(extends2) {
506         __ getlex2(m, extends2);
507         __ dup(m);
508         /* notice: we get a Verify Error #1107 if the top elemnt on the scope
509            stack is not the superclass */
510         __ pushscope(m);count++;
511     } else {
512         __ pushnull(m);
513         /* notice: we get a verify error #1107 if the top element on the scope 
514            stack is not the global object */
515         __ getlocal_0(m);
516         __ pushscope(m);count++;
517     }
518     __ newclass(m,state->cls);
519     while(count--) {
520         __ popscope(m);
521     }
522     __ setslot(m, slotindex);
523
524     /* flash.display.MovieClip handling */
525     if(!globalclass && public && classinfo_equals(registry_getMovieClip(),extends)) {
526         if(state->package && state->package[0]) {
527             globalclass = concat3str(state->package, ".", state->classname);
528         } else {
529             globalclass = strdup(state->classname);
530         }
531     }
532     multiname_destroy(extends2);
533 }
534
535 static void endclass()
536 {
537     /*printf("leaving class %s\n", state->classname);*/
538     old_state();
539 }
540 static void startfunction(token_t*ns, token_t*mod, token_t*getset, token_t*name,
541                           param_list_t*params, classinfo_t*type)
542 {
543     token_list_t*t;
544     new_state();
545     state->function = name->text;
546     
547     /*printf("entering function %s\n", name->text);
548     if(ns)
549         printf("  namespace: %s\n", ns->text);
550     printf("  getset: %s\n", getset->text);
551     printf("  params: ");for(t=params->tokens;t;t=t->next) printf("%s ", t->token->text);printf("\n");
552     printf("  mod: ");for(t=mod->tokens;t;t=t->next) printf("%s ", t->token->text);printf("\n");
553     if(type)
554         printf("  type: %s.%s\n", type->package, type->name);
555     print_imports();*/
556     
557     if(state->m) {
558         syntaxerror("not able to start another method scope");
559     }
560
561     multiname_t*type2 = sig2mname(type);
562     if(!strcmp(state->classname,name->text)) {
563         state->m = abc_class_constructor(state->cls, type2, 0);
564     } else {
565         state->m = abc_class_method(state->cls, type2, name->text, 0);
566     }
567     param_list_t*p;
568     for(p=params;p;p=p->next) {
569         multiname_t*m = sig2mname(p->param->type);
570         list_append(state->m->method->parameters, m);
571     }
572
573     /* state->vars is initialized by state_new */
574     array_append(state->vars, "this", 0);
575     for(p=params;p;p=p->next) {
576         array_append(state->vars, p->param->name, 0);
577     }
578
579     __ getlocal_0(state->m);
580     __ pushscope(state->m);
581 }
582 static void endfunction()
583 {
584     /*printf("leaving function %s\n", state->function);*/
585     __ returnvoid(state->m);
586
587     old_state();
588 }
589
590
591 static token_t* empty_token()
592 {
593     NEW(token_t,t);
594     t->type=T_EMPTY;
595     t->text=0;
596     return t;
597 }
598
599 void extend(token_t*list, token_t*add) {
600     list_append(list->tokens,add);
601     if(!list->text)
602         list->text = add->text;
603 }
604 void extend_s(token_t*list, char*seperator, token_t*add) {
605     list_append(list->tokens,add);
606     char*t1 = list->text;
607     char*t2 = seperator;
608     char*t3 = add->text;
609     int l1 = strlen(t1);
610     int l2 = strlen(t2);
611     int l3 = strlen(t3);
612     list->text = malloc(l1+l2+l3+1);
613     strcpy(list->text, t1);
614     strcpy(list->text+l1, t2);
615     strcpy(list->text+l1+l2, t3);
616     list->text[l1+l2+l3]=0;
617 }
618
619 static int find_variable(char*name, classinfo_t**m)
620 {
621     state_list_t* s = state_stack;
622     while(s) {
623         int i = array_find(s->state->vars, name);
624         if(i>=0) {
625             if(m) {
626                 *m = array_getvalue(s->state->vars, i);
627             }
628             return i + s->state->local_var_base;
629         }
630         s = s->next;
631     }
632     return -1;
633
634 static int find_variable_safe(char*name, classinfo_t**m)
635 {
636     int i = find_variable(name, m);
637     if(i<0)
638         syntaxerror("undefined variable: %s", name);
639     return i;
640 }
641 static char variable_exists(char*name) 
642 {
643     return array_contains(state->vars, name);
644 }
645 static int new_variable(char*name, classinfo_t*type)
646 {
647     return array_append(state->vars, name, type) + state->local_var_base;
648 }
649 code_t* killvars(code_t*c) 
650 {
651     int t;
652     for(t=0;t<state->vars->num;t++) {
653         classinfo_t*type = array_getvalue(state->vars, t);
654         //do this always, otherwise register types don't match
655         //in the verifier when doing nested loops
656         //if(!TYPE_IS_BUILTIN_SIMPLE(type)) {
657             c = abc_kill(c, t+state->local_var_base);
658         //}
659     }
660     return c;
661 }
662
663 char is_subtype_of(classinfo_t*type, classinfo_t*supertype)
664 {
665     return 1; // FIXME
666 }
667
668 void breakjumpsto(code_t*c, code_t*jump) 
669 {
670     while(c->prev) 
671         c=c->prev;
672     while(c) {
673         if(c->opcode == OPCODE___BREAK__) {
674             c->opcode = OPCODE_JUMP;
675             c->branch = jump;
676         }
677         c = c->next;
678     }
679 }
680
681 classinfo_t*join_types(classinfo_t*type1, classinfo_t*type2, char op)
682 {
683     return registry_getanytype(); // FIXME
684 }
685 code_t*converttype(code_t*c, classinfo_t*from, classinfo_t*to)
686 {
687     if(from==to)
688         return c;
689     if(!to) {
690         /*TODO: can omit this if from is zero? */
691         return abc_coerce_a(c);
692     }
693     if(TYPE_IS_NUMBER(from) && TYPE_IS_UINT(to)) {
694         MULTINAME(m, TYPE_UINT);
695         return abc_coerce2(c, &m);
696     }
697     if(TYPE_IS_NUMBER(from) && TYPE_IS_INT(to)) {
698         MULTINAME(m, TYPE_INT);
699         return abc_coerce2(c, &m);
700     }
701     return c;
702 }
703
704 code_t*defaultvalue(code_t*c, classinfo_t*type)
705 {
706     if(TYPE_IS_INT(type) || TYPE_IS_UINT(type) || TYPE_IS_FLOAT(type)) {
707        c = abc_pushbyte(c, 0);
708     } else if(TYPE_IS_BOOLEAN(type)) {
709        c = abc_pushfalse(c);
710     } else {
711        c = abc_pushnull(c);
712     }
713     return c;
714 }
715
716 %}
717
718
719 %%
720
721 /* ------------ code blocks / statements ---------------- */
722
723 PROGRAM: MAYBECODE
724
725 MAYBECODE: CODE {$$=$1;}
726 MAYBECODE:      {$$=code_new();}
727
728 CODE: CODE CODEPIECE {$$=code_append($1,$2);}
729 CODE: CODEPIECE {$$=$1;}
730
731 CODEPIECE: PACKAGE_DECLARATION   {$$=code_new();/*enters a scope*/}
732 CODEPIECE: CLASS_DECLARATION     {$$=code_new();/*enters a scope*/}
733 CODEPIECE: INTERFACE_DECLARATION {/*TODO*/$$=code_new();}
734 CODEPIECE: IMPORT                {$$=code_new();/*adds imports to current scope*/}
735 CODEPIECE: ';'                   {$$=code_new();}
736 CODEPIECE: VARIABLE_DECLARATION  {$$=$1}
737 CODEPIECE: VOIDEXPRESSION        {$$=$1}
738 CODEPIECE: FOR                   {$$=$1}
739 CODEPIECE: WHILE                 {$$=$1}
740 CODEPIECE: BREAK                 {$$=$1}
741 CODEPIECE: RETURN                {$$=$1}
742 CODEPIECE: IF                    {$$=$1}
743 CODEPIECE: ASSIGNMENT            {$$=$1}
744 CODEPIECE: NAMESPACE_DECLARATION {/*TODO*/$$=code_new();}
745 CODEPIECE: FUNCTION_DECLARATION  {/*TODO*/$$=code_new();}
746 CODEPIECE: USE_NAMESPACE         {/*TODO*/$$=code_new();}
747
748 CODEBLOCK :  '{' MAYBECODE '}' {$$=$2;}
749 CODEBLOCK :  CODEPIECE ';'             {$$=$1;}
750 CODEBLOCK :  CODEPIECE %prec below_semicolon {$$=$1;}
751
752 /* ------------ functions --------------------------- */
753
754 FUNCTION_DECLARATION: MODIFIERS "function" GETSET T_IDENTIFIER '(' MAYBE_PARAM_LIST ')' 
755                       MAYBETYPE '{' {startfunction(0,$1,$3,$4,$6,$8)} MAYBECODE '}' {
756     if(!state->m) syntaxerror("internal error: undefined function");
757     state->initcode = abc_nop(state->initcode);
758     state->initcode = abc_nop(state->initcode);
759     state->initcode = abc_nop(state->initcode);
760     state->m->code = code_append(state->initcode, $11);state->initcode=0;
761     endfunction()
762 }
763
764 /* ------------ variables --------------------------- */
765
766 MAYBEEXPRESSION : '=' EXPRESSION {$$=$2;}
767                 |                {$$.c=abc_pushundefined(0);
768                                   $$.t=TYPE_ANY;
769                                  }
770
771 VAR : "const" | "var"
772 VARIABLE_DECLARATION : VAR T_IDENTIFIER MAYBETYPE MAYBEEXPRESSION {
773     if(variable_exists($2->text))
774         syntaxerror("Variable %s already defined", $2->text);
775    
776     if(!is_subtype_of($4.t, $3)) {
777         syntaxerror("Can't convert %s to %s", $4.t->name, 
778                                               $3->name);
779     }
780
781     int index = new_variable($2->text, $3);
782     
783     if($3) {
784         if($4.c->prev || $4.c->opcode != OPCODE_PUSHUNDEFINED) {
785             $$ = $4.c;
786             $$ = converttype($$, $4.t, $3);
787             $$ = abc_setlocal($$, index);
788         } else {
789             $$ = defaultvalue(0, $3);
790             $$ = abc_setlocal($$, index);
791         }
792
793         /* push default value for type on stack */
794         state->initcode = defaultvalue(state->initcode, $3);
795         state->initcode = abc_setlocal(state->initcode, index);
796     } else {
797         /* only bother to actually set this variable if its syntax is either
798             var x:type;
799            or
800             var x=expr;
801         */
802         if($4.c->prev || $4.c->opcode != OPCODE_PUSHUNDEFINED) {
803             $$ = $4.c;
804             $$ = abc_coerce_a($$);
805             $$ = abc_setlocal($$, index);
806         } else {
807             $$ = code_new();
808         }
809     }
810     
811     /* that's the default for a local register, anyway
812         else {
813         state->initcode = abc_pushundefined(state->initcode);
814         state->initcode = abc_setlocal(state->initcode, index);
815     }*/
816     printf("variable %s -> %d (%s)\n", $2->text, index, $4.t?$4.t->name:"");
817 }
818 ASSIGNMENT :           T_IDENTIFIER '=' EXPRESSION {
819     classinfo_t*type=0;
820     int i = find_variable_safe($1->text, &type);
821     $$ = $3.c;
822     if(!type && $3.t) {
823         // convert to "any" type, the register is untyped
824         $$ = abc_coerce_a($$);
825     } else {
826         // TODO: convert ints to strings etc.
827     }
828     $$ = abc_setlocal($$, i);
829 }
830
831 /* ------------ control flow ------------------------- */
832
833 MAYBEELSE:  %prec prec_none {$$ = code_new();}
834 MAYBEELSE: "else" CODEBLOCK {$$=$2;}
835 //MAYBEELSE: ';' "else" CODEBLOCK {$$=$3;}
836
837 IF  : "if" '(' {new_state();} EXPRESSION ')' CODEBLOCK MAYBEELSE {
838     $$ = state->initcode;state->initcode=0;
839
840     $$ = code_append($$, $4.c);
841     code_t*myjmp,*myif = $$ = abc_iffalse($$, 0);
842    
843     $$ = code_append($$, $6);
844     if($7) {
845         myjmp = $$ = abc_jump($$, 0);
846     }
847     myif->branch = $$ = abc_label($$);
848     if($7) {
849         $$ = code_append($$, $7);
850         myjmp->branch = $$ = abc_label($$);
851     }
852     
853     $$ = killvars($$);old_state();
854 }
855
856 FOR_INIT : {$$=code_new();}
857 FOR_INIT : ASSIGNMENT | VARIABLE_DECLARATION | VOIDEXPRESSION
858
859 FOR : "for" '(' {new_state();} FOR_INIT ';' EXPRESSION ';' VOIDEXPRESSION ')' CODEBLOCK {
860     $$ = state->initcode;state->initcode=0;
861
862     $$ = code_append($$, $4);
863     code_t*loopstart = $$ = abc_label($$);
864     $$ = code_append($$, $6.c);
865     code_t*myif = $$ = abc_iffalse($$, 0);
866     $$ = code_append($$, $10);
867     $$ = code_append($$, $8);
868     $$ = abc_jump($$, loopstart);
869     code_t*out = $$ = abc_label($$);
870     breakjumpsto($$, out);
871     myif->branch = out;
872
873     $$ = killvars($$);old_state();
874 }
875
876 WHILE : "while" '(' {new_state();} EXPRESSION ')' CODEBLOCK {
877     $$ = state->initcode;state->initcode=0;
878
879     code_t*myjmp = $$ = abc_jump($$, 0);
880     code_t*loopstart = $$ = abc_label($$);
881     $$ = code_append($$, $6);
882     myjmp->branch = $$ = abc_label($$);
883     $$ = code_append($$, $4.c);
884     $$ = abc_iftrue($$, loopstart);
885     code_t*out = $$ = abc_label($$);
886     breakjumpsto($$, out);
887
888     $$ = killvars($$);old_state();
889 }
890
891 BREAK : "break" {
892     $$ = abc___break__(0);
893 }
894
895 /* ------------ packages and imports ---------------- */
896
897 X_IDENTIFIER: T_IDENTIFIER
898             | "package"
899
900 PACKAGE: PACKAGE '.' X_IDENTIFIER {$$ = concat3($1,$2,$3);}
901 PACKAGE: X_IDENTIFIER             {$$=$1;}
902
903 PACKAGE_DECLARATION : "package" PACKAGE '{' {startpackage($2)} MAYBECODE '}' {endpackage()}
904 PACKAGE_DECLARATION : "package" '{' {startpackage(0)} MAYBECODE '}' {endpackage()}
905
906 IMPORT : "import" QNAME {
907        classinfo_t*c = $2;
908        if(!c) 
909             syntaxerror("Couldn't import class\n");
910        state_has_imports();
911        dict_put(state->imports, c->name, c);
912        $$=0;
913 }
914 IMPORT : "import" PACKAGE '.' '*' {
915        NEW(import_t,i);
916        i->package = $2->text;
917        state_has_imports();
918        list_append(state->wildcard_imports, i);
919        $$=0;
920 }
921
922 /* ------------ classes and interfaces -------------- */
923
924 MODIFIERS : {$$=empty_token();}
925 MODIFIERS : MODIFIER_LIST {$$=$1}
926 MODIFIER_LIST : MODIFIER MODIFIER_LIST {extend($2,$1);$$=$2;}
927 MODIFIER_LIST : MODIFIER               {$$=empty_token();extend($$,$1);}
928 MODIFIER : KW_PUBLIC | KW_PRIVATE | KW_PROTECTED | KW_STATIC | KW_DYNAMIC | KW_FINAL | KW_OVERRIDE | KW_NATIVE | KW_INTERNAL
929
930 EXTENDS : {$$=registry_getobjectclass();}
931 EXTENDS : KW_EXTENDS QNAME {$$=$2;}
932
933 EXTENDS_LIST : {$$=list_new();}
934 EXTENDS_LIST : KW_EXTENDS QNAME_LIST {$$=$2;}
935
936 IMPLEMENTS_LIST : {$$=list_new();}
937 IMPLEMENTS_LIST : KW_IMPLEMENTS QNAME_LIST {$$=$2;}
938
939 CLASS_DECLARATION : MODIFIERS "class" T_IDENTIFIER 
940                               EXTENDS IMPLEMENTS_LIST 
941                               '{' {startclass($1,$3,$4,$5, 0);} 
942                               MAYBE_DECLARATION_LIST 
943                               '}' {endclass();}
944 INTERFACE_DECLARATION : MODIFIERS "interface" T_IDENTIFIER 
945                               EXTENDS_LIST 
946                               '{' {startclass($1,$3,0,$4,1);}
947                               MAYBE_IDECLARATION_LIST 
948                               '}' {endclass();}
949
950 /* ------------- package + class ids --------------- */
951
952 CLASS: T_IDENTIFIER {
953
954     /* try current package */
955     $$ = registry_findclass(state->package, $1->text);
956
957     /* try explicit imports */
958     dictentry_t* e = dict_get_slot(state->imports, $1->text);
959     while(e) {
960         if($$)
961             break;
962         if(!strcmp(e->key, $1->text)) {
963             $$ = (classinfo_t*)e->data;
964         }
965         e = e->next;
966     }
967
968     /* try package.* imports */
969     import_list_t*l = state->wildcard_imports;
970     while(l) {
971         if($$)
972             break;
973         //printf("does package %s contain a class %s?\n", l->import->package, $1->text);
974         $$ = registry_findclass(l->import->package, $1->text);
975         l = l->next;
976     }
977
978     /* try global package */
979     if(!$$) {
980         $$ = registry_findclass("", $1->text);
981     }
982
983     if(!$$) syntaxerror("Could not find class %s\n", $1->text);
984 }
985
986 PACKAGEANDCLASS : PACKAGE '.' T_IDENTIFIER {
987     $$ = registry_findclass($1->text, $3->text);
988     if(!$$) syntaxerror("Couldn't find class %s.%s\n", $1->text, $3->text);
989 }
990
991 QNAME: PACKAGEANDCLASS
992      | CLASS
993
994
995 /* ----------function calls, constructor calls ------ */
996
997 MAYBE_PARAM_VALUES :  %prec prec_none {$$=0;}
998 MAYBE_PARAM_VALUES : '(' MAYBE_EXPRESSION_LIST ')' {$$=$2}
999
1000 MAYBE_EXPRESSION_LIST : {$$=0;}
1001 MAYBE_EXPRESSION_LIST : EXPRESSION_LIST
1002 EXPRESSION_LIST : EXPRESSION                     {$$=list_new();
1003                                                   typedcode_t*t = malloc(sizeof(typedcode_t));
1004                                                   *t = $1;
1005                                                   list_append($$, t);}
1006 EXPRESSION_LIST : EXPRESSION_LIST ',' EXPRESSION {$$=$1;
1007                                                   typedcode_t*t = malloc(sizeof(typedcode_t));
1008                                                   *t = $3;
1009                                                   list_append($$, t);}
1010
1011 NEW : "new" CLASS MAYBE_PARAM_VALUES {
1012     MULTINAME(m, $2);
1013     $$.c = code_new();
1014     $$.c = abc_findpropstrict2($$.c, &m);
1015     typedcode_list_t*l = $3;
1016     int len = 0;
1017     while(l) {
1018         $$.c = code_append($$.c, l->typedcode->c); // push parameters on stack
1019         l = l->next;
1020         len ++;
1021     }
1022     $$.c = abc_constructprop2($$.c, &m, len);
1023     $$.t = $2;
1024 }
1025
1026 /* TODO: use abc_call (for calling local variables),
1027          abc_callstatic (for calling own methods) 
1028          call (for closures)
1029 */
1030 FUNCTIONCALL : E '(' MAYBE_EXPRESSION_LIST ')' {
1031     typedcode_list_t*l = $3;
1032     int len = 0;
1033     code_t*paramcode = 0;
1034     while(l) {
1035         paramcode = code_append(paramcode, l->typedcode->c); // push parameters on stack
1036         l = l->next;
1037         len ++;
1038     }
1039
1040     $$.c = $1.c;
1041     if($$.c->opcode == OPCODE_GETPROPERTY) {
1042         multiname_t*name = multiname_clone($$.c->data[0]);
1043         $$.c = code_cutlast($$.c);
1044         $$.c = code_append($$.c, paramcode);
1045         $$.c = abc_callproperty2($$.c, name, len);
1046     } else {
1047         int i = find_variable_safe("this", 0);
1048         $$.c = abc_getlocal($$.c, i);
1049         $$.c = code_append($$.c, paramcode);
1050         $$.c = abc_call($$.c, len);
1051     }
1052     /* TODO: look up the functions's return value */
1053     $$.t = TYPE_ANY;
1054 }
1055
1056 RETURN: "return" %prec prec_none {
1057     $$ = abc_returnvoid(0);
1058 }
1059 RETURN: "return" EXPRESSION {
1060     $$ = $2.c;
1061     $$ = abc_returnvalue($$);
1062 }
1063
1064 TYPE : QNAME {$$=$1;}
1065      | '*'        {$$=registry_getanytype();}
1066      |  "String"  {$$=registry_getstringclass();}
1067      |  "int"     {$$=registry_getintclass();}
1068      |  "uint"    {$$=registry_getuintclass();}
1069      |  "Boolean" {$$=registry_getbooleanclass();}
1070      |  "Number"  {$$=registry_getnumberclass();}
1071
1072 MAYBETYPE: ':' TYPE {$$=$2;}
1073 MAYBETYPE:          {$$=0;}
1074
1075 //FUNCTION_HEADER:      NAMESPACE MODIFIERS T_FUNCTION GETSET T_IDENTIFIER '(' PARAMS ')' 
1076 FUNCTION_HEADER:      MODIFIERS "function" GETSET T_IDENTIFIER '(' MAYBE_PARAM_LIST ')' 
1077                       MAYBETYPE
1078
1079 NAMESPACE_DECLARATION : MODIFIERS KW_NAMESPACE T_IDENTIFIER
1080 NAMESPACE_DECLARATION : MODIFIERS KW_NAMESPACE T_IDENTIFIER '=' T_IDENTIFIER
1081 NAMESPACE_DECLARATION : MODIFIERS KW_NAMESPACE T_IDENTIFIER '=' T_STRING
1082
1083 //NAMESPACE :              {$$=empty_token();}
1084 //NAMESPACE : T_IDENTIFIER {$$=$1};
1085
1086 CONSTANT : T_BYTE {$$.c = abc_pushbyte(0, $1);
1087                    //MULTINAME(m, registry_getintclass());
1088                    //$$.c = abc_coerce2($$.c, &m); // FIXME
1089                    $$.t = TYPE_INT;
1090                   }
1091 CONSTANT : T_SHORT {$$.c = abc_pushshort(0, $1);
1092                     $$.t = TYPE_INT;
1093                    }
1094 CONSTANT : T_INT {$$.c = abc_pushint(0, $1);
1095                   $$.t = TYPE_INT;
1096                  }
1097 CONSTANT : T_UINT {$$.c = abc_pushuint(0, $1);
1098                    $$.t = TYPE_UINT;
1099                   }
1100 CONSTANT : T_FLOAT {$$.c = abc_pushdouble(0, $1);
1101                     $$.t = TYPE_FLOAT;
1102                    }
1103 CONSTANT : T_STRING {$$.c = abc_pushstring(0, $1);
1104                      $$.t = TYPE_STRING;
1105                     }
1106 CONSTANT : KW_TRUE {$$.c = abc_pushtrue(0);
1107                     $$.t = TYPE_BOOLEAN;
1108                    }
1109 CONSTANT : KW_FALSE {$$.c = abc_pushfalse(0);
1110                      $$.t = TYPE_BOOLEAN;
1111                     }
1112 CONSTANT : KW_NULL {$$.c = abc_pushnull(0);
1113                     $$.t = TYPE_NULL;
1114                    }
1115
1116 USE_NAMESPACE : "use" "namespace" T_IDENTIFIER
1117
1118
1119 EXPRESSION : E %prec prec_none  /*precedence below '-x'*/ {$$ = $1;}
1120 VOIDEXPRESSION : E %prec prec_none {$$=$1.c;/*calculate and discard*/$$=abc_pop($$);}
1121
1122 E : CONSTANT
1123 E : VAR_READ %prec T_IDENTIFIER {$$ = $1;}
1124 E : NEW                         {$$ = $1;}
1125 E : T_REGEXP                    {$$.c = abc_pushundefined(0); /* FIXME */
1126                                  $$.t = TYPE_ANY;
1127                                 }
1128 E : FUNCTIONCALL
1129 E : E '<' E {$$.c = code_append($1.c,$3.c);$$.c = abc_greaterequals($$.c);$$.c=abc_not($$.c);
1130              $$.t = TYPE_BOOLEAN;
1131             }
1132 E : E '>' E {$$.c = code_append($1.c,$3.c);$$.c = abc_greaterthan($$.c);
1133              $$.t = TYPE_BOOLEAN;
1134             }
1135 E : E "<=" E {$$.c = code_append($1.c,$3.c);$$.c = abc_greaterthan($$.c);$$.c=abc_not($$.c);
1136               $$.t = TYPE_BOOLEAN;
1137              }
1138 E : E ">=" E {$$.c = code_append($1.c,$3.c);$$.c = abc_greaterequals($$.c);
1139               $$.t = TYPE_BOOLEAN;
1140              }
1141 E : E "==" E {$$.c = code_append($1.c,$3.c);$$.c = abc_equals($$.c);
1142               $$.t = TYPE_BOOLEAN;
1143              }
1144 E : E "===" E {$$.c = code_append($1.c,$3.c);$$.c = abc_strictequals($$.c);
1145               $$.t = TYPE_BOOLEAN;
1146              }
1147 E : E "!=" E {$$.c = code_append($1.c,$3.c);$$.c = abc_equals($$.c);$$.c = abc_not($$.c);
1148               $$.t = TYPE_BOOLEAN;
1149              }
1150
1151 E : E "||" E {$$.t = join_types($1.t, $3.t, 'O');
1152               $$.c = $1.c;
1153               $$.c = converttype($$.c, $1.t, $$.t);
1154               $$.c = abc_dup($$.c);
1155               code_t*jmp = $$.c = abc_iftrue($$.c, 0);
1156               $$.c = abc_pop($$.c);
1157               $$.c = code_append($$.c,$3.c);
1158               $$.c = converttype($$.c, $1.t, $$.t);
1159               code_t*label = $$.c = abc_label($$.c);
1160               jmp->branch = label;
1161              }
1162 E : E "&&" E {$$.t = join_types($1.t, $3.t, 'A');
1163               $$.c = $1.c;
1164               $$.c = converttype($$.c, $1.t, $$.t);
1165               $$.c = abc_dup($$.c);
1166               code_t*jmp = $$.c = abc_iffalse($$.c, 0);
1167               $$.c = abc_pop($$.c);
1168               $$.c = code_append($$.c,$3.c);
1169               $$.c = converttype($$.c, $1.t, $$.t);
1170               code_t*label = $$.c = abc_label($$.c);
1171               jmp->branch = label;              
1172              }
1173
1174 E : E '.' T_IDENTIFIER
1175             {$$.c = $1.c;
1176              if($$.t) {
1177                  namespace_t ns = {$$.t->access, (char*)$$.t->package};
1178                  multiname_t m = {QNAME, &ns, 0, $3->text};
1179                  $$.c = abc_getproperty2($$.c, &m);
1180                 /* FIXME: get type of ($1.t).$3 */
1181                  $$.t = registry_getanytype();
1182              } else {
1183                  namespace_t ns = {ACCESS_PACKAGE, ""};
1184                  multiname_t m = {QNAME, &ns, 0, $3->text};
1185                  $$.c = abc_getproperty2($$.c, &m);
1186                  $$.t = registry_getanytype();
1187              }
1188             }
1189
1190 E : '!' E    {$$.c=$2.c;
1191               $$.c = abc_not($$.c);
1192               $$.t = TYPE_BOOLEAN;
1193              }
1194
1195 E : E '-' E
1196 E : E '/' E
1197 E : E '+' E {$$.c = code_append($1.c,$3.c);$$.c = abc_add($$.c);$$.c=abc_coerce_a($$.c);
1198              $$.t = join_types($1.t, $3.t, '+');
1199             }
1200 E : E '%' E {$$.c = code_append($1.c,$3.c);$$.c = abc_modulo($$.c);$$.c=abc_coerce_a($$.c);
1201              $$.t = join_types($1.t, $3.t, '%');
1202             }
1203 E : E '*' E {$$.c = code_append($1.c,$3.c);$$.c = abc_multiply($$.c);$$.c=abc_coerce_a($$.c);
1204              $$.t = join_types($1.t, $3.t, '*');
1205             }
1206
1207 E : E "as" E
1208 E : E "is" E
1209 E : '(' E ')' {$$=$2;}
1210 E : '-' E {$$=$2;}
1211
1212 E : LH "+=" E {$$.c = $1.read;$$.c=code_append($$.c,$3.c);$$.c=abc_add($$.c);
1213                classinfo_t*type = join_types($1.type, $3.t, '+');
1214                $$.c=converttype($$.c, type, $1.type);
1215                $$.c=abc_dup($$.c);$$.c=code_append($$.c,$1.write);
1216                $$.t = $1.type;
1217               }
1218 E : LH "-=" E {$$.c = $1.read;$$.c=code_append($$.c,$3.c);$$.c=abc_add($$.c);
1219                classinfo_t*type = join_types($1.type, $3.t, '-');
1220                $$.c=converttype($$.c, type, $1.type);
1221                $$.c=abc_dup($$.c);$$.c=code_append($$.c,$1.write);
1222                $$.t = $1.type;
1223               }
1224
1225 // TODO: use inclocal where appropriate
1226 E : LH "++" {$$.c = $1.read;
1227              classinfo_t*type = $1.type;
1228              if(TYPE_IS_INT(type) || TYPE_IS_UINT(type)) {
1229                  $$.c=abc_increment_i($$.c);
1230              } else {
1231                  $$.c=abc_increment($$.c);
1232                  type = TYPE_NUMBER;
1233              }
1234              $$.c=converttype($$.c, type, $1.type);
1235              $$.c=abc_dup($$.c);$$.c=code_append($$.c,$1.write);
1236              $$.t = $1.type;
1237             }
1238 E : LH "--" {$$.c = $1.read;
1239              classinfo_t*type = $1.type;
1240              if(TYPE_IS_INT(type) || TYPE_IS_UINT(type)) {
1241                  $$.c=abc_decrement_i($$.c);
1242              } else {
1243                  $$.c=abc_decrement($$.c);
1244                  type = TYPE_NUMBER;
1245              }
1246              $$.c=converttype($$.c, type, $1.type);
1247              $$.c=abc_dup($$.c);$$.c=code_append($$.c,$1.write);
1248              $$.t = $1.type;
1249             }
1250
1251 LH: T_IDENTIFIER {
1252   int i = find_variable_safe($1->text, &$$.type);
1253   $$.read = abc_getlocal(0, i);
1254   $$.write = abc_setlocal(0, i);
1255 }
1256
1257
1258 VAR_READ : T_IDENTIFIER {
1259     $$.t = 0;
1260     $$.c = 0;
1261     int i = find_variable($1->text, &$$.t);
1262     if(i>=0) {
1263         $$.c = abc_getlocal($$.c, i);
1264     } else {
1265         $$.t = 0;
1266         $$.c = abc_findpropstrict($$.c, $1->text);
1267         $$.c = abc_getproperty($$.c, $1->text);
1268     }
1269 }
1270
1271 //VARIABLE : T_IDENTIFIER
1272 //VARIABLE : VARIABLE '.' T_IDENTIFIER
1273 //VARIABLE : VARIABLE ".." T_IDENTIFIER // descendants
1274 //VARIABLE : VARIABLE "::" VARIABLE // namespace declaration
1275 //VARIABLE : VARIABLE "::" '[' EXPRESSION ']' // qualified expression
1276 //VARIABLE : VARIABLE '[' EXPRESSION ']' // unqualified expression
1277
1278 GETSET : "get" {$$=$1;}
1279        | "set" {$$=$1;}
1280        |       {$$=empty_token();}
1281
1282 MAYBE_PARAM_LIST: {$$=list_new();}
1283 MAYBE_PARAM_LIST: PARAM_LIST {$$=$1;}
1284 PARAM_LIST: PARAM_LIST ',' PARAM {$$ =$1;         list_append($$, $3);}
1285 PARAM_LIST: PARAM                {$$ = list_new();list_append($$, $1);}
1286 PARAM:  T_IDENTIFIER ':' TYPE {$$ = malloc(sizeof(param_t));
1287                                $$->name=$1->text;$$->type = $3;}
1288 PARAM:  T_IDENTIFIER          {$$ = malloc(sizeof(param_t));
1289                                $$->name=$1->text;$$->type = TYPE_ANY;}
1290
1291 DECLARATION : VARIABLE_DECLARATION
1292 DECLARATION : FUNCTION_DECLARATION
1293
1294 IDECLARATION : VARIABLE_DECLARATION
1295 IDECLARATION : FUNCTION_DECLARATION
1296
1297 //IDENTIFIER_LIST : T_IDENTIFIER ',' IDENTIFIER_LIST {extend($3,$1);$$=$3;}
1298 //IDENTIFIER_LIST : T_IDENTIFIER                     {$$=empty_token();extend($$,$1);}
1299
1300 QNAME_LIST : QNAME {$$=list_new();list_append($$, $1);}
1301 QNAME_LIST : QNAME_LIST ',' QNAME {$$=$1;list_append($$,$3);}
1302
1303 MAYBE_DECLARATION_LIST : 
1304 MAYBE_DECLARATION_LIST : DECLARATION_LIST
1305 DECLARATION_LIST : DECLARATION
1306 DECLARATION_LIST : DECLARATION_LIST DECLARATION
1307
1308 MAYBE_IDECLARATION_LIST : 
1309 MAYBE_IDECLARATION_LIST : IDECLARATION_LIST
1310 IDECLARATION_LIST : IDECLARATION
1311 IDECLARATION_LIST : IDECLARATION_LIST FUNCTION_HEADER
1312
1313 // chapter 14
1314 // keywords: as break case catch class const continue default delete do else extends false finally for function if implements import in instanceof interface internal is native new null package private protected public return super switch this throw to true try typeof use var void while with
1315 // syntactic keywords: each get set namespace include dynamic final native override static
1316