18 multiname_t*multiname;
19 multiname_list_t*multiname_list;
23 %token<token> T_IDENTIFIER
24 %token<token> T_STRING
25 %token<token> T_REGEXP
26 %token<token> T_IMPLEMENTS
27 %token<token> T_NAMESPACE
28 %token<token> T_PACKAGE
29 %token<token> T_PROTECTED
30 %token<token> T_PUBLIC
31 %token<token> T_PRIVATE
34 %token<token> T_INTERNAL
37 %token<token> T_NATIVE
38 %token<token> T_FUNCTION
43 %token<token> T_STATIC
44 %token<token> T_IMPORT
45 %token<token> T_INTERFACE
46 %token<token> T_NUMBER
50 %token<token> T_BOOLEAN
52 %token<token> T_DYNAMIC
53 %token<token> T_OVERRIDE
56 %token<token> T_EXTENDS
58 %token<token> T_EQEQ "=="
59 %token<token> T_LE "<="
60 %token<token> T_GE ">="
61 %token<token> T_DIVBY "/="
62 %token<token> T_MODBY "%="
63 %token<token> T_PLUSBY "+="
64 %token<token> T_MINUSBY "-="
65 %token<token> T_SHRBY ">>="
66 %token<token> T_SHLBY "<<="
67 %token<token> T_USHRBY ">>>="
68 %token<token> T_OROR "||"
69 %token<token> T_ANDAND "&&"
70 %token<token> T_COLONCOLON "::"
71 %token<token> T_MINUSMINUS "--"
72 %token<token> T_PLUSPLUS "++"
73 %token<token> T_DOTDOT ".."
74 %token<token> T_SHL "<<"
75 %token<token> T_USHR ">>>"
76 %token<token> T_SHR ">>"
77 %token<token> T_IS "is"
78 %token<token> T_AS "as"
79 %token<token> T_SEMICOLON ';'
80 %token<token> T_STAR '*'
81 %token<token> T_DOT '.'
83 // precendence: from low to high
84 // http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000012.html
98 %nonassoc "!=" "==" "<=" '<' ">=" '>' // TODO: support "a < b < c" syntax?
117 %type <token> CODEPIECE
118 %type <token> PACKAGE_DECLARATION
119 %type <token> FUNCTION_DECLARATION
120 %type <token> VARIABLE_DECLARATION
121 %type <token> CLASS_DECLARATION
122 %type <token> NAMESPACE_DECLARATION
123 %type <token> INTERFACE_DECLARATION
124 %type <token> EXPRESSION
126 %type <token> CONSTANT
129 %type <token> ASSIGNMENT
131 %type <multiname> MAYBETYPE
132 %type <token> PACKAGESPEC
136 %type <token> PARAM_LIST
137 %type <token> MODIFIERS
138 %type <token> MODIFIER_LIST
139 %type <multiname_list> IMPLEMENTS_LIST
140 %type <multiname> EXTENDS
141 %type <multiname_list> EXTENDS_LIST
142 %type <multiname> PACKAGEANDCLASS
143 %type <multiname_list> PACKAGEANDCLASS_LIST
144 %type <token> MULTILEVELIDENTIFIER
145 %type <multiname> TYPE
147 %type <token> VARIABLE
149 %type <token> FUNCTIONCALL
150 %type <token> X_IDENTIFIER
151 %type <token> MODIFIER
152 %type <token> PACKAGE
157 static int yyerror(char*s)
159 syntaxerror("%s", s);
161 static token_t* concat2(token_t* t1, token_t* t2)
164 int l1 = strlen(t1->text);
165 int l2 = strlen(t2->text);
166 t->text = malloc(l1+l2+1);
167 memcpy(t->text , t1->text, l1);
168 memcpy(t->text+l1, t2->text, l2);
172 static token_t* concat3(token_t* t1, token_t* t2, token_t* t3)
175 int l1 = strlen(t1->text);
176 int l2 = strlen(t2->text);
177 int l3 = strlen(t3->text);
178 t->text = malloc(l1+l2+l3+1);
179 memcpy(t->text , t1->text, l1);
180 memcpy(t->text+l1, t2->text, l2);
181 memcpy(t->text+l1+l2, t3->text, l3);
182 t->text[l1+l2+l3] = 0;
186 typedef struct _import {
190 DECLARE_LIST(import);
192 typedef struct _state {
200 import_list_t*imports;
208 static state_t* state = 0;
212 static state_list_t*state_stack=0;
214 void initialize_state()
217 NEW(state_list_t, sl);
219 state = sl->state = s;
221 state->file = abc_file_new();
224 state->init = abc_initscript(state->file, 0, 0);
225 abc_method_body_t*m = state->init->method->body;
229 void* finalize_state()
232 syntaxerror("unexpected end of file");
234 abc_method_body_t*m = state->init->method->body;
240 static void new_state()
243 NEW(state_list_t, sl);
244 memcpy(s, state, sizeof(state_t)); //shallow copy
245 sl->next = state_stack;
251 static void old_state()
253 if(!state_stack || !state_stack->next)
254 syntaxerror("invalid nesting");
255 state_t*oldstate = state;
256 state_list_t*old = state_stack;
257 state_stack = state_stack->next;
259 state = state_stack->state;
262 static void startpackage(token_t*t)
265 syntaxerror("Packages can not be nested.");
268 char*name = t?t->text:"";
269 printf("entering package \"%s\"\n", name);
270 state->package = name;
272 static void endpackage()
274 printf("leaving package \"%s\"\n", state->package);
278 static void startclass(token_t*modifiers, token_t*name, multiname_t*extends, multiname_list_t*implements)
281 syntaxerror("inner classes now allowed");
284 state->classname = name->text;
285 printf("entering class %s\n", name->text);
287 printf(" modifiers: ");for(t=modifiers->tokens;t;t=t->next) printf("%s ", t->token->text);printf("\n");
288 printf(" extends: %s\n", multiname_tostring(extends));
290 multiname_list_t*mlist=0;
291 printf(" implements (%d): ", list_length(implements));
292 for(mlist=implements;mlist;mlist=mlist->next) {
293 printf("%s ", multiname_tostring(mlist->multiname));
297 char public=0,internal=0,final=0,sealed=1;
298 for(t=modifiers->tokens;t;t=t->next) {
299 if(t->token->type == T_INTERNAL) {
300 /* the programmer is being explicit-
301 being internal is the default anyway */
303 } else if(t->token->type == T_PUBLIC) {
305 } else if(t->token->type == T_FINAL) {
308 syntaxerror("modifier \"%s\" not supported in class declaration", t->token->text);
312 syntaxerror("public and internal not supported at the same time.");
314 /* create the class name, together with the proper attributes */
315 multiname_t* classname = 0;
316 if(!public && !state->package)
317 classname = multiname_new(namespace_new_private(current_filename), state->classname);
318 else if(!public && state->package)
319 classname = multiname_new(namespace_new_packageinternal(state->package), state->classname);
320 else if(state->package)
321 classname = multiname_new(namespace_new_package(state->package), state->classname);
323 syntaxerror("public classes only allowed inside a package");
325 state->cls = abc_class_new(state->file, classname, extends);
326 if(final) abc_class_final(state->cls);
327 if(sealed) abc_class_sealed(state->cls);
329 for(mlist=implements;mlist;mlist=mlist->next) {
330 abc_class_add_interface(state->cls, mlist->multiname);
333 /* now write the construction code for this class */
334 int slotindex = abc_initscript_addClassTrait(state->init, classname, state->cls);
336 abc_method_body_t*m = state->init->method->body;
337 __ getglobalscope(m);
338 multiname_t*s = extends;
342 //TODO: take a look at the current scope stack, maybe
343 // we can re-use something
346 s = registry_getsuperclass(s);
349 /* TODO: if this is one of *our* classes, we can also
350 do a getglobalscope/getslot <nr> (which references
351 the init function's slots) */
352 __ getlex2(m, extends);
353 __ newclass(m,state->cls);
358 __ setslot(m, slotindex);
361 static void endclass()
363 printf("leaving class %s\n", state->classname);
366 static void addimport(token_t*t)
370 list_append(state->imports, i);
372 static void print_imports()
374 import_list_t*l = state->imports;
376 printf(" import %s\n", l->import->path);
380 static void startfunction(token_t*ns, token_t*mod, token_t*getset, token_t*name,
381 token_t*params, multiname_t*type)
385 state->function = name->text;
386 printf("entering function %s\n", name->text);
388 printf(" namespace: %s\n", ns->text);
389 printf(" getset: %s\n", getset->text);
390 printf(" params: ");for(t=params->tokens;t;t=t->next) printf("%s ", t->token->text);printf("\n");
391 printf(" mod: ");for(t=mod->tokens;t;t=t->next) printf("%s ", t->token->text);printf("\n");
392 printf(" type: %s\n", multiname_tostring(type));
395 abc_method_body_t* m=0;
396 if(!strcmp(state->classname,name->text)) {
397 m = abc_class_constructor(state->cls, type, 0);
399 m = abc_class_method(state->cls, type, name->text, 0);
403 static void endfunction()
405 printf("leaving function %s\n", state->function);
408 static int newvariable(token_t*mod, token_t*varconst, token_t*name, multiname_t*type)
411 printf("defining new variable %s\n", name->text);
412 printf(" mod: ");for(t=mod->tokens;t;t=t->next) printf("%s ", t->token->text);printf("\n");
413 printf(" access: ");printf("%s\n", varconst->text);
414 printf(" type: ");printf("%s\n", multiname_tostring(type));
416 static token_t* empty_token()
424 void extend(token_t*list, token_t*add) {
425 list_append(list->tokens,add);
427 list->text = add->text;
429 void extend_s(token_t*list, char*seperator, token_t*add) {
430 list_append(list->tokens,add);
431 char*t1 = list->text;
437 list->text = malloc(l1+l2+l3+1);
438 strcpy(list->text, t1);
439 strcpy(list->text+l1, t2);
440 strcpy(list->text+l1+l2, t3);
441 list->text[l1+l2+l3]=0;
453 CODE: CODE CODEPIECE {$$=$1;}
454 CODE: CODEPIECE {$$=empty_token();}
457 CODEPIECE: VARIABLE_DECLARATION {$$=$1;}
458 CODEPIECE: PACKAGE_DECLARATION
460 CODEPIECE: NAMESPACE_DECLARATION
461 CODEPIECE: CLASS_DECLARATION
462 CODEPIECE: INTERFACE_DECLARATION
463 CODEPIECE: FUNCTION_DECLARATION
464 CODEPIECE: EXPRESSION
467 CODEPIECE: ASSIGNMENT
469 PACKAGE_DECLARATION : T_PACKAGE MULTILEVELIDENTIFIER '{' {startpackage($2)} MAYBECODE '}' {endpackage()}
470 PACKAGE_DECLARATION : T_PACKAGE '{' {startpackage(0)} MAYBECODE '}' {endpackage()}
472 IMPORT : T_IMPORT PACKAGESPEC {addimport($2);}
474 TYPE : PACKAGEANDCLASS {$$=$1;}
475 | '*' {$$=registry_getanytype();}
476 | T_STRING {$$=registry_getstringclass();}
477 | T_INT {$$=registry_getintclass();}
478 | T_UINT {$$=registry_getuintclass();}
479 | T_BOOLEAN {$$=registry_getbooleanclass();}
480 | T_NUMBER {$$=registry_getnumberclass();}
482 MAYBETYPE: ':' TYPE {$$=$2;}
485 //FUNCTION_HEADER: NAMESPACE MODIFIERS T_FUNCTION GETSET T_IDENTIFIER '(' PARAMS ')'
486 FUNCTION_HEADER: MODIFIERS T_FUNCTION GETSET T_IDENTIFIER '(' PARAMS ')'
488 FUNCTION_DECLARATION: MODIFIERS T_FUNCTION GETSET T_IDENTIFIER '(' PARAMS ')'
489 MAYBETYPE '{' {startfunction(0,$1,$3,$4,$6,$8)} MAYBECODE '}' {endfunction()}
491 NAMESPACE_DECLARATION : MODIFIERS T_NAMESPACE T_IDENTIFIER
492 NAMESPACE_DECLARATION : MODIFIERS T_NAMESPACE T_IDENTIFIER '=' T_IDENTIFIER
493 NAMESPACE_DECLARATION : MODIFIERS T_NAMESPACE T_IDENTIFIER '=' T_STRING
495 //NAMESPACE : {$$=empty_token();}
496 //NAMESPACE : T_IDENTIFIER {$$=$1};
504 VAR : T_CONST | T_VAR
509 VARIABLE_DECLARATION : MODIFIERS VAR T_IDENTIFIER MAYBETYPE {
510 int i = newvariable($1,$2,$3,$4);
512 VARIABLE_DECLARATION : MODIFIERS VAR T_IDENTIFIER MAYBETYPE '=' EXPRESSION {
513 int i = newvariable($1,$2,$3,$4);
539 //E : '(' E ')' // conflicts with function calls: "a=f(c++);"<->"a=f;(c++)"
540 //E : '-' E // conflicts with non-assignment statements: "a=3-1;"<->"a=3;-1"
542 NEW : T_NEW T_IDENTIFIER
543 | T_NEW T_IDENTIFIER '(' ')'
544 | T_NEW T_IDENTIFIER '(' EXPRESSION_LIST ')'
546 FUNCTIONCALL : VARIABLE '(' EXPRESSION_LIST ')'
547 FUNCTIONCALL : VARIABLE '(' ')'
549 EXPRESSION_LIST : EXPRESSION
550 EXPRESSION_LIST : EXPRESSION_LIST ',' EXPRESSION
552 VARIABLE : T_IDENTIFIER
553 VARIABLE : VARIABLE '.' T_IDENTIFIER
554 VARIABLE : VARIABLE ".." T_IDENTIFIER // descendants
555 VARIABLE : VARIABLE "::" VARIABLE // namespace declaration
556 VARIABLE : VARIABLE "::" '[' EXPRESSION ']' // qualified expression
557 VARIABLE : VARIABLE '[' EXPRESSION ']' // unqualified expression
559 ASSIGNMENT : VARIABLE '=' EXPRESSION
560 NEW_ASSIGNMENT : T_VAR VARIABLE MAYBETYPE '=' EXPRESSION
562 FOR : T_FOR '(' NEW_ASSIGNMENT ';' EXPRESSION ';' EXPRESSION ')' '{' MAYBECODE '}'
563 FOR : T_FOR '(' ASSIGNMENT ';' EXPRESSION ';' EXPRESSION ')' '{' MAYBECODE '}'
565 USE : T_USE T_NAMESPACE T_IDENTIFIER
567 // keywords which also may be identifiers
568 X_IDENTIFIER : T_IDENTIFIER | T_PACKAGE
570 PACKAGESPEC : PACKAGESPEC '.' PACKAGESPEC {if($1->text[0]=='*') syntaxerror("wildcard in the middle of path");
571 $$ = concat3($1,$2,$3);}
572 PACKAGESPEC : X_IDENTIFIER {$$=$1;}
573 PACKAGESPEC : '*' {$$=$1;}
575 GETSET : T_GET {$$=$1;}
577 | {$$=empty_token();}
579 CLASS_DECLARATION : MODIFIERS T_CLASS T_IDENTIFIER EXTENDS IMPLEMENTS_LIST '{' {startclass($1,$3,$4,$5);} MAYBE_DECLARATION_LIST '}' {endclass();}
580 INTERFACE_DECLARATION : MODIFIERS T_INTERFACE T_IDENTIFIER EXTENDS_LIST '{' MAYBE_IDECLARATION_LIST '}'
582 PARAMS: {$$=empty_token();}
583 PARAMS: PARAM_LIST {$$=$1;}
584 PARAM_LIST: PARAM_LIST ',' PARAM {extend($1,$3);$$=$1;}
585 PARAM_LIST: PARAM {$$=empty_token();extend($$,$1);}
586 PARAM: T_IDENTIFIER ':' TYPE {$$=$1;}
588 MODIFIERS : {$$=empty_token();}
589 MODIFIERS : MODIFIER_LIST {$$=$1}
590 MODIFIER_LIST : MODIFIER MODIFIER_LIST {extend($2,$1);$$=$2;}
591 MODIFIER_LIST : MODIFIER {$$=empty_token();extend($$,$1);}
592 MODIFIER : T_PUBLIC | T_PRIVATE | T_PROTECTED | T_STATIC | T_DYNAMIC | T_FINAL | T_OVERRIDE | T_NATIVE | T_INTERNAL
594 DECLARATION : VARIABLE_DECLARATION
595 DECLARATION : FUNCTION_DECLARATION
597 IDECLARATION : VARIABLE_DECLARATION
598 IDECLARATION : FUNCTION_DECLARATION
600 IMPLEMENTS_LIST : {$$=list_new();}
601 IMPLEMENTS_LIST : T_IMPLEMENTS PACKAGEANDCLASS_LIST {$$=$2;}
603 EXTENDS : {$$=registry_getobjectclass();}
604 EXTENDS : T_EXTENDS PACKAGEANDCLASS {$$=$2;}
606 EXTENDS_LIST : {$$=list_new();}
607 EXTENDS_LIST : T_EXTENDS PACKAGEANDCLASS_LIST {$$=$2;}
609 //IDENTIFIER_LIST : T_IDENTIFIER ',' IDENTIFIER_LIST {extend($3,$1);$$=$3;}
610 //IDENTIFIER_LIST : T_IDENTIFIER {$$=empty_token();extend($$,$1);}
612 PACKAGEANDCLASS : T_IDENTIFIER {$$ = registry_findclass(state->package, $1->text);}
613 PACKAGEANDCLASS : PACKAGE '.' T_IDENTIFIER {$$ = registry_findclass($1->text, $3->text);}
614 PACKAGE : X_IDENTIFIER
615 PACKAGE : PACKAGE '.' X_IDENTIFIER {$$=$1;extend_s($$,".",$3);}
617 MULTILEVELIDENTIFIER : MULTILEVELIDENTIFIER '.' X_IDENTIFIER {$$=$1;extend_s($$, ".", $3)}
618 MULTILEVELIDENTIFIER : T_IDENTIFIER {$$=$1;extend($$,$1)};
620 PACKAGEANDCLASS_LIST : PACKAGEANDCLASS {$$=list_new();list_append($$, $1);}
621 PACKAGEANDCLASS_LIST : PACKAGEANDCLASS_LIST ',' PACKAGEANDCLASS {$$=$1;list_append($$,$3);}
623 MAYBE_DECLARATION_LIST :
624 MAYBE_DECLARATION_LIST : DECLARATION_LIST
625 DECLARATION_LIST : DECLARATION
626 DECLARATION_LIST : DECLARATION_LIST DECLARATION
628 MAYBE_IDECLARATION_LIST :
629 MAYBE_IDECLARATION_LIST : IDECLARATION_LIST
630 IDECLARATION_LIST : IDECLARATION
631 IDECLARATION_LIST : IDECLARATION_LIST FUNCTION_HEADER
634 // 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
635 // syntactic keywords: each get set namespace include dynamic final native override static