-CODEPIECE: PACKAGE_DECLARATION {$$=code_new();/*enters a scope*/}
-CODEPIECE: CLASS_DECLARATION {$$=code_new();/*enters a scope*/}
-CODEPIECE: FUNCTION_DECLARATION {$$=code_new();/*enters a scope*/}
-CODEPIECE: INTERFACE_DECLARATION {$$=code_new();}
-CODEPIECE: IMPORT {$$=code_new();/*adds imports to current scope*/}
-CODEPIECE: ';' {$$=code_new();}
-CODEPIECE: VARIABLE_DECLARATION {$$=$1}
-CODEPIECE: VOIDEXPRESSION {$$=$1}
-CODEPIECE: FOR {$$=$1}
-CODEPIECE: WHILE {$$=$1}
-CODEPIECE: DO_WHILE {$$=$1}
-CODEPIECE: BREAK {$$=$1}
-CODEPIECE: CONTINUE {$$=$1}
-CODEPIECE: RETURN {$$=$1}
-CODEPIECE: IF {$$=$1}
-CODEPIECE: NAMESPACE_DECLARATION {/*TODO*/$$=code_new();}
-CODEPIECE: USE_NAMESPACE {/*TODO*/$$=code_new();}
-
-CODEBLOCK : '{' MAYBECODE '}' {$$=$2;}
+code_t* insert_finally(code_t*c, code_t*finally, int tempvar)
+{
+ if(!finally)
+ return c;
+ code_t*i = c;
+ char cantdup=0;
+ int num_insertion_points=0;
+ while(i) {
+ if(IS_FINALLY_TARGET(i->opcode))
+ num_insertion_points++;
+ i = i->prev;
+ }
+ i = finally;
+ int code_size=0;
+ while(i) {
+ code_size++;
+ if(i->branch || i->opcode == OPCODE_LOOKUPSWITCH) {
+ cantdup=1;
+ }
+ i = i->prev;
+ }
+ int simple_version_cost = (1+num_insertion_points)*code_size;
+ int lookup_version_cost = 4*num_insertion_points + 5;
+
+ if(cantdup || simple_version_cost > lookup_version_cost) {
+ printf("lookup %d > *%d*\n", simple_version_cost, lookup_version_cost);
+ return insert_finally_lookup(c, finally, tempvar);
+ } else {
+ printf("simple *%d* < %d\n", simple_version_cost, lookup_version_cost);
+ return insert_finally_simple(c, finally, tempvar);
+ }
+}
+
+#define PASS1 }} if(as3_pass == 1) {{
+#define PASS1END }} if(as3_pass == 2) {{
+#define PASS2 }} if(as3_pass == 2) {{
+#define PASS12 }} {{
+#define PASS12END }} if(as3_pass == 2) {{
+
+%}
+
+%%
+
+/* ------------ code blocks / statements ---------------- */
+
+PROGRAM: MAYBE_PROGRAM_CODE_LIST
+
+MAYBE_PROGRAM_CODE_LIST: | PROGRAM_CODE_LIST
+PROGRAM_CODE_LIST: PROGRAM_CODE
+ | PROGRAM_CODE_LIST PROGRAM_CODE
+
+PROGRAM_CODE: PACKAGE_DECLARATION
+ | INTERFACE_DECLARATION
+ | CLASS_DECLARATION
+ | FUNCTION_DECLARATION
+ | SLOT_DECLARATION
+ | PACKAGE_INITCODE
+ | CONDITIONAL_COMPILATION '{' MAYBE_PROGRAM_CODE_LIST '}' // conditional compilation
+ | ';'
+
+MAYBE_INPACKAGE_CODE_LIST: | INPACKAGE_CODE_LIST
+INPACKAGE_CODE_LIST: INPACKAGE_CODE
+ | INPACKAGE_CODE_LIST INPACKAGE_CODE
+
+INPACKAGE_CODE: INTERFACE_DECLARATION
+ | CLASS_DECLARATION
+ | FUNCTION_DECLARATION
+ | SLOT_DECLARATION
+ | PACKAGE_INITCODE
+ | CONDITIONAL_COMPILATION '{' MAYBE_INPACKAGE_CODE_LIST '}' // conditional compilation
+ | ';'
+
+MAYBECODE: CODE {$$=$1;}
+MAYBECODE: {$$=code_new();}
+
+CODE: CODE CODEPIECE {$$=code_append($1,$2);}
+CODE: CODEPIECE {$$=$1;}
+
+// code which may appear outside of methods
+CODE_STATEMENT: IMPORT
+CODE_STATEMENT: FOR
+CODE_STATEMENT: FOR_IN
+CODE_STATEMENT: WHILE
+CODE_STATEMENT: DO_WHILE
+CODE_STATEMENT: SWITCH
+CODE_STATEMENT: IF
+CODE_STATEMENT: WITH
+CODE_STATEMENT: TRY
+CODE_STATEMENT: VOIDEXPRESSION
+CODE_STATEMENT: USE_NAMESPACE
+CODE_STATEMENT: NAMESPACE_DECLARATION
+CODE_STATEMENT: '{' CODE '}' {$$=$2;}
+CODE_STATEMENT: '{' '}' {$$=0;}
+
+// code which may appear in methods
+CODEPIECE: ';' {$$=0;}
+CODEPIECE: CODE_STATEMENT
+CODEPIECE: VARIABLE_DECLARATION
+CODEPIECE: BREAK
+CODEPIECE: CONTINUE
+CODEPIECE: RETURN
+CODEPIECE: THROW
+CODEPIECE: CONDITIONAL_COMPILATION '{' CODE '}' {$$=$3;}
+
+//CODEBLOCK : '{' CODE '}' {$$=$2;}
+//CODEBLOCK : '{' '}' {$$=0;}