3 Routines for compiling Flash2 AVM2 ABC Actionscript
5 Extension module for the rfxswf library.
6 Part of the swftools package.
8 Copyright (c) 2008 Matthias Kramm <kramm@quiss.org>
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.
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.
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 */
30 #include "tokenizer.h"
42 multiname_t*multiname;
43 multiname_list_t*multiname_list;
45 unsigned int number_uint;
48 struct _code_list*code_list;
49 struct _writeable writeable;
54 %token<token> T_IDENTIFIER
55 %token<string> T_STRING
56 %token<token> T_REGEXP
58 %token<number_int> T_INT
59 %token<number_uint> T_UINT
60 %token<number_uint> T_BYTE
61 %token<number_uint> T_SHORT
62 %token<number_float> T_FLOAT
64 %token<token> KW_IMPLEMENTS
65 %token<token> KW_NAMESPACE
66 %token<token> KW_PACKAGE "package"
67 %token<token> KW_PROTECTED
68 %token<token> KW_PUBLIC
69 %token<token> KW_PRIVATE
70 %token<token> KW_USE "use"
71 %token<token> KW_INTERNAL
72 %token<token> KW_NEW "new"
73 %token<token> KW_NATIVE
74 %token<token> KW_FUNCTION "function"
75 %token<token> KW_FOR "for"
76 %token<token> KW_CLASS "class"
77 %token<token> KW_CONST "const"
78 %token<token> KW_SET "set"
79 %token<token> KW_STATIC
80 %token<token> KW_IMPORT "import"
81 %token<token> KW_INTERFACE "interface"
83 %token<token> KW_VAR "var"
84 %token<token> KW_DYNAMIC
85 %token<token> KW_OVERRIDE
86 %token<token> KW_FINAL
87 %token<token> KW_GET "get"
88 %token<token> KW_EXTENDS
89 %token<token> KW_FALSE "false"
90 %token<token> KW_TRUE "true"
91 %token<token> KW_BOOLEAN "Boolean"
92 %token<token> KW_UINT "uint"
93 %token<token> KW_INT "int"
94 %token<token> KW_NUMBER "Number"
95 %token<token> KW_STRING "String"
96 %token<token> KW_IF "if"
97 %token<token> KW_ELSE "else"
98 %token<token> KW_IS "is"
99 %token<token> KW_AS "as"
101 %token<token> T_EQEQ "=="
102 %token<token> T_NE "!="
103 %token<token> T_LE "<="
104 %token<token> T_GE ">="
105 %token<token> T_DIVBY "/="
106 %token<token> T_MODBY "%="
107 %token<token> T_PLUSBY "+="
108 %token<token> T_MINUSBY "-="
109 %token<token> T_SHRBY ">>="
110 %token<token> T_SHLBY "<<="
111 %token<token> T_USHRBY ">>>="
112 %token<token> T_OROR "||"
113 %token<token> T_ANDAND "&&"
114 %token<token> T_COLONCOLON "::"
115 %token<token> T_MINUSMINUS "--"
116 %token<token> T_PLUSPLUS "++"
117 %token<token> T_DOTDOT ".."
118 %token<token> T_SHL "<<"
119 %token<token> T_USHR ">>>"
120 %token<token> T_SHR ">>"
121 %token<token> T_SEMICOLON ';'
122 %token<token> T_STAR '*'
123 %token<token> T_DOT '.'
126 %type <code> CODEPIECE CODEPIECE2
127 %type <code> CODEBLOCK MAYBECODE
128 %type <token> PACKAGE_DECLARATION
129 %type <token> FUNCTION_DECLARATION
130 %type <code> VARIABLE_DECLARATION
131 %type <token> CLASS_DECLARATION
132 %type <token> NAMESPACE_DECLARATION
133 %type <token> INTERFACE_DECLARATION
134 %type <code> EXPRESSION
135 %type <code> MAYBEEXPRESSION
138 %type <code> CONSTANT
139 %type <code> FOR IF MAYBEELSE
141 %type <code> ASSIGNMENT NEW_ASSIGNMENT SOME_ASSIGNMENT
143 %type <multiname> MAYBETYPE
144 %type <token> PACKAGESPEC
148 %type <token> PARAM_LIST
149 %type <token> MODIFIERS
150 %type <token> MODIFIER_LIST
151 %type <multiname_list> IMPLEMENTS_LIST
152 %type <multiname> EXTENDS
153 %type <multiname_list> EXTENDS_LIST
154 %type <multiname> PACKAGEANDCLASS
155 %type <multiname_list> PACKAGEANDCLASS_LIST
156 %type <token> MULTILEVELIDENTIFIER
157 %type <multiname> TYPE
159 //%type <token> VARIABLE
160 %type <code> VAR_READ
162 %type <token> X_IDENTIFIER
163 %type <token> MODIFIER
164 %type <token> PACKAGE
165 %type <code> FUNCTIONCALL
166 %type <code_list> MAYBE_EXPRESSION_LIST EXPRESSION_LIST
168 // precendence: from low to high
169 // http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000012.html
184 %nonassoc "!=" "==" "<=" '<' ">=" '>' // TODO: support "a < b < c" syntax?
200 %nonassoc T_IDENTIFIER
209 static int yyerror(char*s)
211 syntaxerror("%s", s);
213 static token_t* concat2(token_t* t1, token_t* t2)
216 int l1 = strlen(t1->text);
217 int l2 = strlen(t2->text);
218 t->text = malloc(l1+l2+1);
219 memcpy(t->text , t1->text, l1);
220 memcpy(t->text+l1, t2->text, l2);
224 static token_t* concat3(token_t* t1, token_t* t2, token_t* t3)
227 int l1 = strlen(t1->text);
228 int l2 = strlen(t2->text);
229 int l3 = strlen(t3->text);
230 t->text = malloc(l1+l2+l3+1);
231 memcpy(t->text , t1->text, l1);
232 memcpy(t->text+l1, t2->text, l2);
233 memcpy(t->text+l1+l2, t3->text, l3);
234 t->text[l1+l2+l3] = 0;
237 static char* concat3str(const char* t1, const char* t2, const char* t3)
242 char*text = malloc(l1+l2+l3+1);
243 memcpy(text , t1, l1);
244 memcpy(text+l1, t2, l2);
245 memcpy(text+l1+l2, t3, l3);
250 typedef struct _import {
254 DECLARE_LIST(import);
256 typedef struct _state {
265 import_list_t*imports;
275 static state_t* state = 0;
279 static state_list_t*state_stack=0;
281 void initialize_state()
284 NEW(state_list_t, sl);
286 state = sl->state = s;
288 state->file = abc_file_new();
289 state->file->flags &= ~ABCFILE_LAZY;
292 state->init = abc_initscript(state->file, 0, 0);
293 abc_method_body_t*m = state->init->method->body;
296 __ findpropstrict(m, "[package]::trace");
297 __ pushstring(m, "[entering global init function]");
298 __ callpropvoid(m, "[package]::trace", 1);
300 void* finalize_state()
303 syntaxerror("unexpected end of file");
305 abc_method_body_t*m = state->init->method->body;
308 __ findpropstrict(m, "[package]::trace");
309 __ pushstring(m, "[leaving global init function]");
310 __ callpropvoid(m, "[package]::trace", 1);
315 static void new_state()
318 NEW(state_list_t, sl);
321 syntaxerror("not able to start another method scope");
324 memcpy(s, state, sizeof(state_t)); //shallow copy
325 sl->next = state_stack;
331 static void old_state()
333 if(!state_stack || !state_stack->next)
334 syntaxerror("invalid nesting");
335 state_t*oldstate = state;
336 state_list_t*old = state_stack;
337 state_stack = state_stack->next;
339 state = state_stack->state;
342 static void startpackage(token_t*t)
345 syntaxerror("Packages can not be nested.");
348 char*name = t?t->text:"";
349 printf("entering package \"%s\"\n", name);
350 state->package = name;
352 static void endpackage()
354 printf("leaving package \"%s\"\n", state->package);
359 static void startclass(token_t*modifiers, token_t*name, multiname_t*extends, multiname_list_t*implements)
362 syntaxerror("inner classes now allowed");
365 state->classname = name->text;
366 printf("entering class %s\n", name->text);
368 printf(" modifiers: ");for(t=modifiers->tokens;t;t=t->next) printf("%s ", t->token->text);printf("\n");
369 printf(" extends: %s\n", multiname_tostring(extends));
371 multiname_list_t*mlist=0;
372 printf(" implements (%d): ", list_length(implements));
373 for(mlist=implements;mlist;mlist=mlist->next) {
374 printf("%s ", multiname_tostring(mlist->multiname));
378 char public=0,internal=0,final=0,sealed=1;
379 for(t=modifiers->tokens;t;t=t->next) {
380 if(t->token->type == KW_INTERNAL) {
381 /* the programmer is being explicit-
382 being internal is the default anyway */
384 } else if(t->token->type == KW_PUBLIC) {
386 } else if(t->token->type == KW_FINAL) {
389 syntaxerror("modifier \"%s\" not supported in class declaration", t->token->text);
393 syntaxerror("public and internal not supported at the same time.");
395 /* create the class name, together with the proper attributes */
396 multiname_t* classname = 0;
397 if(!public && !state->package)
398 classname = multiname_new(namespace_new_private(current_filename), state->classname);
399 else if(!public && state->package)
400 classname = multiname_new(namespace_new_packageinternal(state->package), state->classname);
401 else if(state->package)
402 classname = multiname_new(namespace_new_package(state->package), state->classname);
404 syntaxerror("public classes only allowed inside a package");
406 state->cls = abc_class_new(state->file, classname, extends);
407 if(final) abc_class_final(state->cls);
408 if(sealed) abc_class_sealed(state->cls);
410 for(mlist=implements;mlist;mlist=mlist->next) {
411 abc_class_add_interface(state->cls, mlist->multiname);
414 /* now write the construction code for this class */
415 int slotindex = abc_initscript_addClassTrait(state->init, classname, state->cls);
417 abc_method_body_t*m = state->init->method->body;
418 __ getglobalscope(m);
419 multiname_t*s = extends;
424 //TODO: take a look at the current scope stack, maybe
425 // we can re-use something
426 s = registry_getsuperclass(s);
431 m->code = m->code->prev->prev; // invert
434 /* continue appending after last op end */
435 while(m->code && m->code->next) m->code = m->code->next;
437 /* TODO: if this is one of *our* classes, we can also
438 do a getglobalscope/getslot <nr> (which references
439 the init function's slots) */
440 __ getlex2(m, extends);
442 __ pushscope(m); // we get a Verify Error #1107 if this is not the top scope
443 __ newclass(m,state->cls);
447 __ setslot(m, slotindex);
449 if(!globalclass && public && multiname_equals(registry_getMovieClip(),extends)) {
450 if(state->package && state->package[0]) {
451 globalclass = concat3str(state->package, ".", state->classname);
453 globalclass = strdup(state->classname);
458 static void endclass()
460 printf("leaving class %s\n", state->classname);
463 static void addimport(token_t*t)
467 list_append(state->imports, i);
469 static void print_imports()
471 import_list_t*l = state->imports;
473 printf(" import %s\n", l->import->path);
477 static void startfunction(token_t*ns, token_t*mod, token_t*getset, token_t*name,
478 token_t*params, multiname_t*type)
482 state->function = name->text;
483 printf("entering function %s\n", name->text);
485 printf(" namespace: %s\n", ns->text);
486 printf(" getset: %s\n", getset->text);
487 printf(" params: ");for(t=params->tokens;t;t=t->next) printf("%s ", t->token->text);printf("\n");
488 printf(" mod: ");for(t=mod->tokens;t;t=t->next) printf("%s ", t->token->text);printf("\n");
489 printf(" type: %s\n", multiname_tostring(type));
492 if(!strcmp(state->classname,name->text)) {
493 state->m = abc_class_constructor(state->cls, type, 0);
495 state->m = abc_class_method(state->cls, type, name->text, 0);
497 state->vars = array_new();
498 array_append(state->vars, "this", 0);
500 __ getlocal_0(state->m);
501 __ pushscope(state->m);
503 static void endfunction()
505 printf("leaving function %s\n", state->function);
506 __ returnvoid(state->m);
510 static int newvariable(token_t*mod, token_t*varconst, token_t*name, multiname_t*type)
513 printf("defining new variable %s\n", name->text);
515 printf(" mod: ");for(t=mod->tokens;t;t=t->next) printf("%s ", t->token->text);printf("\n");
518 printf(" access: ");printf("%s\n", varconst->text);
520 printf(" type: ");printf("%s\n", multiname_tostring(type));
523 syntaxerror("not allowed to defined variables outside a method");
525 int index = array_find(state->vars, name->text);
527 syntaxerror("Variable %s already defined", name->text);
529 index = array_append(state->vars, name->text, 0);
533 static token_t* empty_token()
541 void extend(token_t*list, token_t*add) {
542 list_append(list->tokens,add);
544 list->text = add->text;
546 void extend_s(token_t*list, char*seperator, token_t*add) {
547 list_append(list->tokens,add);
548 char*t1 = list->text;
554 list->text = malloc(l1+l2+l3+1);
555 strcpy(list->text, t1);
556 strcpy(list->text+l1, t2);
557 strcpy(list->text+l1+l2, t3);
558 list->text[l1+l2+l3]=0;
567 MAYBECODE: CODE {$$=$1;}
568 MAYBECODE: {$$=code_new();}
570 CODE: CODE CODEPIECE2 {$$=$1;}
571 CODE: CODEPIECE2 {$$=code_new();}
573 CODEPIECE2: CODEPIECE {
575 state->m->code = code_append(state->m->code, $1);
579 CODEPIECE: ';' {$$=code_new();}
580 CODEPIECE: VARIABLE_DECLARATION {$$=$1}
581 CODEPIECE: PACKAGE_DECLARATION {/*TODO*/$$=code_new();}
582 CODEPIECE: IMPORT {/*TODO*/$$=code_new();}
583 CODEPIECE: NAMESPACE_DECLARATION {/*TODO*/$$=code_new();}
584 CODEPIECE: CLASS_DECLARATION {/*TODO*/$$=code_new();}
585 CODEPIECE: INTERFACE_DECLARATION {/*TODO*/$$=code_new();}
586 CODEPIECE: FUNCTION_DECLARATION {/*TODO*/$$=code_new();}
587 CODEPIECE: EXPRESSION {/*calculate and discard*/$$=$1;$$=abc_pop($$);}
588 CODEPIECE: FOR {$$=$1}
589 CODEPIECE: IF {$$=$1}
590 CODEPIECE: USE {/*TODO*/$$=code_new();}
591 CODEPIECE: ASSIGNMENT {/*TODO*/$$=code_new();}
593 CODEBLOCK : '{' MAYBECODE '}' {$$=$2;}
594 CODEBLOCK : CODEPIECE {$$=$1;}
596 PACKAGE_DECLARATION : "package" MULTILEVELIDENTIFIER '{' {startpackage($2)} MAYBECODE '}' {endpackage()}
597 PACKAGE_DECLARATION : "package" '{' {startpackage(0)} MAYBECODE '}' {endpackage()}
599 IMPORT : "import" PACKAGESPEC {addimport($2);}
601 TYPE : PACKAGEANDCLASS {$$=$1;}
602 | '*' {$$=registry_getanytype();}
603 | "String" {$$=registry_getstringclass();}
604 | "int" {$$=registry_getintclass();}
605 | "uint" {$$=registry_getuintclass();}
606 | "Boolean" {$$=registry_getbooleanclass();}
607 | "Number" {$$=registry_getnumberclass();}
609 MAYBETYPE: ':' TYPE {$$=$2;}
612 //FUNCTION_HEADER: NAMESPACE MODIFIERS T_FUNCTION GETSET T_IDENTIFIER '(' PARAMS ')'
613 FUNCTION_HEADER: MODIFIERS "function" GETSET T_IDENTIFIER '(' PARAMS ')'
615 FUNCTION_DECLARATION: MODIFIERS "function" GETSET T_IDENTIFIER '(' PARAMS ')'
616 MAYBETYPE '{' {startfunction(0,$1,$3,$4,$6,$8)} MAYBECODE '}' {endfunction()}
618 NAMESPACE_DECLARATION : MODIFIERS KW_NAMESPACE T_IDENTIFIER
619 NAMESPACE_DECLARATION : MODIFIERS KW_NAMESPACE T_IDENTIFIER '=' T_IDENTIFIER
620 NAMESPACE_DECLARATION : MODIFIERS KW_NAMESPACE T_IDENTIFIER '=' T_STRING
622 //NAMESPACE : {$$=empty_token();}
623 //NAMESPACE : T_IDENTIFIER {$$=$1};
625 CONSTANT : T_BYTE {$$ = abc_pushbyte(0, $1);$$=abc_coerce2($$,registry_getnumberclass());}
626 CONSTANT : T_SHORT {$$ = abc_pushshort(0, $1);}
627 CONSTANT : T_INT {$$ = abc_pushint(0, $1);}
628 CONSTANT : T_UINT {$$ = abc_pushuint(0, $1);}
629 CONSTANT : T_FLOAT {$$ = abc_pushdouble(0, $1);}
630 CONSTANT : T_STRING {$$ = abc_pushstring(0, $1);}
631 CONSTANT : KW_TRUE {$$ = abc_pushtrue(0);}
632 CONSTANT : KW_FALSE {$$ = abc_pushfalse(0);}
633 CONSTANT : KW_NULL {$$ = abc_pushnull(0);}
635 VAR : "const" | "var"
640 VARIABLE_DECLARATION : MODIFIERS VAR T_IDENTIFIER MAYBETYPE MAYBEEXPRESSION {
641 int i = newvariable($1,$2,$3,$4);
643 $$ = abc_setlocal($$, i);
646 NEW_ASSIGNMENT : "var" T_IDENTIFIER MAYBETYPE '=' EXPRESSION {
647 int i = newvariable(0,0,$2,$3);
649 $$ = abc_setlocal($$, i);
651 ASSIGNMENT : T_IDENTIFIER '=' EXPRESSION {
652 int i = array_find(state->vars, $1->text);
654 syntaxerror("Unknown variable '%s'", $1->text);
657 $$ = abc_setlocal($$, i);
659 SOME_ASSIGNMENT : ASSIGNMENT | NEW_ASSIGNMENT
661 FOR : "for" '(' SOME_ASSIGNMENT ';' EXPRESSION ';' EXPRESSION ')' '{' MAYBECODE '}' {
663 code_t*loopstart = $$ = abc_label($$);
664 $$ = code_append($$, $5);
665 code_t*myif = $$ = abc_iffalse($$, 0);
666 $$ = code_append($$, $10);
667 $$ = code_append($$, $7);$$=abc_pop($$);
668 $$ = abc_jump($$, loopstart);
672 MAYBEELSE: %prec prec_none {$$ = code_new();}
673 MAYBEELSE: "else" CODEBLOCK {$$=$2;}
674 MAYBEELSE: ';' "else" CODEBLOCK {$$=$3;}
676 IF : "if" '(' EXPRESSION ')' CODEBLOCK MAYBEELSE {
678 code_t*myjmp,*myif = $$ = abc_iffalse($$, 0);
679 $$ = code_append($$, $5);
681 myjmp = $$ = abc_jump($$, 0);
683 myif->branch = $$ = abc_label($$);
685 $$ = code_append($$, $6);
686 myjmp->branch = $$ = abc_label($$);
690 USE : "use" KW_NAMESPACE T_IDENTIFIER
693 MAYBEEXPRESSION : '=' EXPRESSION {$$=$2;}
696 EXPRESSION : E %prec prec_none /*precendence below '-x'*/ {$$ = $1;}
699 E : VAR_READ %prec T_IDENTIFIER {$$ = $1;}
700 E : NEW {$$ = abc_pushundefined(0); /* FIXME */}
701 E : T_REGEXP {$$ = abc_pushundefined(0); /* FIXME */}
703 E : E '<' E {$$ = code_append($1,$3);$$ = abc_greaterequals($$);$$=abc_not($$);}
704 E : E '>' E {$$ = code_append($1,$3);$$ = abc_greaterthan($$);}
705 E : E "<=" E {$$ = code_append($1,$3);$$ = abc_greaterthan($$);$$=abc_not($$);}
706 E : E ">=" E {$$ = code_append($1,$3);$$ = abc_greaterequals($$);}
707 E : E "==" E {$$ = code_append($1,$3);$$ = abc_equals($$);}
708 E : E "!=" E {$$ = code_append($1,$3);$$ = abc_equals($$);$$ = abc_not($$);}
709 E : E '+' E {$$ = code_append($1,$3);$$ = abc_add($$);}
716 E : '(' E ')' {$$=$2;}
719 // TODO: use inclocal where appropriate
720 E : LH "++" {$$ = $1.read;$$=abc_increment($$);$$=abc_dup($$);$$=code_append($$,$1.write);}
721 E : LH "--" {$$ = $1.read;$$=abc_decrement($$);$$=abc_dup($$);$$=code_append($$,$1.write);}
724 int i = array_find(state->vars, $1->text);
725 if(i<0) syntaxerror("unknown variable '%s'", $1->text);
726 $$.read = abc_getlocal(0, i);
727 $$.write = abc_setlocal(0, i);
730 NEW : "new" T_IDENTIFIER
731 | "new" T_IDENTIFIER '(' ')'
732 | "new" T_IDENTIFIER '(' EXPRESSION_LIST ')'
734 FUNCTIONCALL : T_IDENTIFIER '(' MAYBE_EXPRESSION_LIST ')' {
735 /* TODO: use abc_call (for calling local variables),
736 abc_callstatic (for calling own methods) */
738 $$ = abc_findproperty($$, $1->text);
740 // push parameters on stack
742 $$ = code_append($$, l->code);
745 $$ = abc_callproperty($$, $1->text, list_length($3));
748 MAYBE_EXPRESSION_LIST : {}
749 MAYBE_EXPRESSION_LIST : EXPRESSION_LIST
750 EXPRESSION_LIST : EXPRESSION {$$=list_new();list_append($$,$1);}
751 EXPRESSION_LIST : EXPRESSION_LIST ',' EXPRESSION {list_append($$,$3);}
753 VAR_READ : T_IDENTIFIER {
754 int i = array_find(state->vars, $1->text);
756 syntaxerror("unknown variable '%s'", $1->text);
757 $$ = abc_getlocal(0, i);
760 //VARIABLE : T_IDENTIFIER
761 //VARIABLE : VARIABLE '.' T_IDENTIFIER
762 //VARIABLE : VARIABLE ".." T_IDENTIFIER // descendants
763 //VARIABLE : VARIABLE "::" VARIABLE // namespace declaration
764 //VARIABLE : VARIABLE "::" '[' EXPRESSION ']' // qualified expression
765 //VARIABLE : VARIABLE '[' EXPRESSION ']' // unqualified expression
767 // keywords which also may be identifiers
768 X_IDENTIFIER : T_IDENTIFIER | KW_PACKAGE
770 PACKAGESPEC : PACKAGESPEC '.' PACKAGESPEC {if($1->text[0]=='*') syntaxerror("wildcard in the middle of path");
771 $$ = concat3($1,$2,$3);}
772 PACKAGESPEC : X_IDENTIFIER {$$=$1;}
773 PACKAGESPEC : '*' {$$=$1;}
775 GETSET : "get" {$$=$1;}
777 | {$$=empty_token();}
779 CLASS_DECLARATION : MODIFIERS "class" T_IDENTIFIER EXTENDS IMPLEMENTS_LIST '{' {startclass($1,$3,$4,$5);} MAYBE_DECLARATION_LIST '}' {endclass();}
780 INTERFACE_DECLARATION : MODIFIERS "interface" T_IDENTIFIER EXTENDS_LIST '{' MAYBE_IDECLARATION_LIST '}'
782 PARAMS: {$$=empty_token();}
783 PARAMS: PARAM_LIST {$$=$1;}
784 PARAM_LIST: PARAM_LIST ',' PARAM {extend($1,$3);$$=$1;}
785 PARAM_LIST: PARAM {$$=empty_token();extend($$,$1);}
786 PARAM: T_IDENTIFIER ':' TYPE {$$=$1;}
788 MODIFIERS : {$$=empty_token();}
789 MODIFIERS : MODIFIER_LIST {$$=$1}
790 MODIFIER_LIST : MODIFIER MODIFIER_LIST {extend($2,$1);$$=$2;}
791 MODIFIER_LIST : MODIFIER {$$=empty_token();extend($$,$1);}
792 MODIFIER : KW_PUBLIC | KW_PRIVATE | KW_PROTECTED | KW_STATIC | KW_DYNAMIC | KW_FINAL | KW_OVERRIDE | KW_NATIVE | KW_INTERNAL
794 DECLARATION : VARIABLE_DECLARATION
795 DECLARATION : FUNCTION_DECLARATION
797 IDECLARATION : VARIABLE_DECLARATION
798 IDECLARATION : FUNCTION_DECLARATION
800 IMPLEMENTS_LIST : {$$=list_new();}
801 IMPLEMENTS_LIST : KW_IMPLEMENTS PACKAGEANDCLASS_LIST {$$=$2;}
803 EXTENDS : {$$=registry_getobjectclass();}
804 EXTENDS : KW_EXTENDS PACKAGEANDCLASS {$$=$2;}
806 EXTENDS_LIST : {$$=list_new();}
807 EXTENDS_LIST : KW_EXTENDS PACKAGEANDCLASS_LIST {$$=$2;}
809 //IDENTIFIER_LIST : T_IDENTIFIER ',' IDENTIFIER_LIST {extend($3,$1);$$=$3;}
810 //IDENTIFIER_LIST : T_IDENTIFIER {$$=empty_token();extend($$,$1);}
812 PACKAGEANDCLASS : T_IDENTIFIER {$$ = registry_findclass(state->package, $1->text);}
813 PACKAGEANDCLASS : PACKAGE '.' T_IDENTIFIER {$$ = registry_findclass($1->text, $3->text);}
814 PACKAGE : X_IDENTIFIER
815 PACKAGE : PACKAGE '.' X_IDENTIFIER {$$=$1;extend_s($$,".",$3);}
817 MULTILEVELIDENTIFIER : MULTILEVELIDENTIFIER '.' X_IDENTIFIER {$$=$1;extend_s($$, ".", $3)}
818 MULTILEVELIDENTIFIER : T_IDENTIFIER {$$=$1;extend($$,$1)};
820 PACKAGEANDCLASS_LIST : PACKAGEANDCLASS {$$=list_new();list_append($$, $1);}
821 PACKAGEANDCLASS_LIST : PACKAGEANDCLASS_LIST ',' PACKAGEANDCLASS {$$=$1;list_append($$,$3);}
823 MAYBE_DECLARATION_LIST :
824 MAYBE_DECLARATION_LIST : DECLARATION_LIST
825 DECLARATION_LIST : DECLARATION
826 DECLARATION_LIST : DECLARATION_LIST DECLARATION
828 MAYBE_IDECLARATION_LIST :
829 MAYBE_IDECLARATION_LIST : IDECLARATION_LIST
830 IDECLARATION_LIST : IDECLARATION
831 IDECLARATION_LIST : IDECLARATION_LIST FUNCTION_HEADER
834 // 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
835 // syntactic keywords: each get set namespace include dynamic final native override static