+FINALLY: "finally" '{' {PASS12 new_state();state->exception_name=0;} MAYBECODE '}' {
+ $4 = var_block($4);
+ if(!$4) {
+ $$=0;
+ } else {
+ NEW(abc_exception_t, e)
+ e->exc_type = 0; //all exceptions
+ e->var_name = 0; //no name
+ e->target = 0;
+ e->to = abc_nop(0);
+ e->to = code_append(e->to, $4);
+ $$ = e;
+ }
+ PASS12 old_state();
+}
+
+CATCH_LIST: CATCH {$$.l=list_new();$$.finally=0;list_append($$.l,$1);}
+CATCH_LIST: CATCH_LIST CATCH {$$=$1;list_append($$.l,$2);}
+CATCH_FINALLY_LIST: CATCH_LIST {$$=$1;}
+CATCH_FINALLY_LIST: CATCH_LIST FINALLY {
+ $$ = $1;
+ $$.finally = 0;
+ if($2) {
+ list_append($$.l,$2);
+ $$.finally = $2->to;$2->to=0;
+ }
+}
+CATCH_FINALLY_LIST: FINALLY {
+ $$.l=list_new();
+ $$.finally = 0;
+ if($1) {
+ list_append($$.l,$1);
+ $$.finally = $1->to;$1->to=0;
+ }
+}
+
+TRY : "try" '{' {PASS12 new_state();} MAYBECODE '}' CATCH_FINALLY_LIST {
+ code_t*out = abc_nop(0);
+
+ code_t*start = abc_nop(0);
+ $$ = code_append(start, $4);
+ if(!is_break_or_jump($4)) {
+ $$ = abc_jump($$, out);
+ }
+ code_t*end = $$ = abc_nop($$);
+
+ int tmp;
+ if($6.finally)
+ tmp = new_variable("__finally__", 0, 0, 0);
+
+ abc_exception_list_t*l = $6.l;
+ int count=0;
+ while(l) {
+ abc_exception_t*e = l->abc_exception;
+ if(e->var_name) {
+ $$ = code_append($$, e->target);
+ $$ = abc_jump($$, out);
+ } else {
+ parserassert((ptroff_t)$6.finally);
+ // finally block
+ e->target = $$ = abc_nop($$);
+ $$ = abc___rethrow__($$);
+ }
+
+ e->from = start;
+ e->to = end;
+
+ l = l->next;
+ }
+ $$ = code_append($$, out);
+
+ $$ = insert_finally($$, $6.finally, tmp);
+
+ list_concat(state->method->exceptions, $6.l);
+
+ $$ = var_block($$);
+ PASS12 old_state();
+}
+
+/* ------------ 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, 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
+ | "package" {PASS12 $$="package";}
+
+PACKAGE: PACKAGE '.' X_IDENTIFIER {PASS12 $$ = concat3($1,".",$3);free($1);$1=0;}
+PACKAGE: X_IDENTIFIER {PASS12 $$=strdup($1);}
+
+PACKAGE_DECLARATION : "package" PACKAGE '{' {PASS12 startpackage($2);free($2);$2=0;}
+ MAYBE_INPACKAGE_CODE_LIST '}' {PASS12 endpackage();$$=0;}
+PACKAGE_DECLARATION : "package" '{' {PASS12 startpackage("");}
+ MAYBE_INPACKAGE_CODE_LIST '}' {PASS12 endpackage();$$=0;}
+
+IMPORT : "import" PACKAGEANDCLASS {
+ PASS12
+ slotinfo_t*s = registry_find($2->package, $2->name);
+ if(!s) {// || !(s->flags&FLAG_BUILTIN)) {
+ as3_schedule_class($2->package, $2->name);
+ }
+
+ PASS2
+ classinfo_t*c = $2;
+ if(!c)
+ syntaxerror("Couldn't import class\n");
+ state_has_imports();
+ dict_put(state->imports, c->name, c);
+ $$=0;
+}
+IMPORT : "import" PACKAGE '.' '*' {
+ PASS12
+ if(strncmp("flash.", $2, 6)) {
+ as3_schedule_package($2);
+ }
+
+ PASS2
+ NEW(import_t,i);
+ i->package = $2;