20 multiname_t*multiname;
21 multiname_list_t*multiname_list;
23 unsigned int number_uint;
26 struct _code_list*code_list;
30 %token<token> T_IDENTIFIER
31 %token<token> T_STRING
32 %token<token> T_REGEXP
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
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"
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"
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 '.'
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
109 %type <code> CONSTANT
112 %type <token> ASSIGNMENT
114 %type <multiname> MAYBETYPE
115 %type <token> PACKAGESPEC
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
130 %type <token> VARIABLE
131 %type <code> VAR_READ
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
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
155 %nonassoc "!=" "==" "<=" '<' ">=" '>' // TODO: support "a < b < c" syntax?
171 %nonassoc T_IDENTIFIER
177 static int yyerror(char*s)
179 syntaxerror("%s", s);
181 static token_t* concat2(token_t* t1, token_t* t2)
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);
192 static token_t* concat3(token_t* t1, token_t* t2, token_t* t3)
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;
205 static char* concat3str(const char* t1, const char* t2, const char* 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);
218 typedef struct _import {
222 DECLARE_LIST(import);
224 typedef struct _state {
233 import_list_t*imports;
243 static state_t* state = 0;
247 static state_list_t*state_stack=0;
249 void initialize_state()
252 NEW(state_list_t, sl);
254 state = sl->state = s;
256 state->file = abc_file_new();
257 state->file->flags &= ~ABCFILE_LAZY;
260 state->init = abc_initscript(state->file, 0, 0);
261 abc_method_body_t*m = state->init->method->body;
264 __ findpropstrict(m, "[package]::trace");
265 __ pushstring(m, "[entering global init function]");
266 __ callpropvoid(m, "[package]::trace", 1);
268 void* finalize_state()
271 syntaxerror("unexpected end of file");
273 abc_method_body_t*m = state->init->method->body;
276 __ findpropstrict(m, "[package]::trace");
277 __ pushstring(m, "[leaving global init function]");
278 __ callpropvoid(m, "[package]::trace", 1);
283 static void new_state()
286 NEW(state_list_t, sl);
289 syntaxerror("not able to start another method scope");
292 memcpy(s, state, sizeof(state_t)); //shallow copy
293 sl->next = state_stack;
299 static void old_state()
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;
307 state = state_stack->state;
310 static void startpackage(token_t*t)
313 syntaxerror("Packages can not be nested.");
316 char*name = t?t->text:"";
317 printf("entering package \"%s\"\n", name);
318 state->package = name;
320 static void endpackage()
322 printf("leaving package \"%s\"\n", state->package);
327 static void startclass(token_t*modifiers, token_t*name, multiname_t*extends, multiname_list_t*implements)
330 syntaxerror("inner classes now allowed");
333 state->classname = name->text;
334 printf("entering class %s\n", name->text);
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));
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));
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 */
352 } else if(t->token->type == KW_PUBLIC) {
354 } else if(t->token->type == KW_FINAL) {
357 syntaxerror("modifier \"%s\" not supported in class declaration", t->token->text);
361 syntaxerror("public and internal not supported at the same time.");
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);
372 syntaxerror("public classes only allowed inside a package");
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);
378 for(mlist=implements;mlist;mlist=mlist->next) {
379 abc_class_add_interface(state->cls, mlist->multiname);
382 /* now write the construction code for this class */
383 int slotindex = abc_initscript_addClassTrait(state->init, classname, state->cls);
385 abc_method_body_t*m = state->init->method->body;
386 __ getglobalscope(m);
387 multiname_t*s = extends;
392 //TODO: take a look at the current scope stack, maybe
393 // we can re-use something
394 s = registry_getsuperclass(s);
399 m->code = m->code->prev->prev; // invert
402 /* continue appending after last op end */
403 while(m->code && m->code->next) m->code = m->code->next;
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);
410 __ pushscope(m); // we get a Verify Error #1107 if this is not the top scope
411 __ newclass(m,state->cls);
415 __ setslot(m, slotindex);
417 if(!globalclass && public && multiname_equals(registry_getMovieClip(),extends)) {
418 if(state->package && state->package[0]) {
419 globalclass = concat3str(state->package, ".", state->classname);
421 globalclass = strdup(state->classname);
426 static void endclass()
428 printf("leaving class %s\n", state->classname);
431 static void addimport(token_t*t)
435 list_append(state->imports, i);
437 static void print_imports()
439 import_list_t*l = state->imports;
441 printf(" import %s\n", l->import->path);
445 static void startfunction(token_t*ns, token_t*mod, token_t*getset, token_t*name,
446 token_t*params, multiname_t*type)
450 state->function = name->text;
451 printf("entering function %s\n", name->text);
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));
460 if(!strcmp(state->classname,name->text)) {
461 state->m = abc_class_constructor(state->cls, type, 0);
463 state->m = abc_class_method(state->cls, type, name->text, 0);
465 state->vars = array_new();
466 array_append(state->vars, "this", 0);
468 __ getlocal_0(state->m);
469 __ pushscope(state->m);
471 static void endfunction()
473 printf("leaving function %s\n", state->function);
474 __ returnvoid(state->m);
478 static int newvariable(token_t*mod, token_t*varconst, token_t*name, multiname_t*type)
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));
487 syntaxerror("not allowed to defined variables outside a method");
489 int index = array_find(state->vars, name->text);
491 syntaxerror("Variable %s already defined", name->text);
493 index = array_append(state->vars, name->text, 0);
497 static token_t* empty_token()
505 void extend(token_t*list, token_t*add) {
506 list_append(list->tokens,add);
508 list->text = add->text;
510 void extend_s(token_t*list, char*seperator, token_t*add) {
511 list_append(list->tokens,add);
512 char*t1 = list->text;
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;
534 CODE: CODE CODEPIECE2 {$$=$1;}
535 CODE: CODEPIECE2 {$$=empty_token();}
537 CODEPIECE2: CODEPIECE {
539 state->m->code = code_append(state->m->code, $1);
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();}
556 PACKAGE_DECLARATION : "package" MULTILEVELIDENTIFIER '{' {startpackage($2)} MAYBECODE '}' {endpackage()}
557 PACKAGE_DECLARATION : "package" '{' {startpackage(0)} MAYBECODE '}' {endpackage()}
559 IMPORT : "import" PACKAGESPEC {addimport($2);}
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();}
569 MAYBETYPE: ':' TYPE {$$=$2;}
572 //FUNCTION_HEADER: NAMESPACE MODIFIERS T_FUNCTION GETSET T_IDENTIFIER '(' PARAMS ')'
573 FUNCTION_HEADER: MODIFIERS "function" GETSET T_IDENTIFIER '(' PARAMS ')'
575 FUNCTION_DECLARATION: MODIFIERS "function" GETSET T_IDENTIFIER '(' PARAMS ')'
576 MAYBETYPE '{' {startfunction(0,$1,$3,$4,$6,$8)} MAYBECODE '}' {endfunction()}
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
582 //NAMESPACE : {$$=empty_token();}
583 //NAMESPACE : T_IDENTIFIER {$$=$1};
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);}
595 VAR : "const" | "var"
600 VARIABLE_DECLARATION : MODIFIERS VAR T_IDENTIFIER MAYBETYPE MAYBEEXPRESSION {
601 int i = newvariable($1,$2,$3,$4);
604 $$ = abc_setlocal($$, i);
607 MAYBEEXPRESSION : '=' EXPRESSION {$$=$2;}
610 EXPRESSION : E %prec prec_none /*precendence below '-x'*/ {$$ = $1;}
613 E : VAR_READ %prec T_IDENTIFIER {$$ = $1;}
614 E : NEW {$$ = abc_pushundefined(0); /* FIXME */}
615 E : T_REGEXP {$$ = abc_pushundefined(0); /* FIXME */}
631 E : '(' E ')' {$$=$2;}
634 NEW : "new" T_IDENTIFIER
635 | "new" T_IDENTIFIER '(' ')'
636 | "new" T_IDENTIFIER '(' EXPRESSION_LIST ')'
638 FUNCTIONCALL : T_IDENTIFIER '(' MAYBE_EXPRESSION_LIST ')' {
639 /* TODO: use abc_call (for calling local variables),
640 abc_callstatic (for calling own methods) */
642 $$ = abc_findproperty($$, $1->text);
644 // push parameters on stack
646 $$ = code_append($$, l->code);
649 $$ = abc_callproperty($$, $1->text, list_length($3));
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);}
657 VAR_READ : T_IDENTIFIER {
658 int i = array_find(state->vars, $1->text);
660 syntaxerror("unknown variable");
661 $$ = abc_getlocal(0, i);
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
670 ASSIGNMENT : VARIABLE '=' EXPRESSION
671 NEW_ASSIGNMENT : "var" VARIABLE MAYBETYPE '=' EXPRESSION
673 FOR : "for" '(' NEW_ASSIGNMENT ';' EXPRESSION ';' EXPRESSION ')' '{' MAYBECODE '}'
674 FOR : "for" '(' ASSIGNMENT ';' EXPRESSION ';' EXPRESSION ')' '{' MAYBECODE '}'
676 USE : "use" KW_NAMESPACE T_IDENTIFIER
678 // keywords which also may be identifiers
679 X_IDENTIFIER : T_IDENTIFIER | KW_PACKAGE
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;}
686 GETSET : "get" {$$=$1;}
688 | {$$=empty_token();}
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 '}'
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;}
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
705 DECLARATION : VARIABLE_DECLARATION
706 DECLARATION : FUNCTION_DECLARATION
708 IDECLARATION : VARIABLE_DECLARATION
709 IDECLARATION : FUNCTION_DECLARATION
711 IMPLEMENTS_LIST : {$$=list_new();}
712 IMPLEMENTS_LIST : KW_IMPLEMENTS PACKAGEANDCLASS_LIST {$$=$2;}
714 EXTENDS : {$$=registry_getobjectclass();}
715 EXTENDS : KW_EXTENDS PACKAGEANDCLASS {$$=$2;}
717 EXTENDS_LIST : {$$=list_new();}
718 EXTENDS_LIST : KW_EXTENDS PACKAGEANDCLASS_LIST {$$=$2;}
720 //IDENTIFIER_LIST : T_IDENTIFIER ',' IDENTIFIER_LIST {extend($3,$1);$$=$3;}
721 //IDENTIFIER_LIST : T_IDENTIFIER {$$=empty_token();extend($$,$1);}
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);}
728 MULTILEVELIDENTIFIER : MULTILEVELIDENTIFIER '.' X_IDENTIFIER {$$=$1;extend_s($$, ".", $3)}
729 MULTILEVELIDENTIFIER : T_IDENTIFIER {$$=$1;extend($$,$1)};
731 PACKAGEANDCLASS_LIST : PACKAGEANDCLASS {$$=list_new();list_append($$, $1);}
732 PACKAGEANDCLASS_LIST : PACKAGEANDCLASS_LIST ',' PACKAGEANDCLASS {$$=$1;list_append($$,$3);}
734 MAYBE_DECLARATION_LIST :
735 MAYBE_DECLARATION_LIST : DECLARATION_LIST
736 DECLARATION_LIST : DECLARATION
737 DECLARATION_LIST : DECLARATION_LIST DECLARATION
739 MAYBE_IDECLARATION_LIST :
740 MAYBE_IDECLARATION_LIST : IDECLARATION_LIST
741 IDECLARATION_LIST : IDECLARATION
742 IDECLARATION_LIST : IDECLARATION_LIST FUNCTION_HEADER
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