X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fas3%2Fparser.y;h=b181866348f71342fe9c8aa543e112a830ae47b5;hp=c692c9de4f3498222c9192a48ff70a5d4746a621;hb=9ed9a87914fc9a590967d46de404e0f6290b7bb2;hpb=c9ef8a6292a3d3dd78f1a73cf55bdc26692c3719 diff --git a/lib/as3/parser.y b/lib/as3/parser.y index c692c9d..b181866 100644 --- a/lib/as3/parser.y +++ b/lib/as3/parser.y @@ -77,7 +77,7 @@ extern int a3_lex(); } -%token T_IDENTIFIER T_NAMESPACE +%token T_IDENTIFIER %token T_STRING %token T_REGEXP %token T_EMPTY @@ -267,7 +267,6 @@ extern int a3_lex(); // needed for "return" precedence: %nonassoc T_STRING T_REGEXP %nonassoc T_INT T_UINT T_FLOAT KW_NAN -%left T_NAMESPACE %nonassoc "false" "true" "null" "undefined" "super" "function" %left above_function @@ -395,6 +394,7 @@ typedef struct _state { dict_t*import_toplevel_packages; dict_t*imports; + dict_t*namespaces; namespace_list_t*active_namespace_urls; char has_own_imports; @@ -502,7 +502,7 @@ static void new_state() state->old = oldstate; state->new_vars = 0; - trie_remember(active_namespaces); + state->namespaces = dict_new(); if(oldstate) state->active_namespace_urls = list_clone(oldstate->active_namespace_urls); @@ -529,8 +529,6 @@ 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; @@ -560,8 +558,6 @@ void initialize_file(char*filename) syntaxerror("invalid call to initialize_file during parsing of another file"); } - active_namespaces = trie_new(); - new_state(); state->package = internal_filename_package = strdup(filename); @@ -912,6 +908,29 @@ static void endpackage() #define FLAG_PACKAGEINTERNAL 2048 #define FLAG_NAMESPACE 4096 +static slotinfo_t* find_class(const char*name); + +const char* lookup_namespace(const char*name) +{ + state_t*s = state; + while(s) { + const char*url = dict_lookup(s->namespaces, name); + if(url) + return url; + s = s->old; + } + varinfo_t*a; + registry_find(state->package, name); + if(( a = (varinfo_t*)find_class(name) )) { + if(a->kind == INFOTYPE_VAR) { + if(!a->value || !NS_TYPE(a->value->type)) + syntaxerror("%s.%s is not a namespace", a->package, a->name); + return a->value->ns->name; + } + } + return 0; +} + static namespace_t modifiers2access(modifiers_t*mod) { namespace_t ns; @@ -921,14 +940,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; - state_t*s = state; - const char*url = (const char*)trie_lookup(active_namespaces, (unsigned char*)mod->ns); - if(!url) { - /* shouldn't happen- the tokenizer only reports something as a namespace - if it was already registered */ - trie_dump(active_namespaces); - syntaxerror("unknown namespace: %s", mod->ns); - } + const char*url = lookup_namespace(mod->ns); + if(!url) { + if(as3_pass>1) { + syntaxerror("unknown namespace: %s (pass %d)", mod->ns, as3_pass); + } else { + url = mod->ns; + } + } ns.name = url; } else if(mod->flags&FLAG_PUBLIC) { if(mod->flags&(FLAG_PRIVATE|FLAG_PROTECTED|FLAG_PACKAGEINTERNAL)) @@ -947,7 +966,6 @@ static namespace_t modifiers2access(modifiers_t*mod) } return ns; } -static slotinfo_t* find_class(const char*name); static memberinfo_t* findmember_nsset(classinfo_t*cls, const char*name, char recurse, char is_static) { @@ -2527,7 +2545,6 @@ X_IDENTIFIER: T_IDENTIFIER | "package" {PASS12 $$="package";} | "namespace" {PASS12 $$="namespace";} | "NaN" {PASS12 $$="NaN";} - | T_NAMESPACE {PASS12 $$=$1;} PACKAGE: PACKAGE '.' X_IDENTIFIER {PASS12 $$ = concat3($1,".",$3);free($1);$1=0;} PACKAGE: X_IDENTIFIER {PASS12 $$=strdup($1);} @@ -2569,7 +2586,7 @@ IMPORT : "import" T_IDENTIFIER { IMPORT : "import" PACKAGEANDCLASS { PASS12 slotinfo_t*s = registry_find($2->package, $2->name); - if(!s && as3_pass==1) {// || !(s->flags&FLAG_BUILTIN)) { + if(!s && as3_pass==1) { as3_schedule_class($2->package, $2->name); } /*if(s && s->kind == INFOTYPE_VAR && TYPE_IS_NAMESPACE(s->type)) { @@ -2615,7 +2632,7 @@ MODIFIER : KW_PUBLIC {PASS12 $$.flags=FLAG_PUBLIC;$$.ns=0;} | KW_OVERRIDE {PASS12 $$.flags=FLAG_OVERRIDE;$$.ns=0;} | KW_NATIVE {PASS12 $$.flags=FLAG_NATIVE;$$.ns=0;} | KW_INTERNAL {PASS12 $$.flags=FLAG_PACKAGEINTERNAL;$$.ns=0;} - | T_NAMESPACE {PASS12 $$.flags=FLAG_NAMESPACE; + | T_IDENTIFIER {PASS12 $$.flags=FLAG_NAMESPACE; $$.ns=$1; } @@ -2840,7 +2857,6 @@ MAYBECONSTANT: '=' E { } } -//CONSTANT : T_NAMESPACE {$$ = constant_new_namespace($1);} CONSTANT : T_INT {$$ = constant_new_int($1);} CONSTANT : T_UINT { $$ = constant_new_uint($1); @@ -2853,11 +2869,6 @@ CONSTANT : "null" {$$ = constant_new_null($1);} CONSTANT : "undefined" {$$ = constant_new_undefined($1);} CONSTANT : KW_NAN {$$ = constant_new_float(__builtin_nan(""));} -/*CONSTANT : T_NAMESPACE { - // TODO - $$ = constant_new_namespace(namespace_new_namespace($1.url)); -}*/ - /* ---------------------------xml ------------------------------ */ %code { @@ -3077,6 +3088,7 @@ CLASS: X_IDENTIFIER { slotinfo_t*s = find_class($1); if(!s) syntaxerror("Could not find class/method %s (current package: %s)\n", $1, state->package); $$ = (classinfo_t*)s; + registry_use(s); } PACKAGEANDCLASS : PACKAGE '.' X_IDENTIFIER { @@ -3091,6 +3103,7 @@ PACKAGEANDCLASS : PACKAGE '.' X_IDENTIFIER { if(!s) syntaxerror("Couldn't find class/method %s.%s\n", $1, $3); free($1);$1=0; $$ = (classinfo_t*)s; + registry_use(s); } CLASS_SPEC: PACKAGEANDCLASS @@ -3522,7 +3535,6 @@ E : E '.' '(' {PASS12 new_state();state->xmlfilter=1;} E ')' { ID_OR_NS : T_IDENTIFIER {$$=$1;} ID_OR_NS : '*' {$$="*";} -ID_OR_NS : T_NAMESPACE {$$=(char*)$1;} SUBNODE: X_IDENTIFIER | '*' {$$="*";} @@ -3792,6 +3804,7 @@ MEMBER : E '.' SUBNODE { /* look at actual classes, in the current package and imported */ if(!state->xmlfilter && (a = find_class(name))) { + registry_use(a); if(state->cls && state->cls->info == (classinfo_t*)a && i_am_static) { o.c = abc_getlocal_0(0); o.t = TYPE_CLASS((classinfo_t*)a); @@ -3828,12 +3841,6 @@ MEMBER : E '.' SUBNODE { } }; -/* TODO: causes 16 r/r conflicts */ -VAR_READ : T_NAMESPACE { - PASS2 - $$ = resolve_identifier($1); -} - VAR_READ : T_IDENTIFIER { PASS1 /* Queue unresolved identifiers for checking against the parent @@ -3891,7 +3898,7 @@ NAMESPACE_ID : "namespace" T_IDENTIFIER '=' T_STRING { } NAMESPACE_DECLARATION : MAYBE_MODIFIERS NAMESPACE_ID { PASS12 - trie_put(active_namespaces, (unsigned char*)$2->name, (void*)$2->url); + dict_put(state->namespaces, (unsigned char*)$2->name, (void*)$2->url); namespace_t access = modifiers2access(&$1); varinfo_t* var = varinfo_register_global(access.access, state->package, $2->name); @@ -3934,7 +3941,7 @@ USE_NAMESPACE : "use" "namespace" CLASS_SPEC { syntaxerror("%s.%s is not a namespace", $3->package, $3->name); const char*url = s->value->ns->name; - trie_put(active_namespaces, (unsigned char*)$3->name, (void*)url); + dict_put(state->namespaces, (unsigned char*)$3->name, (void*)url); add_active_url(url); $$=0; }