X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fas3%2Fparser.y;h=d2188ef3adca462869ab324366483baa6c335e20;hb=d49fd65de7a35d210dd7b9aa746ac647c5a90238;hp=32007bc3798d5f35190a02a0764a775263022aa1;hpb=f5192a905ac6fe6406519f8b78c128fda3d4fd21;p=swftools.git diff --git a/lib/as3/parser.y b/lib/as3/parser.y index 32007bc..d2188ef 100644 --- a/lib/as3/parser.y +++ b/lib/as3/parser.y @@ -58,6 +58,8 @@ char*id; constant_t*constant; for_start_t for_start; + abc_exception_t *exception; + abc_exception_list_t *exception_list; } @@ -76,16 +78,16 @@ %token T_DO "do" %token T_SWITCH "switch" -%token KW_IMPLEMENTS +%token KW_IMPLEMENTS "implements" %token KW_NAMESPACE "namespace" %token KW_PACKAGE "package" -%token KW_PROTECTED -%token KW_PUBLIC -%token KW_PRIVATE +%token KW_PROTECTED "protected" +%token KW_PUBLIC "public" +%token KW_PRIVATE "private" %token KW_USE "use" -%token KW_INTERNAL +%token KW_INTERNAL "internal" %token KW_NEW "new" -%token KW_NATIVE +%token KW_NATIVE "native" %token KW_FUNCTION "function" %token KW_UNDEFINED "undefined" %token KW_CONTINUE "continue" @@ -95,7 +97,9 @@ %token KW_CASE "case" %token KW_SET "set" %token KW_VOID "void" -%token KW_STATIC +%token KW_THROW "throw" +%token KW_STATIC "static" +%token KW_WITH "with" %token KW_INSTANCEOF "instanceof" %token KW_IMPORT "import" %token KW_RETURN "return" @@ -104,13 +108,13 @@ %token KW_NULL "null" %token KW_VAR "var" %token KW_DYNAMIC "dynamic" -%token KW_OVERRIDE -%token KW_FINAL +%token KW_OVERRIDE "override" +%token KW_FINAL "final" %token KW_EACH "each" %token KW_GET "get" %token KW_TRY "try" %token KW_SUPER "super" -%token KW_EXTENDS +%token KW_EXTENDS "extends" %token KW_FALSE "false" %token KW_TRUE "true" %token KW_BOOLEAN "Boolean" @@ -157,10 +161,12 @@ %type VARCONST %type CODE %type CODEPIECE CODE_STATEMENT -%type CODEBLOCK MAYBECODE MAYBE_CASE_LIST CASE_LIST DEFAULT CASE SWITCH +%type CODEBLOCK MAYBECODE MAYBE_CASE_LIST CASE_LIST DEFAULT CASE SWITCH WITH %type PACKAGE_DECLARATION SLOT_DECLARATION %type FUNCTION_DECLARATION PACKAGE_INITCODE -%type VARIABLE_DECLARATION ONE_VARIABLE VARIABLE_LIST +%type VARIABLE_DECLARATION ONE_VARIABLE VARIABLE_LIST THROW +%type CATCH +%type CATCH_LIST %type CLASS_DECLARATION %type NAMESPACE_DECLARATION %type INTERFACE_DECLARATION @@ -169,7 +175,7 @@ %type MAYBEEXPRESSION %type E DELETE %type CONSTANT -%type FOR FOR_IN IF WHILE DO_WHILE MAYBEELSE BREAK RETURN CONTINUE +%type FOR FOR_IN IF WHILE DO_WHILE MAYBEELSE BREAK RETURN CONTINUE TRY %type USE_NAMESPACE %type FOR_INIT %type IMPORT @@ -289,6 +295,7 @@ typedef struct _methodstate { char is_constructor; char has_super; char is_global; + abc_exception_list_t*exceptions; } methodstate_t; typedef struct _state { @@ -302,6 +309,8 @@ typedef struct _state { classstate_t*cls; methodstate_t*method; + + char*exception_name; dict_t*vars; } state_t; @@ -360,11 +369,6 @@ static namespace_list_t nl2 = {&ns2,&nl3}; static namespace_list_t nl1 = {&ns1,&nl2}; static namespace_set_t nopackage_namespace_set = {&nl1}; -static void init_globals() -{ - global = rfx_calloc(sizeof(global_t)); -} - static void new_state() { NEW(state_t, s); @@ -425,9 +429,11 @@ static void old_state() } void initialize_state() { - init_globals(); + global = rfx_calloc(sizeof(global_t)); new_state(); + state->package = current_filename; + global->file = abc_file_new(); global->file->flags &= ~ABCFILE_LAZY; global->variable_count = 1; @@ -491,9 +497,6 @@ void* finalize_state() static void startpackage(char*name) { - if(state->package) { - syntaxerror("Packages can not be nested."); - } new_state(); /*printf("entering package \"%s\"\n", name);*/ state->package = strdup(name); @@ -822,13 +825,7 @@ static memberinfo_t*registerfunction(enum yytokentype getset, int flags, char*na memberinfo_t*minfo = 0; if(!state->cls) { //package method - minfo = rfx_calloc(sizeof(memberinfo_t)); - classinfo_t*c = classinfo_register(flags2access(flags), state->package, name, 0); - c->flags |= FLAG_METHOD; - c->function = minfo; - minfo->kind = MEMBER_METHOD; - minfo->name = name; - minfo->flags = FLAG_STATIC; + minfo = memberinfo_register_global(flags2access(flags), state->package, name, MEMBER_METHOD); minfo->return_type = return_type; } else if(getset != KW_GET && getset != KW_SET) { //class method @@ -969,11 +966,13 @@ static void endfunction(token_t*ns, int flags, enum yytokentype getset, char*nam } check_code_for_break(body); - if(f->body) + if(f->body) { f->body->code = body; - else //interface + f->body->exceptions = state->method->exceptions; + } else { //interface if(body) syntaxerror("interface methods can't have a method body"); + } free(state->method);state->method=0; old_state(); @@ -1099,14 +1098,15 @@ static classinfo_t* find_class(char*name) classinfo_t*c=0; c = registry_findclass(state->package, name); + if(c) return c; /* try explicit imports */ dictentry_t* e = dict_get_slot(state->imports, name); + if(c) return c; while(e) { - if(c) - break; if(!strcmp(e->key, name)) { c = (classinfo_t*)e->data; + if(c) return c; } e = e->next; } @@ -1114,18 +1114,21 @@ static classinfo_t* find_class(char*name) /* try package.* imports */ import_list_t*l = state->wildcard_imports; while(l) { - if(c) - break; //printf("does package %s contain a class %s?\n", l->import->package, name); c = registry_findclass(l->import->package, name); + if(c) return c; l = l->next; } /* try global package */ - if(!c) { - c = registry_findclass("", name); - } - return c; + c = registry_findclass("", name); + if(c) return c; + + /* try local "filename" package */ + c = registry_findclass(current_filename, name); + if(c) return c; + + return 0; } static code_t* toreadwrite(code_t*in, code_t*middlepart, char justassign, char readbefore) @@ -1296,6 +1299,7 @@ PROGRAM_CODE: PACKAGE_DECLARATION | FUNCTION_DECLARATION | SLOT_DECLARATION | PACKAGE_INITCODE + | ';' MAYBE_INPACKAGE_CODE_LIST: | INPACKAGE_CODE_LIST INPACKAGE_CODE_LIST: INPACKAGE_CODE @@ -1306,6 +1310,7 @@ INPACKAGE_CODE: INTERFACE_DECLARATION | FUNCTION_DECLARATION | SLOT_DECLARATION | PACKAGE_INITCODE + | ';' MAYBECODE: CODE {$$=$1;} MAYBECODE: {$$=code_new();} @@ -1322,18 +1327,17 @@ CODE_STATEMENT: WHILE CODE_STATEMENT: DO_WHILE CODE_STATEMENT: SWITCH CODE_STATEMENT: IF +CODE_STATEMENT: WITH +CODE_STATEMENT: TRY // code which may appear anywhere -CODEPIECE: ';' {$$=0;} -//CODEPIECE: PACKAGE_DECLARATION -//CODEPIECE: CLASS_DECLARATION -//CODEPIECE: FUNCTION_DECLARATION -//CODEPIECE: INTERFACE_DECLARATION +CODEPIECE: ';' {$$=0;} CODEPIECE: VARIABLE_DECLARATION CODEPIECE: CODE_STATEMENT CODEPIECE: BREAK CODEPIECE: CONTINUE CODEPIECE: RETURN +CODEPIECE: THROW CODEPIECE: NAMESPACE_DECLARATION {/*TODO*/$$=0;} CODEPIECE: USE_NAMESPACE {/*TODO*/$$=0;} @@ -1591,6 +1595,79 @@ SWITCH : T_SWITCH '(' {new_state();} E ')' '{' MAYBE_CASE_LIST '}' { old_state(); } +/* ------------ try / catch /finally ---------------- */ + +FINALLY: "finally" '{' CODE '}' +MAYBE_FINALLY: | FINALLY + +CATCH: "catch" '(' T_IDENTIFIER MAYBETYPE ')' {new_state();state->exception_name=$3;new_variable($3, $4, 0);} + '{' CODE '}' { + code_t*c = 0; + int i = find_variable_safe($3)->index; + c = abc_setlocal(c, i); + c = code_append(c, $8); + c = abc_kill(c, i); + + namespace_t name_ns = {ACCESS_PACKAGE, ""}; + multiname_t name = {QNAME, &name_ns, 0, $3}; + + NEW(abc_exception_t, e) + e->exc_type = sig2mname($4); + e->var_name = multiname_clone(&name); + e->target = code_start(c); + $$ = e; + old_state(); +} + +CATCH_LIST: CATCH {$$=list_new();list_append($$,$1);} +CATCH_LIST: CATCH_LIST CATCH {$$=$1;list_append($$,$2);} + +TRY : "try" '{' CODE '}' CATCH_LIST MAYBE_FINALLY { + code_t*start = code_start($3); + $$=$3; + + code_t*out = abc_nop(0); + code_t*jmp = $$ = abc_jump($$, out); + + abc_exception_list_t*l = $5; + while(l) { + abc_exception_t*e = l->abc_exception; + e->from = start; + e->to = jmp; + $$ = code_append($$, e->target); + $$ = abc_jump($$, out); + l = l->next; + } + $$ = code_append($$, out); + jmp->branch = out; + + list_concat(state->method->exceptions, $5); +} + +/* ------------ throw ------------------------------- */ + +THROW : "throw" EXPRESSION { + $$=$2.c; + $$=abc_throw($$); +} +THROW : "throw" %prec prec_none { + if(!state->exception_name) + syntaxerror("re-throw only possible within a catch block"); + variable_t*v = find_variable(state->exception_name); + $$=code_new(); + $$=abc_getlocal($$, v->index); + $$=abc_throw($$); +} + +/* ------------ with -------------------------------- */ + +WITH : "with" '(' EXPRESSION ')' CODEBLOCK { + $$ = $3.c; + $$ = abc_pushscope($$); + $$ = code_append($$, $5); + $$ = abc_popscope($$); +} + /* ------------ packages and imports ---------------- */ X_IDENTIFIER: T_IDENTIFIER @@ -1695,42 +1772,53 @@ VARCONST: "var" | "const" SLOT_DECLARATION: MAYBE_MODIFIERS VARCONST T_IDENTIFIER MAYBETYPE MAYBEEXPRESSION { int flags = $1; - memberinfo_t* info = memberinfo_register(state->cls->info, $3, MEMBER_SLOT); + memberinfo_t* info = state->cls? + memberinfo_register(state->cls->info, $3, MEMBER_SLOT): + memberinfo_register_global(flags2access($1), state->package, $3, MEMBER_SLOT); + info->type = $4; info->flags = flags; - trait_t*t=0; + /* slot name */ namespace_t mname_ns = {flags2access(flags), ""}; multiname_t mname = {QNAME, &mname_ns, 0, $3}; - - if(!(flags&FLAG_STATIC)) { - if($4) { - MULTINAME(m, $4); - t=abc_class_slot(state->cls->abc, &mname, &m); - } else { - t=abc_class_slot(state->cls->abc, &mname, 0); - } - info->slot = t->slot_id; + + trait_list_t**traits; + code_t**code; + if(!state->cls) { + // global variable + traits = &global->init->traits; + code = &global->init->method->body->code; + } else if(flags&FLAG_STATIC) { + // static variable + traits = &state->cls->abc->static_traits; + code = &state->cls->static_init; } else { - if($4) { - MULTINAME(m, $4); - t=abc_class_staticslot(state->cls->abc, &mname, &m); - } else { - t=abc_class_staticslot(state->cls->abc, &mname, 0); - } - info->slot = t->slot_id; + // instance variable + traits = &state->cls->abc->traits; + code = &state->cls->init; + } + + trait_t*t=0; + if($4) { + MULTINAME(m, $4); + t = trait_new_member(traits, multiname_clone(&m), multiname_clone(&mname), 0); + } else { + t = trait_new_member(traits, 0, multiname_clone(&mname), 0); } + info->slot = t->slot_id; + + /* initalization code (if needed) */ + code_t*c = 0; if($5.c && !is_pushundefined($5.c)) { - code_t*c = 0; c = abc_getlocal_0(c); c = code_append(c, $5.c); c = converttype(c, $5.t, $4); c = abc_setslot(c, t->slot_id); - if(!(flags&FLAG_STATIC)) - state->cls->init = code_append(state->cls->init, c); - else - state->cls->static_init = code_append(state->cls->static_init, c); } + + *code = code_append(*code, c); + if($2==KW_CONST) { t->kind= TRAIT_CONST; }