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