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