From b16e095437f2a9c6adcfadbe8116f413927a4ed5 Mon Sep 17 00:00:00 2001 From: kramm Date: Fri, 2 Jan 2009 21:05:23 +0000 Subject: [PATCH] implemented throw and try/catch --- lib/as3/parser.y | 88 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 80 insertions(+), 8 deletions(-) diff --git a/lib/as3/parser.y b/lib/as3/parser.y index e643572..0c8c635 100644 --- a/lib/as3/parser.y +++ b/lib/as3/parser.y @@ -58,6 +58,8 @@ char*id; constant_t*constant; for_start_t for_start; + abc_exception_t *exception; + abc_exception_list_t *exception_list; } @@ -95,6 +97,7 @@ %token KW_CASE "case" %token KW_SET "set" %token KW_VOID "void" +%token KW_THROW "throw" %token KW_STATIC %token KW_INSTANCEOF "instanceof" %token KW_IMPORT "import" @@ -160,7 +163,9 @@ %type CODEBLOCK MAYBECODE MAYBE_CASE_LIST CASE_LIST DEFAULT CASE SWITCH %type PACKAGE_DECLARATION SLOT_DECLARATION %type FUNCTION_DECLARATION PACKAGE_INITCODE -%type VARIABLE_DECLARATION ONE_VARIABLE VARIABLE_LIST +%type VARIABLE_DECLARATION ONE_VARIABLE VARIABLE_LIST THROW +%type CATCH +%type CATCH_LIST %type CLASS_DECLARATION %type NAMESPACE_DECLARATION %type INTERFACE_DECLARATION @@ -169,7 +174,7 @@ %type MAYBEEXPRESSION %type E DELETE %type CONSTANT -%type FOR FOR_IN IF WHILE DO_WHILE MAYBEELSE BREAK RETURN CONTINUE +%type FOR FOR_IN IF WHILE DO_WHILE MAYBEELSE BREAK RETURN CONTINUE TRY %type USE_NAMESPACE %type FOR_INIT %type IMPORT @@ -289,6 +294,7 @@ typedef struct _methodstate { char is_constructor; char has_super; char is_global; + abc_exception_list_t*exceptions; } methodstate_t; typedef struct _state { @@ -302,6 +308,8 @@ typedef struct _state { classstate_t*cls; methodstate_t*method; + + char*exception_name; dict_t*vars; } state_t; @@ -957,11 +965,13 @@ static void endfunction(token_t*ns, int flags, enum yytokentype getset, char*nam } check_code_for_break(body); - if(f->body) + if(f->body) { f->body->code = body; - else //interface + f->body->exceptions = state->method->exceptions; + } else { //interface if(body) syntaxerror("interface methods can't have a method body"); + } free(state->method);state->method=0; old_state(); @@ -1316,18 +1326,16 @@ CODE_STATEMENT: WHILE CODE_STATEMENT: DO_WHILE CODE_STATEMENT: SWITCH CODE_STATEMENT: IF +CODE_STATEMENT: TRY // code which may appear anywhere -//CODEPIECE: PACKAGE_DECLARATION -//CODEPIECE: CLASS_DECLARATION -//CODEPIECE: FUNCTION_DECLARATION -//CODEPIECE: INTERFACE_DECLARATION CODEPIECE: ';' {$$=0;} CODEPIECE: VARIABLE_DECLARATION CODEPIECE: CODE_STATEMENT CODEPIECE: BREAK CODEPIECE: CONTINUE CODEPIECE: RETURN +CODEPIECE: THROW CODEPIECE: NAMESPACE_DECLARATION {/*TODO*/$$=0;} CODEPIECE: USE_NAMESPACE {/*TODO*/$$=0;} @@ -1585,6 +1593,70 @@ SWITCH : T_SWITCH '(' {new_state();} E ')' '{' MAYBE_CASE_LIST '}' { old_state(); } +/* ------------ 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($$); +} + /* ------------ packages and imports ---------------- */ X_IDENTIFIER: T_IDENTIFIER -- 1.7.10.4