61bbdfc9e10b1a6ba5b55a81f4a68f81be213a49
[swftools.git] / lib / as3 / parser.y
1 %{
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <memory.h>
5 #include "abc.h"
6 #include "pool.h"
7 #include "files.h"
8 #include "tokenizer.h"
9 #include "registry.h"
10 #include "code.h"
11 #include "opcodes.h"
12 %}
13
14 //%glr-parser
15 //%expect-rr 1
16 %error-verbose
17
18 %union tokenunion {
19     tokenptr_t token;
20     multiname_t*multiname;
21     multiname_list_t*multiname_list;
22     int number_int;
23     unsigned int number_uint;
24     double number_float;
25     struct _code*code;
26     struct _code_list*code_list;
27 }
28
29
30 %token<token> T_IDENTIFIER
31 %token<token> T_STRING
32 %token<token> T_REGEXP
33 %token<token> T_EMPTY
34 %token<number_int> T_INT
35 %token<number_uint> T_UINT
36 %token<number_uint> T_BYTE
37 %token<number_uint> T_SHORT
38 %token<number_float> T_FLOAT
39
40 %token<token> KW_IMPLEMENTS
41 %token<token> KW_NAMESPACE
42 %token<token> KW_PACKAGE "package"
43 %token<token> KW_PROTECTED
44 %token<token> KW_PUBLIC
45 %token<token> KW_PRIVATE
46 %token<token> KW_USE "use"
47 %token<token> KW_INTERNAL
48 %token<token> KW_NEW "new"
49 %token<token> KW_NATIVE
50 %token<token> KW_FUNCTION "function"
51 %token<token> KW_FOR "for"
52 %token<token> KW_CLASS "class"
53 %token<token> KW_CONST "const"
54 %token<token> KW_SET "set"
55 %token<token> KW_STATIC
56 %token<token> KW_IMPORT "import"
57 %token<token> KW_INTERFACE "interface"
58 %token<token> KW_NULL
59 %token<token> KW_VAR "var"
60 %token<token> KW_DYNAMIC
61 %token<token> KW_OVERRIDE
62 %token<token> KW_FINAL
63 %token<token> KW_GET "get"
64 %token<token> KW_EXTENDS
65 %token<token> KW_FALSE "False"
66 %token<token> KW_TRUE "True"
67 %token<token> KW_BOOLEAN "Boolean"
68 %token<token> KW_UINT "uint"
69 %token<token> KW_INT "int"
70 %token<token> KW_NUMBER "Number"
71 %token<token> KW_STRING "String"
72 %token<token> KW_IS "is"
73 %token<token> KW_AS "as"
74
75 %token<token> T_EQEQ "=="
76 %token<token> T_LE "<="
77 %token<token> T_GE ">="
78 %token<token> T_DIVBY "/=" 
79 %token<token> T_MODBY "%="
80 %token<token> T_PLUSBY "+=" 
81 %token<token> T_MINUSBY "-="
82 %token<token> T_SHRBY ">>="
83 %token<token> T_SHLBY "<<="
84 %token<token> T_USHRBY ">>>="
85 %token<token> T_OROR "||"
86 %token<token> T_ANDAND "&&"
87 %token<token> T_COLONCOLON "::"
88 %token<token> T_MINUSMINUS "--"
89 %token<token> T_PLUSPLUS "++"
90 %token<token> T_DOTDOT ".."
91 %token<token> T_SHL "<<"
92 %token<token> T_USHR ">>>"
93 %token<token> T_SHR ">>"
94 %token<token> T_SEMICOLON ';'
95 %token<token> T_STAR '*'
96 %token<token> T_DOT '.'
97
98 %type <token> CODE
99 %type <code> CODEPIECE CODEPIECE2
100 %type <token> PACKAGE_DECLARATION
101 %type <token> FUNCTION_DECLARATION
102 %type <code> VARIABLE_DECLARATION
103 %type <token> CLASS_DECLARATION
104 %type <token> NAMESPACE_DECLARATION
105 %type <token> INTERFACE_DECLARATION
106 %type <code> EXPRESSION
107 %type <code> MAYBEEXPRESSION
108 %type <code> E
109 %type <code> CONSTANT
110 %type <token> FOR
111 %type <token> USE
112 %type <token> ASSIGNMENT
113 %type <token> IMPORT
114 %type <multiname> MAYBETYPE
115 %type <token> PACKAGESPEC
116 %type <token> GETSET
117 %type <token> PARAM
118 %type <token> PARAMS
119 %type <token> PARAM_LIST
120 %type <token> MODIFIERS
121 %type <token> MODIFIER_LIST
122 %type <multiname_list> IMPLEMENTS_LIST
123 %type <multiname> EXTENDS
124 %type <multiname_list> EXTENDS_LIST
125 %type <multiname> PACKAGEANDCLASS
126 %type <multiname_list> PACKAGEANDCLASS_LIST
127 %type <token> MULTILEVELIDENTIFIER
128 %type <multiname> TYPE
129 %type <token> VAR
130 %type <token> VARIABLE
131 %type <token> NEW
132 %type <token> X_IDENTIFIER
133 %type <token> MODIFIER
134 %type <token> PACKAGE
135 %type <code> FUNCTIONCALL
136 %type <code_list> MAYBE_EXPRESSION_LIST EXPRESSION_LIST
137
138 // precendence: from low to high
139 // http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000012.html
140
141 %left prec_none
142 %right '?' ':'
143 %nonassoc '='
144 %nonassoc "/=" "%="
145 %nonassoc "+=" "-="
146 %nonassoc ">>="
147 %nonassoc "<<="
148 %nonassoc ">>>="
149 %nonassoc "||"
150 %nonassoc "&&"
151 %nonassoc '|'
152 %nonassoc '^'
153 %nonassoc '&'
154 %nonassoc "!=" "==" "<=" '<' ">=" '>' // TODO: support "a < b < c" syntax?
155 %nonassoc "is"
156 %left '-'
157 %left '+'
158 %left "<<"
159 %left ">>>"
160 %left ">>"
161 %left '%'
162 %left '/'
163 %left '*'
164 %left '!'
165 %left '~'
166 %left "--" "++"
167 %left '['
168 %nonassoc "as"
169 %left '.' ".." "::"
170 %nonassoc T_IDENTIFIER
171 %left '('
172
173      
174 %{
175
176 static int yyerror(char*s)
177 {
178    syntaxerror("%s", s); 
179 }
180 static token_t* concat2(token_t* t1, token_t* t2)
181 {
182     NEW(token_t,t);
183     int l1 = strlen(t1->text);
184     int l2 = strlen(t2->text);
185     t->text = malloc(l1+l2+1);
186     memcpy(t->text   , t1->text, l1);
187     memcpy(t->text+l1, t2->text, l2);
188     t->text[l1+l2] = 0;
189     return t;
190 }
191 static token_t* concat3(token_t* t1, token_t* t2, token_t* t3)
192 {
193     NEW(token_t,t);
194     int l1 = strlen(t1->text);
195     int l2 = strlen(t2->text);
196     int l3 = strlen(t3->text);
197     t->text = malloc(l1+l2+l3+1);
198     memcpy(t->text   , t1->text, l1);
199     memcpy(t->text+l1, t2->text, l2);
200     memcpy(t->text+l1+l2, t3->text, l3);
201     t->text[l1+l2+l3] = 0;
202     return t;
203 }
204 static char* concat3str(const char* t1, const char* t2, const char* t3)
205 {
206     int l1 = strlen(t1);
207     int l2 = strlen(t2);
208     int l3 = strlen(t3);
209     char*text = malloc(l1+l2+l3+1);
210     memcpy(text   , t1, l1);
211     memcpy(text+l1, t2, l2);
212     memcpy(text+l1+l2, t3, l3);
213     text[l1+l2+l3] = 0;
214     return text;
215 }
216
217 typedef struct _import {
218     char*path;
219 } import_t;
220
221 DECLARE_LIST(import);
222
223 typedef struct _state {
224     abc_file_t*file;
225     abc_script_t*init;
226
227     int level;
228
229     char*package;     
230     char*function;
231     abc_method_body_t*m;
232     import_list_t*imports;
233    
234     /* class data */
235     char*classname;
236     abc_class_t*cls;
237
238     array_t*vars;
239
240 } state_t;
241
242 static state_t* state = 0;
243
244 DECLARE_LIST(state);
245
246 static state_list_t*state_stack=0;
247
248 void initialize_state()
249 {
250     NEW(state_t, s);
251     NEW(state_list_t, sl);
252     state_stack = sl;
253     state = sl->state = s;
254
255     state->file = abc_file_new();
256     state->file->flags &= ~ABCFILE_LAZY;
257     state->level = 0;
258     
259     state->init = abc_initscript(state->file, 0, 0);
260     abc_method_body_t*m = state->init->method->body;
261     __ getlocal_0(m);
262     __ pushscope(m);
263     __ findpropstrict(m, "[package]::trace");
264     __ pushstring(m, "[entering global init function]");
265     __ callpropvoid(m, "[package]::trace", 1);
266 }
267 void* finalize_state()
268 {
269     if(state->level) {
270         syntaxerror("unexpected end of file");
271     }
272     abc_method_body_t*m = state->init->method->body;
273     //__ popscope(m);
274     
275     __ findpropstrict(m, "[package]::trace");
276     __ pushstring(m, "[leaving global init function]");
277     __ callpropvoid(m, "[package]::trace", 1);
278     __ returnvoid(m);
279     return state->file;
280 }
281
282 static void new_state()
283 {
284     NEW(state_t, s);
285     NEW(state_list_t, sl);
286
287     if(state->m) {
288         syntaxerror("not able to start another method scope");
289     }
290
291     memcpy(s, state, sizeof(state_t)); //shallow copy
292     sl->next = state_stack;
293     sl->state = s;
294     state_stack = sl;
295     state = s;
296     state->level++;
297 }
298 static void old_state()
299 {
300     if(!state_stack || !state_stack->next)
301         syntaxerror("invalid nesting");
302     state_t*oldstate = state;
303     state_list_t*old = state_stack;
304     state_stack = state_stack->next;
305     free(old);
306     state = state_stack->state;
307 }
308
309 static void startpackage(token_t*t) 
310 {
311     if(state->package) {
312         syntaxerror("Packages can not be nested."); 
313     } 
314     new_state();
315     char*name = t?t->text:"";
316     printf("entering package \"%s\"\n", name);
317     state->package = name;
318 }
319 static void endpackage()
320 {
321     printf("leaving package \"%s\"\n", state->package);
322     old_state();
323 }
324
325 char*globalclass=0;
326 static void startclass(token_t*modifiers, token_t*name, multiname_t*extends, multiname_list_t*implements)
327 {
328     if(state->cls) {
329         syntaxerror("inner classes now allowed"); 
330     }
331     new_state();
332     state->classname = name->text;
333     printf("entering class %s\n", name->text);
334     token_list_t*t=0;
335     printf("  modifiers: ");for(t=modifiers->tokens;t;t=t->next) printf("%s ", t->token->text);printf("\n");
336     printf("  extends: %s\n", multiname_tostring(extends));
337
338     multiname_list_t*mlist=0;
339     printf("  implements (%d): ", list_length(implements));
340     for(mlist=implements;mlist;mlist=mlist->next)  {
341         printf("%s ", multiname_tostring(mlist->multiname));
342     }
343     printf("\n");
344
345     char public=0,internal=0,final=0,sealed=1;
346     for(t=modifiers->tokens;t;t=t->next) {
347         if(t->token->type == KW_INTERNAL) {
348             /* the programmer is being explicit- 
349                being internal is the default anyway */
350             internal = 1;
351         } else if(t->token->type == KW_PUBLIC) {
352             public = 1;
353         } else if(t->token->type == KW_FINAL) {
354             final = 1;
355         } else {
356             syntaxerror("modifier \"%s\" not supported in class declaration", t->token->text);
357         }
358     }
359     if(public&&internal)
360         syntaxerror("public and internal not supported at the same time.");
361
362     /* create the class name, together with the proper attributes */
363     multiname_t* classname = 0;
364     if(!public && !state->package)
365         classname = multiname_new(namespace_new_private(current_filename), state->classname);
366     else if(!public && state->package)
367         classname = multiname_new(namespace_new_packageinternal(state->package), state->classname);
368     else if(state->package)
369         classname = multiname_new(namespace_new_package(state->package), state->classname);
370     else
371         syntaxerror("public classes only allowed inside a package");
372
373     state->cls = abc_class_new(state->file, classname, extends);
374     if(final) abc_class_final(state->cls);
375     if(sealed) abc_class_sealed(state->cls);
376
377     for(mlist=implements;mlist;mlist=mlist->next) {
378         abc_class_add_interface(state->cls, mlist->multiname);
379     }
380
381     /* now write the construction code for this class */
382     int slotindex = abc_initscript_addClassTrait(state->init, classname, state->cls);
383
384     abc_method_body_t*m = state->init->method->body;
385     __ getglobalscope(m);
386     multiname_t*s = extends;
387
388     int count=0;
389     
390     while(s) {
391         //TODO: take a look at the current scope stack, maybe 
392         //      we can re-use something
393         s = registry_getsuperclass(s);
394         if(!s) 
395         break;
396         __ getlex2(m, s);
397         __ pushscope(m);
398         m->code = m->code->prev->prev; // invert
399         count++;
400     }
401     /* continue appending after last op end */
402     while(m->code && m->code->next) m->code = m->code->next; 
403
404     /* TODO: if this is one of *our* classes, we can also 
405              do a getglobalscope/getslot <nr> (which references
406              the init function's slots) */
407     __ getlex2(m, extends);
408     __ dup(m);
409     __ pushscope(m); // we get a Verify Error #1107 if this is not the top scope
410     __ newclass(m,state->cls);
411     while(count--) {
412         __ popscope(m);
413     }
414     __ setslot(m, slotindex);
415
416     if(!globalclass && public && multiname_equals(registry_getMovieClip(),extends)) {
417         if(state->package && state->package[0]) {
418             globalclass = concat3str(state->package, ".", state->classname);
419         } else {
420             globalclass = strdup(state->classname);
421         }
422     }
423 }
424
425 static void endclass()
426 {
427     printf("leaving class %s\n", state->classname);
428     old_state();
429 }
430 static void addimport(token_t*t)
431 {
432     NEW(import_t,i);
433     i->path = t->text;
434     list_append(state->imports, i);
435 }
436 static void print_imports()
437 {
438     import_list_t*l = state->imports;
439     while(l) {
440         printf("  import %s\n", l->import->path);
441         l = l->next;
442     }
443 }
444 static void startfunction(token_t*ns, token_t*mod, token_t*getset, token_t*name,
445                           token_t*params, multiname_t*type)
446 {
447     token_list_t*t;
448     new_state();
449     state->function = name->text;
450     printf("entering function %s\n", name->text);
451     if(ns)
452         printf("  namespace: %s\n", ns->text);
453     printf("  getset: %s\n", getset->text);
454     printf("  params: ");for(t=params->tokens;t;t=t->next) printf("%s ", t->token->text);printf("\n");
455     printf("  mod: ");for(t=mod->tokens;t;t=t->next) printf("%s ", t->token->text);printf("\n");
456     printf("  type: %s\n", multiname_tostring(type));
457     print_imports();
458
459     if(!strcmp(state->classname,name->text)) {
460         state->m = abc_class_constructor(state->cls, type, 0);
461     } else {
462         state->m = abc_class_method(state->cls, type, name->text, 0);
463     }
464     state->vars = array_new();
465     array_append(state->vars, "this", 0);
466
467     __ getlocal_0(state->m);
468     __ pushscope(state->m);
469 }
470 static void endfunction()
471 {
472     printf("leaving function %s\n", state->function);
473     __ returnvoid(state->m);
474
475     old_state();
476 }
477 static int newvariable(token_t*mod, token_t*varconst, token_t*name, multiname_t*type)
478 {
479     token_list_t*t;
480     printf("defining new variable %s\n", name->text);
481     printf("  mod: ");for(t=mod->tokens;t;t=t->next) printf("%s ", t->token->text);printf("\n");
482     printf("  access: ");printf("%s\n", varconst->text);
483     printf("  type: ");printf("%s\n", multiname_tostring(type));
484
485     if(!state->vars) 
486         syntaxerror("not allowed to defined variables outside a method");
487
488     int index = array_find(state->vars, name->text);
489     if(index>=0) {
490         syntaxerror("Variable %s already defined", name->text);
491     } else {
492         index = array_append(state->vars, name->text, 0);
493     }
494     return index;
495 }
496 static token_t* empty_token()
497 {
498     NEW(token_t,t);
499     t->type=T_EMPTY;
500     t->text=0;
501     return t;
502 }
503
504 void extend(token_t*list, token_t*add) {
505     list_append(list->tokens,add);
506     if(!list->text)
507         list->text = add->text;
508 }
509 void extend_s(token_t*list, char*seperator, token_t*add) {
510     list_append(list->tokens,add);
511     char*t1 = list->text;
512     char*t2 = seperator;
513     char*t3 = add->text;
514     int l1 = strlen(t1);
515     int l2 = strlen(t2);
516     int l3 = strlen(t3);
517     list->text = malloc(l1+l2+l3+1);
518     strcpy(list->text, t1);
519     strcpy(list->text+l1, t2);
520     strcpy(list->text+l1+l2, t3);
521     list->text[l1+l2+l3]=0;
522 }
523
524 %}
525
526 %%
527
528 PROGRAM: MAYBECODE
529
530 MAYBECODE: CODE
531 MAYBECODE: 
532
533 CODE: CODE CODEPIECE2 {$$=$1;}
534 CODE: CODEPIECE2 {$$=empty_token();}
535
536 CODEPIECE2: CODEPIECE {
537     if(state->m) {
538         state->m->code = code_append(state->m->code, $1);
539     }
540 }
541
542 CODEPIECE: ';'                   {/*TODO*/$$=code_new();}
543 CODEPIECE: VARIABLE_DECLARATION  {$$=$1}
544 CODEPIECE: PACKAGE_DECLARATION   {/*TODO*/$$=code_new();}
545 CODEPIECE: IMPORT                {/*TODO*/$$=code_new();}
546 CODEPIECE: NAMESPACE_DECLARATION {/*TODO*/$$=code_new();}
547 CODEPIECE: CLASS_DECLARATION     {/*TODO*/$$=code_new();}
548 CODEPIECE: INTERFACE_DECLARATION {/*TODO*/$$=code_new();}
549 CODEPIECE: FUNCTION_DECLARATION  {/*TODO*/$$=code_new();}
550 CODEPIECE: EXPRESSION            {/*calculate and discard*/$$=$1;$$=abc_pop($$);}
551 CODEPIECE: FOR                   {/*TODO*/$$=code_new();}
552 CODEPIECE: USE                   {/*TODO*/$$=code_new();}
553 CODEPIECE: ASSIGNMENT            {/*TODO*/$$=code_new();}
554
555 PACKAGE_DECLARATION : "package" MULTILEVELIDENTIFIER '{' {startpackage($2)} MAYBECODE '}' {endpackage()}
556 PACKAGE_DECLARATION : "package" '{' {startpackage(0)} MAYBECODE '}' {endpackage()}
557
558 IMPORT : "import" PACKAGESPEC {addimport($2);}
559
560 TYPE : PACKAGEANDCLASS {$$=$1;}
561      | '*'        {$$=registry_getanytype();}
562      |  "String"  {$$=registry_getstringclass();}
563      |  "int"     {$$=registry_getintclass();}
564      |  "uint"    {$$=registry_getuintclass();}
565      |  "Boolean" {$$=registry_getbooleanclass();}
566      |  "Number"  {$$=registry_getnumberclass();}
567
568 MAYBETYPE: ':' TYPE {$$=$2;}
569 MAYBETYPE:          {$$=0;}
570
571 //FUNCTION_HEADER:      NAMESPACE MODIFIERS T_FUNCTION GETSET T_IDENTIFIER '(' PARAMS ')' 
572 FUNCTION_HEADER:      MODIFIERS "function" GETSET T_IDENTIFIER '(' PARAMS ')' 
573                       MAYBETYPE
574 FUNCTION_DECLARATION: MODIFIERS "function" GETSET T_IDENTIFIER '(' PARAMS ')' 
575                       MAYBETYPE '{' {startfunction(0,$1,$3,$4,$6,$8)} MAYBECODE '}' {endfunction()}
576
577 NAMESPACE_DECLARATION : MODIFIERS KW_NAMESPACE T_IDENTIFIER
578 NAMESPACE_DECLARATION : MODIFIERS KW_NAMESPACE T_IDENTIFIER '=' T_IDENTIFIER
579 NAMESPACE_DECLARATION : MODIFIERS KW_NAMESPACE T_IDENTIFIER '=' T_STRING
580
581 //NAMESPACE :              {$$=empty_token();}
582 //NAMESPACE : T_IDENTIFIER {$$=$1};
583
584 CONSTANT : T_BYTE {$$ = abc_pushbyte(0, $1);}
585 CONSTANT : T_SHORT {$$ = abc_pushshort(0, $1);}
586 CONSTANT : T_INT {$$ = abc_pushint(0, $1);}
587 CONSTANT : T_UINT {$$ = abc_pushuint(0, $1);}
588 CONSTANT : T_FLOAT {$$ = abc_pushdouble(0, $1);}
589 CONSTANT : T_STRING {$$ = abc_pushstring(0, $1->text);}
590 CONSTANT : KW_TRUE {$$ = abc_pushtrue(0);}
591 CONSTANT : KW_FALSE {$$ = abc_pushfalse(0);}
592 CONSTANT : KW_NULL {$$ = abc_pushnull(0);}
593
594 VAR : "const" | "var"
595
596 // type annotation
597 // TODO: NAMESPACE
598
599 VARIABLE_DECLARATION : MODIFIERS VAR T_IDENTIFIER MAYBETYPE MAYBEEXPRESSION {
600     int i = newvariable($1,$2,$3,$4);
601     $$=code_new();
602     $$ = $5;
603     $$ = abc_setlocal($$, i);
604 }
605
606 MAYBEEXPRESSION : '=' EXPRESSION {$$=$2;}
607                 |                {$$=code_new();}
608
609 EXPRESSION : E %prec prec_none  {$$ = $1;} //precendence below '-x'
610
611 E : CONSTANT
612 E : VARIABLE %prec T_IDENTIFIER {$$ = abc_pushundefined(0); /* FIXME */}
613 E : NEW                         {$$ = abc_pushundefined(0); /* FIXME */}
614 E : T_REGEXP                    {$$ = abc_pushundefined(0); /* FIXME */}
615 E : FUNCTIONCALL
616 E : E '<' E
617 E : E '>' E
618 E : E "<=" E
619 E : E ">=" E
620 E : E "==" E
621 E : E '+' E
622 E : E '-' E
623 E : E '/' E
624 E : E '%' E
625 E : E '*' E
626 E : E "++"
627 E : E "--"
628 E : E "as" TYPE
629 E : E "is" TYPE
630 E : '(' E ')' {$$=$2;}
631 E : '-' E {$$=$2;}
632
633 NEW : "new" T_IDENTIFIER
634     | "new" T_IDENTIFIER '(' ')'
635     | "new" T_IDENTIFIER '(' EXPRESSION_LIST ')'
636
637 FUNCTIONCALL : T_IDENTIFIER '(' MAYBE_EXPRESSION_LIST ')' {
638         /* TODO: use abc_call (for calling local variables),
639                  abc_callstatic (for calling own methods) */
640         $$ = code_new();
641         $$ = abc_findproperty($$, $1->text);
642         code_list_t*l = $3;
643         // push parameters on stack
644         while(l) {
645             $$ = code_append($$, l->code);
646             l = l->next;
647         }
648         $$ = abc_callproperty($$, $1->text, list_length($3));
649 }
650
651 MAYBE_EXPRESSION_LIST : {}
652 MAYBE_EXPRESSION_LIST : EXPRESSION_LIST
653 EXPRESSION_LIST : EXPRESSION                     {$$=list_new();list_append($$,$1);}
654 EXPRESSION_LIST : EXPRESSION_LIST ',' EXPRESSION {list_append($$,$3);}
655
656 VARIABLE : T_IDENTIFIER
657 VARIABLE : VARIABLE '.' T_IDENTIFIER
658 VARIABLE : VARIABLE ".." T_IDENTIFIER // descendants
659 VARIABLE : VARIABLE "::" VARIABLE // namespace declaration
660 VARIABLE : VARIABLE "::" '[' EXPRESSION ']' // qualified expression
661 VARIABLE : VARIABLE '[' EXPRESSION ']' // unqualified expression
662
663 ASSIGNMENT :           VARIABLE           '=' EXPRESSION
664 NEW_ASSIGNMENT : "var" VARIABLE MAYBETYPE '=' EXPRESSION
665
666 FOR : "for" '(' NEW_ASSIGNMENT ';' EXPRESSION ';' EXPRESSION ')' '{' MAYBECODE '}'
667 FOR : "for" '(' ASSIGNMENT     ';' EXPRESSION ';' EXPRESSION ')' '{' MAYBECODE '}'
668
669 USE : "use" KW_NAMESPACE T_IDENTIFIER
670
671 // keywords which also may be identifiers
672 X_IDENTIFIER : T_IDENTIFIER | KW_PACKAGE
673
674 PACKAGESPEC : PACKAGESPEC '.' PACKAGESPEC {if($1->text[0]=='*') syntaxerror("wildcard in the middle of path");
675                                            $$ = concat3($1,$2,$3);}
676 PACKAGESPEC : X_IDENTIFIER                {$$=$1;}
677 PACKAGESPEC : '*'                         {$$=$1;}
678
679 GETSET : "get" {$$=$1;}
680        | "set" {$$=$1;}
681        |       {$$=empty_token();}
682
683 CLASS_DECLARATION : MODIFIERS "class" T_IDENTIFIER EXTENDS IMPLEMENTS_LIST '{' {startclass($1,$3,$4,$5);} MAYBE_DECLARATION_LIST '}' {endclass();}
684 INTERFACE_DECLARATION : MODIFIERS "interface" T_IDENTIFIER EXTENDS_LIST '{' MAYBE_IDECLARATION_LIST '}'
685
686 PARAMS: {$$=empty_token();}
687 PARAMS: PARAM_LIST {$$=$1;}
688 PARAM_LIST: PARAM_LIST ',' PARAM {extend($1,$3);$$=$1;}
689 PARAM_LIST: PARAM                {$$=empty_token();extend($$,$1);}
690 PARAM:  T_IDENTIFIER ':' TYPE {$$=$1;}
691
692 MODIFIERS : {$$=empty_token();}
693 MODIFIERS : MODIFIER_LIST {$$=$1}
694 MODIFIER_LIST : MODIFIER MODIFIER_LIST {extend($2,$1);$$=$2;}
695 MODIFIER_LIST : MODIFIER               {$$=empty_token();extend($$,$1);}
696 MODIFIER : KW_PUBLIC | KW_PRIVATE | KW_PROTECTED | KW_STATIC | KW_DYNAMIC | KW_FINAL | KW_OVERRIDE | KW_NATIVE | KW_INTERNAL
697
698 DECLARATION : VARIABLE_DECLARATION
699 DECLARATION : FUNCTION_DECLARATION
700
701 IDECLARATION : VARIABLE_DECLARATION
702 IDECLARATION : FUNCTION_DECLARATION
703
704 IMPLEMENTS_LIST : {$$=list_new();}
705 IMPLEMENTS_LIST : KW_IMPLEMENTS PACKAGEANDCLASS_LIST {$$=$2;}
706
707 EXTENDS : {$$=registry_getobjectclass();}
708 EXTENDS : KW_EXTENDS PACKAGEANDCLASS {$$=$2;}
709
710 EXTENDS_LIST : {$$=list_new();}
711 EXTENDS_LIST : KW_EXTENDS PACKAGEANDCLASS_LIST {$$=$2;}
712
713 //IDENTIFIER_LIST : T_IDENTIFIER ',' IDENTIFIER_LIST {extend($3,$1);$$=$3;}
714 //IDENTIFIER_LIST : T_IDENTIFIER                     {$$=empty_token();extend($$,$1);}
715
716 PACKAGEANDCLASS : T_IDENTIFIER {$$ = registry_findclass(state->package, $1->text);}
717 PACKAGEANDCLASS : PACKAGE '.' T_IDENTIFIER {$$ = registry_findclass($1->text, $3->text);}
718 PACKAGE : X_IDENTIFIER
719 PACKAGE : PACKAGE '.' X_IDENTIFIER {$$=$1;extend_s($$,".",$3);}
720
721 MULTILEVELIDENTIFIER : MULTILEVELIDENTIFIER '.' X_IDENTIFIER {$$=$1;extend_s($$, ".", $3)}
722 MULTILEVELIDENTIFIER : T_IDENTIFIER                 {$$=$1;extend($$,$1)};
723
724 PACKAGEANDCLASS_LIST : PACKAGEANDCLASS {$$=list_new();list_append($$, $1);}
725 PACKAGEANDCLASS_LIST : PACKAGEANDCLASS_LIST ',' PACKAGEANDCLASS {$$=$1;list_append($$,$3);}
726
727 MAYBE_DECLARATION_LIST : 
728 MAYBE_DECLARATION_LIST : DECLARATION_LIST
729 DECLARATION_LIST : DECLARATION
730 DECLARATION_LIST : DECLARATION_LIST DECLARATION
731
732 MAYBE_IDECLARATION_LIST : 
733 MAYBE_IDECLARATION_LIST : IDECLARATION_LIST
734 IDECLARATION_LIST : IDECLARATION
735 IDECLARATION_LIST : IDECLARATION_LIST FUNCTION_HEADER
736
737 // chapter 14
738 // 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
739 // syntactic keywords: each get set namespace include dynamic final native override static
740