+/* ------------ 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($$);
+}
+