+E : E '.' '(' {PASS12 new_state();state->xmlfilter=1;} E ')' {
+ PASS1 old_state();
+ PASS2
+ typedcode_t v = node_read($1);
+ typedcode_t w = node_read($5);
+ code_t*c = 0;
+ int index = alloc_local();
+ int result = alloc_local();
+ int tmp = alloc_local();
+ int xml = alloc_local();
+
+ c = code_append(c, v.c);
+ c = abc_checkfilter(c);
+ c = abc_coerce_a(c); //hasnext2 converts to *
+ c = abc_setlocal(c, xml);
+ multiname_t m = {QNAME, &stdns, 0, "XMLList"};
+ c = abc_getlex2(c, &m);
+ c = abc_construct(c, 0);
+ c = abc_setlocal(c, result);
+ c = abc_pushbyte(c, 0);
+ c = abc_setlocal(c, index);
+ code_t*jmp = c = abc_jump(c, 0);
+ code_t*loop = c = abc_label(c);
+ c = abc_getlocal(c, xml);
+ c = abc_getlocal(c, index);
+ c = abc_nextvalue(c);
+ c = abc_dup(c);
+ c = abc_setlocal(c, tmp);
+ c = abc_pushwith(c);
+ c = code_append(c, w.c);
+ c = abc_popscope(c);
+ code_t*b = c = abc_iffalse(c, 0);
+ c = abc_getlocal(c, result);
+ c = abc_getlocal(c, index);
+ c = abc_getlocal(c, tmp);
+ multiname_t m2 = {MULTINAMEL, 0, &nopackage_namespace_set, 0};
+ c = abc_setproperty2(c, &m2);
+ c = b->branch = jmp->branch = abc_nop(c);
+ c = abc_kill(c, tmp);
+ c = abc_hasnext2(c, xml, index);
+ c = abc_iftrue(c, loop);
+ c = abc_getlocal(c, result);
+ c = abc_kill(c, xml);
+ c = abc_kill(c, result);
+ c = abc_kill(c, index);
+
+ c = var_block(c, state->vars);
+ old_state();
+ typedcode_t r;
+ r.c = c;
+ r.t = TYPE_XMLLIST;
+ $$ = mkcodenode(r);
+}
+
+ID_OR_NS : T_IDENTIFIER {$$=$1;}
+ID_OR_NS : '*' {$$="*";}
+ID_OR_NS : T_NAMESPACE {$$=(char*)$1;}
+SUBNODE: X_IDENTIFIER
+ | '*' {$$="*";}
+
+/*
+MAYBE_NS: T_IDENTIFIER "::" {$$=$1;}
+ | T_NAMESPACE "::" {$$=(char*)$1;}
+ | '*' "::" {$$="*";}
+ | {$$=0;}*/
+
+E : E '.' ID_OR_NS "::" SUBNODE {
+ typedcode_t v = node_read($1);
+ typedcode_t w = node_read(resolve_identifier($3));
+ v.c = code_append(v.c, w.c);
+ if(!TYPE_IS_NAMESPACE(w.t)) {
+ as3_softwarning("%s might not be a namespace", $3);
+ }
+ v.c = converttype(v.c, w.t, TYPE_NAMESPACE);
+ multiname_t m = {RTQNAME, 0, 0, $5};
+ v.c = abc_getproperty2(v.c, &m);
+ if(TYPE_IS_XML(v.t)) {
+ v.t = TYPE_XMLLIST;
+ } else {
+ v.c = abc_coerce_a(v.c);
+ v.t = TYPE_ANY;
+ }
+ $$ = mkcodenode(v);
+}
+E : E ".." SUBNODE {
+ typedcode_t v = node_read($1);
+ multiname_t m = {MULTINAME, 0, &nopackage_namespace_set, $3};
+ v.c = abc_getdescendants2(v.c, &m);
+ v.t = TYPE_XMLLIST;
+ $$ = mkcodenode(v);
+}
+E : E '.' '[' E ']' {
+ typedcode_t v = node_read($1);
+ typedcode_t w = node_read($4);
+ multiname_t m = {MULTINAMEL, 0, &nopackage_namespace_set, 0};
+ v.c = code_append(v.c, w.c);
+ v.c = converttype(w.c, w.t, TYPE_STRING);
+ v.c = abc_getproperty2(v.c, &m);
+ v.t = TYPE_XMLLIST;
+ $$ = mkcodenode(v);
+}
+
+E : E '.' '@' SUBNODE {
+ typedcode_t v = node_read($1);
+ multiname_t m = {MULTINAMEA, 0, &nopackage_namespace_set, $4};
+ v.c = abc_getproperty2(v.c, &m);
+ v.t = TYPE_STRING;
+ $$ = mkcodenode(v);
+}
+E : E ".." '@' SUBNODE {
+ typedcode_t v = node_read($1);
+ multiname_t m = {MULTINAMEA, 0, &nopackage_namespace_set, $4};
+ v.c = abc_getdescendants2(v.c, &m);
+ v.t = TYPE_STRING;
+ $$ = mkcodenode(v);
+}
+E : E '.' '@' '[' E ']' {
+ typedcode_t v = node_read($1);
+ typedcode_t w = node_read($5);
+ multiname_t m = {MULTINAMELA, 0, &nopackage_namespace_set, 0};
+ v.c = code_append(v.c, w.c);
+ v.c = converttype(w.c, w.t, TYPE_STRING);
+ v.c = abc_getproperty2(v.c, &m);
+ v.t = TYPE_STRING;
+ $$ = mkcodenode(v);
+}
+E : E ".." '@' '[' E ']' {
+ typedcode_t v = node_read($1);
+ typedcode_t w = node_read($5);
+ multiname_t m = {MULTINAMELA, 0, &nopackage_namespace_set, 0};
+ v.c = code_append(v.c, w.c);
+ v.c = converttype(w.c, w.t, TYPE_STRING);
+ v.c = abc_getdescendants2(v.c, &m);
+ v.t = TYPE_STRING;
+ $$ = mkcodenode(v);
+}
+
+MEMBER : E '.' SUBNODE {
+ typedcode_t v1 = node_read($1);
+ $$.c = v1.c;
+ classinfo_t*t = v1.t;
+ char is_static = 0;
+ if(TYPE_IS_CLASS(t) && t->data) {
+ t = t->data;
+ is_static = 1;
+ }
+ if(TYPE_IS_XML(t)) {
+ multiname_t m = {MULTINAME, 0, &nopackage_namespace_set, $3};
+ $$.c = abc_getproperty2($$.c, &m);
+ $$.c = abc_coerce_a($$.c);
+ $$.t = TYPE_XMLLIST;
+ } else if(t) {
+ if(t->subtype==INFOTYPE_UNRESOLVED) {
+ syntaxerror("syntaxerror: trying to resolve property '%s' on incomplete object '%s'", $3, t->name);
+ }
+ memberinfo_t*f = findmember_nsset(t, $3, 1);
+ char noslot = 0;
+ if(f && !is_static != !(f->flags&FLAG_STATIC))
+ noslot=1;
+ if(f && f->slot && !noslot) {
+ $$.c = abc_getslot($$.c, f->slot);
+ } else {
+ if(!f) {
+ if(!TYPE_IS_XMLLIST(t)) {
+ as3_softwarning("Access of undefined property '%s' in %s", $3, t->name);
+ }
+ }
+ MEMBER_MULTINAME(m, f, $3);
+ $$.c = abc_getproperty2($$.c, &m);
+ }
+ /* determine type */
+ $$.t = slotinfo_gettype((slotinfo_t*)f);
+ if(!$$.t)
+ $$.c = abc_coerce_a($$.c);
+
+ } else if(v1.c && v1.c->opcode == OPCODE___PUSHPACKAGE__) {
+ string_t*package = v1.c->data[0];
+ char*package2 = concat3(package->str, ".", $3);
+
+ slotinfo_t*a = registry_find(package->str, $3);
+ if(a) {
+ $$ = push_class(a);
+ } else if(dict_contains(state->import_toplevel_packages, package2) ||
+ registry_ispackage(package2)) {
+ $$.c = v1.c;
+ $$.c->data[0] = string_new4(package2);
+ $$.t = 0;
+ } else {
+ syntaxerror("couldn't resolve %s", package2);
+ }
+ } else {
+ /* when resolving a property on an unknown type, we do know the
+ name of the property (and don't seem to need the package), but
+ we need to make avm2 try out all access modes */
+ as3_softwarning("Resolving %s on unknown type", $3);
+ multiname_t m = {MULTINAME, 0, &nopackage_namespace_set, $3};
+ $$.c = abc_getproperty2($$.c, &m);
+ $$.c = abc_coerce_a($$.c);
+ $$.t = TYPE_ANY;
+ }
+}