X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fas3%2Fparser.y;h=a81e4e04cedda223b9595aeba7cbe2a92dac16d5;hb=71c8242a8242eeb6e8b6dcf57239550a6f35c88a;hp=d6cf02aefa59475fc73a3bb800b57bfc64d52836;hpb=6b14c68239f98b818a7aacacc49bb7a16bfa7812;p=swftools.git diff --git a/lib/as3/parser.y b/lib/as3/parser.y index d6cf02a..a81e4e0 100644 --- a/lib/as3/parser.y +++ b/lib/as3/parser.y @@ -354,8 +354,7 @@ typedef struct _state { import_list_t*wildcard_imports; dict_t*import_toplevel_packages; dict_t*imports; - namespace_list_t*active_namespaces; - namespace_decl_list_t*new_namespaces; + char has_own_imports; char new_vars; // e.g. transition between two functions @@ -441,10 +440,11 @@ static void new_state() state = s; state->level++; state->has_own_imports = 0; - state->new_namespaces = 0; state->vars = dict_new(); state->old = oldstate; state->new_vars = 0; + + trie_remember(active_namespaces); } static void state_has_imports() { @@ -491,18 +491,14 @@ static void state_destroy(state_t*state) static void old_state() { + trie_rollback(active_namespaces); + if(!state || !state->old) syntaxerror("invalid nesting"); state_t*leaving = state; state = state->old; - namespace_decl_list_t*nl=leaving->new_namespaces; - while(nl) { - tokenizer_unregister_namespace(nl->namespace_decl->name); - nl = nl->next; - } - if(as3_pass>1 && leaving->method && leaving->method != state->method && !leaving->method->inner) { free(leaving->method); leaving->method=0; @@ -526,6 +522,9 @@ void initialize_file(char*filename) if(state) { syntaxerror("invalid call to initialize_file during parsing of another file"); } + + active_namespaces = trie_new(); + new_state(); state->package = internal_filename_package = strdup(filename); @@ -844,7 +843,14 @@ static namespace_t modifiers2access(modifiers_t*mod) if(mod->flags&(FLAG_PRIVATE|FLAG_PROTECTED|FLAG_PACKAGEINTERNAL)) syntaxerror("invalid combination of access levels and namespaces"); ns.access = ACCESS_NAMESPACE; - ns.name = mod->ns; + state_t*s = state; + const char*url = (const char*)trie_lookup(active_namespaces, mod->ns); + if(!url) { + /* shouldn't happen- the tokenizer only reports something as a namespace + if it was already registered */ + syntaxerror("unknown namespace: %s", mod->ns); + } + ns.name = url; } else if(mod->flags&FLAG_PUBLIC) { if(mod->flags&(FLAG_PRIVATE|FLAG_PROTECTED|FLAG_PACKAGEINTERNAL)) syntaxerror("invalid combination of access levels"); @@ -864,6 +870,12 @@ static namespace_t modifiers2access(modifiers_t*mod) } static slotinfo_t* find_class(const char*name); +memberinfo_t* findmember_nsset(classinfo_t*cls, const char*name, char recurse) +{ + /* FIXME- we need to loop through namespaces here */ + return registry_findmember(cls, "", name, recurse); +} + static void function_initvars(methodstate_t*m, params_t*params, int flags, char var0) { if(var0) { @@ -1163,6 +1175,7 @@ void check_code_for_break(code_t*c) static void check_constant_against_type(classinfo_t*t, constant_t*c) { + return; #define xassert(b) if(!(b)) syntaxerror("Invalid default value %s for type '%s'", constant_tostring(c), t->name) if(TYPE_IS_NUMBER(t)) { xassert(c->type == CONSTANT_FLOAT @@ -1373,8 +1386,6 @@ static void startfunction(modifiers_t*mod, enum yytokentype getset, char*name, static abc_method_t* endfunction(modifiers_t*mod, enum yytokentype getset, char*name, params_t*params, classinfo_t*return_type, code_t*body) { - int flags = mod?mod->flags:0; - if(as3_pass==1) { // store inner methods in variables function_initvars(state->method, 0, 0, 0); @@ -1447,10 +1458,10 @@ static abc_method_t* endfunction(modifiers_t*mod, enum yytokentype getset, char* } else if(state->method->is_constructor) { f = abc_class_getconstructor(state->cls->abc, type2); } else if(!state->method->is_global) { - namespace_t mname_ns = {state->method->info->access, ""}; + namespace_t mname_ns = modifiers2access(mod); multiname_t mname = {QNAME, &mname_ns, 0, name}; - if(flags&FLAG_STATIC) + if(mod->flags&FLAG_STATIC) f = abc_class_staticmethod(state->cls->abc, type2, &mname); else f = abc_class_method(state->cls->abc, type2, &mname); @@ -1466,7 +1477,7 @@ static abc_method_t* endfunction(modifiers_t*mod, enum yytokentype getset, char* //flash doesn't seem to allow us to access function slots //state->method->info->slot = slot; - if(flags&FLAG_OVERRIDE) f->trait->attributes |= TRAIT_ATTR_OVERRIDE; + if(mod && mod->flags&FLAG_OVERRIDE) f->trait->attributes |= TRAIT_ATTR_OVERRIDE; if(getset == KW_GET) f->trait->kind = TRAIT_GETTER; if(getset == KW_SET) f->trait->kind = TRAIT_SETTER; if(params->varargs) f->flags |= METHOD_NEED_REST; @@ -1940,7 +1951,6 @@ char is_break_or_jump(code_t*c) return 0; } - #define IS_FINALLY_TARGET(op) \ ((op) == OPCODE___CONTINUE__ || \ (op) == OPCODE___BREAK__ || \ @@ -2580,6 +2590,7 @@ WITH : WITH_HEAD CODEBLOCK { X_IDENTIFIER: T_IDENTIFIER | "package" {PASS12 $$="package";} + | T_NAMESPACE {PASS12 $$=$1;} PACKAGE: PACKAGE '.' X_IDENTIFIER {PASS12 $$ = concat3($1,".",$3);free($1);$1=0;} PACKAGE: X_IDENTIFIER {PASS12 $$=strdup($1);} @@ -2632,7 +2643,6 @@ MODIFIER_LIST : MODIFIER_LIST MODIFIER { $$.ns=$1.ns?$1.ns:$2.ns; } - MODIFIER : KW_PUBLIC {PASS12 $$.flags=FLAG_PUBLIC;$$.ns=0;} | KW_PRIVATE {PASS12 $$.flags=FLAG_PRIVATE;$$.ns=0;} | KW_PROTECTED {PASS12 $$.flags=FLAG_PROTECTED;$$.ns=0;} @@ -2910,7 +2920,7 @@ INNERFUNCTION: "function" MAYBE_IDENTIFIER '(' MAYBE_PARAM_LIST ')' MAYBETYPE /* ------------- package + class ids --------------- */ -CLASS: T_IDENTIFIER { +CLASS: X_IDENTIFIER { PASS1 NEW(unresolvedinfo_t,c); memset(c, 0, sizeof(*c)); c->kind = INFOTYPE_UNRESOLVED; @@ -2929,7 +2939,7 @@ CLASS: T_IDENTIFIER { $$ = (classinfo_t*)s; } -PACKAGEANDCLASS : PACKAGE '.' T_IDENTIFIER { +PACKAGEANDCLASS : PACKAGE '.' X_IDENTIFIER { PASS1 NEW(unresolvedinfo_t,c); memset(c, 0, sizeof(*c)); c->kind = INFOTYPE_UNRESOLVED; @@ -3592,7 +3602,7 @@ E : "super" '.' T_IDENTIFIER classinfo_t*t = state->cls->info->superclass; if(!t) t = TYPE_OBJECT; - memberinfo_t*f = registry_findmember_nsset(t, state->active_namespaces, $3, 1); + memberinfo_t*f = findmember_nsset(t, $3, 1); MEMBER_MULTINAME(m, f, $3); $$.c = 0; @@ -3652,7 +3662,7 @@ E : E '.' T_IDENTIFIER { if(t->subtype==INFOTYPE_UNRESOLVED) { syntaxerror("syntaxerror: trying to resolve property '%s' on incomplete object '%s'", $3, t->name); } - memberinfo_t*f = registry_findmember_nsset(t, state->active_namespaces, $3, 1); + memberinfo_t*f = findmember_nsset(t, $3, 1); char noslot = 0; if(f && !is_static != !(f->flags&FLAG_STATIC)) noslot=1; @@ -3731,7 +3741,7 @@ VAR_READ : T_IDENTIFIER { int i_am_static = (state->method && state->method->info)?(state->method->info->flags&FLAG_STATIC):FLAG_STATIC; /* look at current class' members */ - if(state->cls && (f = registry_findmember_nsset(state->cls->info, state->active_namespaces, $1, 1)) && + if(state->cls && (f = findmember_nsset(state->cls->info, $1, 1)) && (f->flags&FLAG_STATIC) >= i_am_static) { // $1 is a function in this class int var_is_static = (f->flags&FLAG_STATIC); @@ -3799,7 +3809,7 @@ NAMESPACE_ID : "namespace" T_IDENTIFIER { PASS12 NEW(namespace_decl_t,n); n->name = $2; - n->url = 0; + n->url = $2; $$=n; } NAMESPACE_ID : "namespace" T_IDENTIFIER '=' T_IDENTIFIER { @@ -3818,20 +3828,23 @@ NAMESPACE_ID : "namespace" T_IDENTIFIER '=' T_STRING { } NAMESPACE_DECLARATION : MAYBE_MODIFIERS NAMESPACE_ID { PASS12 - list_append(state->new_namespaces, $2); - tokenizer_register_namespace($2->name); + trie_put(active_namespaces, $2->name, (void*)$2->url); + + namespace_t access = modifiers2access(&$1); + varinfo_t* var = varinfo_register_global(access.access, state->package, $2->name); + var->type = TYPE_NAMESPACE; + namespace_t ns; + ns.access = ACCESS_NAMESPACE; + ns.name = $2->url; + var->value = constant_new_namespace(&ns); + $$=0; } USE_NAMESPACE : "use" "namespace" CLASS_SPEC { PASS12 - NEW(namespace_decl_t,n); - n->name = $3->name; - n->url = 0; - /* FIXME: for pass2, we should now try to figure out what the URL of - this thing is */ - list_append(state->new_namespaces, n); - tokenizer_register_namespace($3->name); + char*url = 0; + trie_put(active_namespaces, $3->name, url); $$=0; }