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
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
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
154 %nonassoc "!=" "==" "<=" '<' ">=" '>' // TODO: support "a < b < c" syntax?
170 %nonassoc T_IDENTIFIER
176 static int yyerror(char*s)
178 syntaxerror("%s", s);
180 static token_t* concat2(token_t* t1, token_t* t2)
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);
191 static token_t* concat3(token_t* t1, token_t* t2, token_t* t3)
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;
204 static char* concat3str(const char* t1, const char* t2, const char* 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);
217 typedef struct _import {
221 DECLARE_LIST(import);
223 typedef struct _state {
232 import_list_t*imports;
242 static state_t* state = 0;
246 static state_list_t*state_stack=0;
248 void initialize_state()
251 NEW(state_list_t, sl);
253 state = sl->state = s;
255 state->file = abc_file_new();
256 state->file->flags &= ~ABCFILE_LAZY;
259 state->init = abc_initscript(state->file, 0, 0);
260 abc_method_body_t*m = state->init->method->body;
263 __ findpropstrict(m, "[package]::trace");
264 __ pushstring(m, "[entering global init function]");
265 __ callpropvoid(m, "[package]::trace", 1);
267 void* finalize_state()
270 syntaxerror("unexpected end of file");
272 abc_method_body_t*m = state->init->method->body;
275 __ findpropstrict(m, "[package]::trace");
276 __ pushstring(m, "[leaving global init function]");
277 __ callpropvoid(m, "[package]::trace", 1);
282 static void new_state()
285 NEW(state_list_t, sl);
288 syntaxerror("not able to start another method scope");
291 memcpy(s, state, sizeof(state_t)); //shallow copy
292 sl->next = state_stack;
298 static void old_state()
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;
306 state = state_stack->state;
309 static void startpackage(token_t*t)
312 syntaxerror("Packages can not be nested.");
315 char*name = t?t->text:"";
316 printf("entering package \"%s\"\n", name);
317 state->package = name;
319 static void endpackage()
321 printf("leaving package \"%s\"\n", state->package);
326 static void startclass(token_t*modifiers, token_t*name, multiname_t*extends, multiname_list_t*implements)
329 syntaxerror("inner classes now allowed");
332 state->classname = name->text;
333 printf("entering class %s\n", name->text);
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));
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));
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 */
351 } else if(t->token->type == KW_PUBLIC) {
353 } else if(t->token->type == KW_FINAL) {
356 syntaxerror("modifier \"%s\" not supported in class declaration", t->token->text);
360 syntaxerror("public and internal not supported at the same time.");
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);
371 syntaxerror("public classes only allowed inside a package");
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);
377 for(mlist=implements;mlist;mlist=mlist->next) {
378 abc_class_add_interface(state->cls, mlist->multiname);
381 /* now write the construction code for this class */
382 int slotindex = abc_initscript_addClassTrait(state->init, classname, state->cls);
384 abc_method_body_t*m = state->init->method->body;
385 __ getglobalscope(m);
386 multiname_t*s = extends;
391 //TODO: take a look at the current scope stack, maybe
392 // we can re-use something
393 s = registry_getsuperclass(s);
398 m->code = m->code->prev->prev; // invert
401 /* continue appending after last op end */
402 while(m->code && m->code->next) m->code = m->code->next;
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);
409 __ pushscope(m); // we get a Verify Error #1107 if this is not the top scope
410 __ newclass(m,state->cls);
414 __ setslot(m, slotindex);
416 if(!globalclass && public && multiname_equals(registry_getMovieClip(),extends)) {
417 if(state->package && state->package[0]) {
418 globalclass = concat3str(state->package, ".", state->classname);
420 globalclass = strdup(state->classname);
425 static void endclass()
427 printf("leaving class %s\n", state->classname);
430 static void addimport(token_t*t)
434 list_append(state->imports, i);
436 static void print_imports()
438 import_list_t*l = state->imports;
440 printf(" import %s\n", l->import->path);
444 static void startfunction(token_t*ns, token_t*mod, token_t*getset, token_t*name,
445 token_t*params, multiname_t*type)
449 state->function = name->text;
450 printf("entering function %s\n", name->text);
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));
459 if(!strcmp(state->classname,name->text)) {
460 state->m = abc_class_constructor(state->cls, type, 0);
462 state->m = abc_class_method(state->cls, type, name->text, 0);
464 state->vars = array_new();
465 array_append(state->vars, "this", 0);
467 __ getlocal_0(state->m);
468 __ pushscope(state->m);
470 static void endfunction()
472 printf("leaving function %s\n", state->function);
473 __ returnvoid(state->m);
477 static int newvariable(token_t*mod, token_t*varconst, token_t*name, multiname_t*type)
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));
486 syntaxerror("not allowed to defined variables outside a method");
488 int index = array_find(state->vars, name->text);
490 syntaxerror("Variable %s already defined", name->text);
492 index = array_append(state->vars, name->text, 0);
496 static token_t* empty_token()
504 void extend(token_t*list, token_t*add) {
505 list_append(list->tokens,add);
507 list->text = add->text;
509 void extend_s(token_t*list, char*seperator, token_t*add) {
510 list_append(list->tokens,add);
511 char*t1 = list->text;
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;
533 CODE: CODE CODEPIECE2 {$$=$1;}
534 CODE: CODEPIECE2 {$$=empty_token();}
536 CODEPIECE2: CODEPIECE {
538 state->m->code = code_append(state->m->code, $1);
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();}
555 PACKAGE_DECLARATION : "package" MULTILEVELIDENTIFIER '{' {startpackage($2)} MAYBECODE '}' {endpackage()}
556 PACKAGE_DECLARATION : "package" '{' {startpackage(0)} MAYBECODE '}' {endpackage()}
558 IMPORT : "import" PACKAGESPEC {addimport($2);}
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();}
568 MAYBETYPE: ':' TYPE {$$=$2;}
571 //FUNCTION_HEADER: NAMESPACE MODIFIERS T_FUNCTION GETSET T_IDENTIFIER '(' PARAMS ')'
572 FUNCTION_HEADER: MODIFIERS "function" GETSET T_IDENTIFIER '(' PARAMS ')'
574 FUNCTION_DECLARATION: MODIFIERS "function" GETSET T_IDENTIFIER '(' PARAMS ')'
575 MAYBETYPE '{' {startfunction(0,$1,$3,$4,$6,$8)} MAYBECODE '}' {endfunction()}
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
581 //NAMESPACE : {$$=empty_token();}
582 //NAMESPACE : T_IDENTIFIER {$$=$1};
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);}
594 VAR : "const" | "var"
599 VARIABLE_DECLARATION : MODIFIERS VAR T_IDENTIFIER MAYBETYPE MAYBEEXPRESSION {
600 int i = newvariable($1,$2,$3,$4);
603 $$ = abc_setlocal($$, i);
606 MAYBEEXPRESSION : '=' EXPRESSION {$$=$2;}
609 EXPRESSION : E %prec prec_none {$$ = $1;} //precendence below '-x'
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 */}
630 E : '(' E ')' {$$=$2;}
633 NEW : "new" T_IDENTIFIER
634 | "new" T_IDENTIFIER '(' ')'
635 | "new" T_IDENTIFIER '(' EXPRESSION_LIST ')'
637 FUNCTIONCALL : T_IDENTIFIER '(' MAYBE_EXPRESSION_LIST ')' {
638 /* TODO: use abc_call (for calling local variables),
639 abc_callstatic (for calling own methods) */
641 $$ = abc_findproperty($$, $1->text);
643 // push parameters on stack
645 $$ = code_append($$, l->code);
648 $$ = abc_callproperty($$, $1->text, list_length($3));
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);}
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
663 ASSIGNMENT : VARIABLE '=' EXPRESSION
664 NEW_ASSIGNMENT : "var" VARIABLE MAYBETYPE '=' EXPRESSION
666 FOR : "for" '(' NEW_ASSIGNMENT ';' EXPRESSION ';' EXPRESSION ')' '{' MAYBECODE '}'
667 FOR : "for" '(' ASSIGNMENT ';' EXPRESSION ';' EXPRESSION ')' '{' MAYBECODE '}'
669 USE : "use" KW_NAMESPACE T_IDENTIFIER
671 // keywords which also may be identifiers
672 X_IDENTIFIER : T_IDENTIFIER | KW_PACKAGE
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;}
679 GETSET : "get" {$$=$1;}
681 | {$$=empty_token();}
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 '}'
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;}
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
698 DECLARATION : VARIABLE_DECLARATION
699 DECLARATION : FUNCTION_DECLARATION
701 IDECLARATION : VARIABLE_DECLARATION
702 IDECLARATION : FUNCTION_DECLARATION
704 IMPLEMENTS_LIST : {$$=list_new();}
705 IMPLEMENTS_LIST : KW_IMPLEMENTS PACKAGEANDCLASS_LIST {$$=$2;}
707 EXTENDS : {$$=registry_getobjectclass();}
708 EXTENDS : KW_EXTENDS PACKAGEANDCLASS {$$=$2;}
710 EXTENDS_LIST : {$$=list_new();}
711 EXTENDS_LIST : KW_EXTENDS PACKAGEANDCLASS_LIST {$$=$2;}
713 //IDENTIFIER_LIST : T_IDENTIFIER ',' IDENTIFIER_LIST {extend($3,$1);$$=$3;}
714 //IDENTIFIER_LIST : T_IDENTIFIER {$$=empty_token();extend($$,$1);}
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);}
721 MULTILEVELIDENTIFIER : MULTILEVELIDENTIFIER '.' X_IDENTIFIER {$$=$1;extend_s($$, ".", $3)}
722 MULTILEVELIDENTIFIER : T_IDENTIFIER {$$=$1;extend($$,$1)};
724 PACKAGEANDCLASS_LIST : PACKAGEANDCLASS {$$=list_new();list_append($$, $1);}
725 PACKAGEANDCLASS_LIST : PACKAGEANDCLASS_LIST ',' PACKAGEANDCLASS {$$=$1;list_append($$,$3);}
727 MAYBE_DECLARATION_LIST :
728 MAYBE_DECLARATION_LIST : DECLARATION_LIST
729 DECLARATION_LIST : DECLARATION
730 DECLARATION_LIST : DECLARATION_LIST DECLARATION
732 MAYBE_IDECLARATION_LIST :
733 MAYBE_IDECLARATION_LIST : IDECLARATION_LIST
734 IDECLARATION_LIST : IDECLARATION
735 IDECLARATION_LIST : IDECLARATION_LIST FUNCTION_HEADER
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