X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=aus_sammelwut%2Fpaulchen%2Fublu%2Fss08%2Fabgabe%2Fgesamt%2F.svn%2Ftext-base%2Fparser.y.svn-base;fp=aus_sammelwut%2Fpaulchen%2Fublu%2Fss08%2Fabgabe%2Fgesamt%2F.svn%2Ftext-base%2Fparser.y.svn-base;h=585b19be4f86f2e0addba192f350665ac6285035;hb=f6171150f9e60240b256808fc31613530b21db6c;hp=0000000000000000000000000000000000000000;hpb=b82da83a0ad2014c11113818eee6bd5fb5f3445c;p=uebersetzerbau-ss10.git diff --git a/aus_sammelwut/paulchen/ublu/ss08/abgabe/gesamt/.svn/text-base/parser.y.svn-base b/aus_sammelwut/paulchen/ublu/ss08/abgabe/gesamt/.svn/text-base/parser.y.svn-base new file mode 100644 index 0000000..585b19b --- /dev/null +++ b/aus_sammelwut/paulchen/ublu/ss08/abgabe/gesamt/.svn/text-base/parser.y.svn-base @@ -0,0 +1,595 @@ +%{ + #include + #include + #include + #include "symbol_table.h" + #include "code_gen.h" + #include "tree.h" + + #define imm_prefix "$" + + char *saved_reg; + +/* TODO failed test case: func f(a) if not (a=0 or a=1) then return 0; end; end; */ +%} + +%start Input +%token FUNC END STRUCT VAR IF THEN ELSE WHILE DO RETURN OR NOT +%token ID NUM ASSIGN GREATER + +@autoinh symbols stack_offset all_pars if_in jump_true jump_false +@autosyn node defined_vars immediate if_out has_call + +@attributes { char *name; } ID +@attributes { long value; } NUM +@attributes { struct symbol_t *fields; struct symbol_t *symbols; int if_in; } Program +@attributes { struct symbol_t *fields; } Structdef +@attributes { struct symbol_t *fields; int offset; } Ids +@attributes { struct symbol_t *pars; int num_pars; int all_pars; } Pars +@attributes { struct symbol_t *symbols; int defined_vars; int if_in; int if_out; } Funcdef +@attributes { struct symbol_t *symbols; int defined_vars; int stack_offset; treenode *node; int if_in; int if_out; int has_call; } Stats +@attributes { struct symbol_t *symbols; treenode *node; int immediate; int has_call; } Expr Term Plusterm Malterm +@attributes { struct symbol_t *symbols; treenode *node; int has_call; } Call Lexpr Field Exprs +@attributes { struct symbol_t *symbols; treenode *node; char *jump_true; char *jump_false; int negated; int if_in; int if_out; int negated2; int top_level; int has_call; } Bool Orterm Subbool Bterm +@attributes { struct symbol_t *in_symbols; struct symbol_t *out_symbols; treenode *node; int defined_vars; int stack_offset; int if_in; int if_out; int has_call; } Stat +@attributes { struct symbol_t *symbols; treenode *node; int defined_vars; int stack_offset; int if_in; int if_out; int if_nr; int has_call; } Blubb + +@traversal @postorder check +@traversal @preorder reg +@traversal @preorder codegen + +%% + +Input: Program + @{ + @i @Program.symbols@ = @Program.fields@; + @i @Program.if_in@ = 0; + + @codegen printf("\t.text\n"); + @} + + ; + +Program: Funcdef ';' Program + @{ + @i @Program.fields@ = @Program.1.fields@; + @i @Program.1.if_in@ = @Funcdef.if_out@; + @} + + | Structdef ';' Program + @{ + @i @Program.fields@ = table_merge(@Structdef.fields@, @Program.1.fields@, 1); + @i @Program.1.symbols@ = @Program.0.symbols@; + @} + + | + @{ @i @Program.fields@ = new_table(); @} + + ; + +Funcdef: FUNC ID '(' Pars ')' Stats END + @{ + @i @Stats.symbols@ = table_merge(@Funcdef.symbols@, @Pars.pars@, 0); + @i @Stats.stack_offset@ = 0; + @i @Pars.all_pars@ = @Pars.num_pars@; + + @codegen function_header(@ID.name@, @Funcdef.defined_vars@, @Stats.has_call@, @Pars.num_pars@); + @} + + | FUNC ID '(' ')' Stats END + @{ + @i @Stats.symbols@ = table_merge(@Funcdef.symbols@, new_table(), 0); + @i @Stats.stack_offset@ = 0; + + @codegen function_header(@ID.name@, @Funcdef.defined_vars@, @Stats.has_call@, 0); + @} + + ; + +Structdef: STRUCT Ids END + @{ + @i @Structdef.fields@ = @Ids.fields@; + @i @Ids.offset@ = 0; + @} + + ; + +Ids: ID Ids + @{ + @i @Ids.fields@ = table_add_symbol(@Ids.1.fields@, @ID.name@, SYMBOL_TYPE_FIELD, 1, @Ids.offset@); + @i @Ids.1.offset@ = @Ids.offset@ + 1; + @} + + | + @{ @i @Ids.fields@ = new_table(); @} + + ; + +Pars: Pars ',' ID + @{ + @i @Pars.pars@ = table_add_param(@Pars.1.pars@, @ID.name@, @Pars.num_pars@); + @i @Pars.num_pars@ = @Pars.1.num_pars@ + 1; + @} + + | ID + @{ + @i @Pars.pars@ = table_add_param(new_table(), @ID.name@, 1); + @i @Pars.num_pars@ = 1; + @} + + ; + +Stats: Stat ';' Stats + @{ + @i @Stat.in_symbols@ = @Stats.symbols@; + @i @Stats.1.symbols@ = @Stat.out_symbols@; + @i @Stats.defined_vars@ = @Stat.defined_vars@ + @Stats.1.defined_vars@; + @i @Stats.1.stack_offset@ = @Stats.stack_offset@ + @Stat.defined_vars@ * 8; + @i @Stats.node@ = new_node(OP_Stats, @Stat.node@, @Stats.1.node@); + @i @Stat.if_in@ = @Stats.if_in@; + @i @Stats.1.if_in@ = @Stat.if_out@; + @i @Stats.if_out@ = @Stats.1.if_out@; + @i @Stats.has_call@ = @Stat.has_call@ || @Stats.1.has_call@; + @} + + | + @{ + @i @Stats.node@ = new_leaf(OP_Empty); /* TODO */ + @i @Stats.defined_vars@ = 0; + @i @Stats.if_out@ = @Stats.if_in@; + @i @Stats.has_call@ = 0; + @} + + ; + +Stat: VAR ID ASSIGN Expr /* Nodes necessary for IF, DO, ... ? */ + @{ + @i @Stat.out_symbols@ = table_add_symbol(clone_table(@Stat.in_symbols@), @ID.name@, SYMBOL_TYPE_VAR, 0, @Stat.stack_offset@); + @i @Expr.symbols@ = @Stat.in_symbols@; + @i @Stat.node@ = new_node(OP_Assign, new_named_leaf_value(OP_ID, @ID.name@, @Stat.stack_offset@, -1), @Expr.node@); + @i @Stat.defined_vars@ = 1; + @i @Stat.if_out@ = @Stat.if_in@; + + @reg @Expr.node@->reg = get_next_reg((char *)NULL, 0); @Stat.node@->reg = @Expr.node@->reg; + + @codegen /* write_tree(@Stat.node@, 0); */ burm_label(@Stat.node@); burm_reduce(@Stat.node@, 1); + @} + + | Lexpr ASSIGN Expr + @{ + @i @Stat.out_symbols@ = @Stat.in_symbols@; + @i @Lexpr.symbols@ = @Stat.in_symbols@; + @i @Expr.symbols@ = @Stat.in_symbols@; + @i @Stat.node@ = new_node(OP_Assign, @Lexpr.node@, @Expr.node@); + @i @Stat.defined_vars@ = 0; + @i @Stat.if_out@ = @Stat.if_in@; + @i @Stat.has_call@ = @Lexpr.has_call@ || @Expr.has_call@; + + @reg @Lexpr.node@->reg = get_next_reg((char *)NULL, 0); @Expr.node@->reg = get_next_reg(@Lexpr.node@->reg, 0); @Stat.node@->reg = @Expr.node@->reg; + + @codegen /* write_tree(@Stat.node@, 0); */ burm_label(@Stat.node@); burm_reduce(@Stat.node@, 1); + @} + + | IF Bool THEN Stats END + @{ + @i @Bool.symbols@ = @Stat.in_symbols@; + @i @Stats.symbols@ = @Stat.in_symbols@; + @i @Stat.out_symbols@ = @Stat.in_symbols@; + @i @Stat.node@ = new_node(OP_If, @Bool.node@, @Stats.node@); + @i @Bool.if_in@ = @Stat.if_in@ + 1; + @i @Stats.if_in@ = @Bool.if_out@; + @i @Stat.if_out@ = @Stats.if_out@; + @e Bool.jump_true : Stats.if_in; @Bool.jump_true@ = malloc(100); sprintf(@Bool.jump_true@, "if_then%i", @Stats.if_in@); + @e Bool.jump_false : Stats.if_in; @Bool.jump_false@ = malloc(100); sprintf(@Bool.jump_false@, "if_end%i", @Stats.if_in@); + @i @Stat.has_call@ = @Bool.has_call@ || @Stats.has_call@; + + @reg @Bool.node@->reg = get_next_reg((char *)NULL, 0); + + @codegen /* write_tree(@Bool.node@, 0); burm_label(@Bool.node@); burm_reduce(@Bool.node@, 1); printf("\ttest %s1, %%%s\n\tjz if_end%i\n", imm_prefix, @Bool.node@->reg, @Stats.if_in@); */ + @codegen @revorder(1) printf("if_end%i:\n", @Stats.if_in@); + @} + + | IF Bool THEN Stats Blubb END + @{ + @i @Bool.symbols@ = @Stat.in_symbols@; + @i @Blubb.symbols@ = @Stat.in_symbols@; + @i @Stat.out_symbols@ = @Stat.in_symbols@; + @i @Stats.symbols@ = @Stat.in_symbols@; + @i @Stat.node@ = new_node(OP_Ifstats, @Stats.node@, @Blubb.node@); + @i @Stat.defined_vars@ = @Stats.defined_vars@ + @Blubb.defined_vars@; + @i @Bool.if_in@ = @Stat.if_in@ + 1; + @i @Stats.if_in@ = @Bool.if_out@; + @i @Blubb.if_in@ = @Stats.if_out@; + @i @Stat.if_out@ = @Blubb.if_out@; + @i @Blubb.if_nr@ = @Stats.if_in@; + @e Bool.jump_true : Stats.if_in; @Bool.jump_true@ = malloc(100); sprintf(@Bool.jump_true@, "if_then%i", @Stats.if_in@); + @e Bool.jump_false : Stats.if_in; @Bool.jump_false@ = malloc(100); sprintf(@Bool.jump_false@, "if_else%i", @Stats.if_in@); + @i @Stat.has_call@ = @Bool.has_call@ || @Stats.has_call@ || @Blubb.has_call@; + + @reg @Bool.node@->reg = get_next_reg((char *)NULL, 0); + + @codegen /* write_tree(@Bool.node@, 0); burm_label(@Bool.node@); burm_reduce(@Bool.node@, 1); printf("\ttest %s1, %%%s\n\tjz if_else%i\n", imm_prefix, @Bool.node@->reg, @Stats.if_in@); */ + @codegen @revorder(1) printf("if_end%i:\n", @Stats.if_in@); + @} + + | WHILE Bool DO Stats END + @{ + @i @Bool.symbols@ = @Stat.in_symbols@; + @i @Stats.symbols@ = @Stat.in_symbols@; + @i @Stat.out_symbols@ = @Stat.in_symbols@; + @i @Stat.node@ = new_node(OP_While, @Bool.node@, @Stats.node@); + @i @Bool.if_in@ = @Stat.if_in@ + 1; + @i @Stats.if_in@ = @Bool.if_out@; + @i @Stat.if_out@ = @Stats.if_out@; + @e Bool.jump_true : Stats.if_in; @Bool.jump_true@ = malloc(100); sprintf(@Bool.jump_true@, "do_enter%i", @Stats.if_in@); + @e Bool.jump_false : Stats.if_in; @Bool.jump_false@ = malloc(100); sprintf(@Bool.jump_false@, "do_end%i", @Stats.if_in@); + @i @Stat.has_call@ = @Bool.has_call@ || @Stats.has_call@; + + @reg @Bool.node@->reg = get_next_reg((char *)NULL, 0); + + @codegen printf("do_start%i:\n", @Stats.if_in@); /* write_tree(@Bool.node@, 0); burm_label(@Bool.node@); burm_reduce(@Bool.node@, 1); printf("\ttest %s1, %%%s\n\tjz do_end%i\n", imm_prefix, @Bool.node@->reg, @Stats.if_in@); */ + @codegen @revorder(1) printf("\tjmp do_start%i\ndo_end%i:\n", @Stats.if_in@, @Stats.if_in@); + @} + + | Call + @{ + @i @Call.symbols@ = @Stat.in_symbols@; + @i @Stat.out_symbols@ = @Stat.in_symbols@; + @i @Stat.node@ = (treenode *)NULL; + @i @Stat.defined_vars@ = 0; + @i @Stat.if_out@ = @Stat.if_in@; + + @reg @Call.node@->reg = "rax"; + @} + + | RETURN Expr + @{ + @i @Expr.symbols@ = @Stat.in_symbols@; + @i @Stat.out_symbols@ = @Stat.in_symbols@; + @i @Stat.node@ = new_node(OP_Return, @Expr.node@, (treenode *)NULL); + @i @Stat.defined_vars@ = 0; + @i @Stat.if_out@ = @Stat.if_in@; + + @reg if(@Expr.node@->op == OP_Call) { @Stat.node@->reg = get_next_reg("rax", 0); } else { @Stat.node@->reg = get_next_reg((char *)NULL, 0); } @Expr.node@->reg = @Stat.node@->reg; + + @codegen /* write_tree(@Stat.node@, 0); */ burm_label(@Stat.node@); burm_reduce(@Stat.node@, 1); + @} + + ; + +Blubb: ELSE Stats + @{ + @codegen printf("\tjmp if_end%i\nif_else%i:\n", @Blubb.if_nr@, @Blubb.if_nr@); + @} + +Lexpr: ID + @{ + @i @Lexpr.node@ = new_named_leaf_value(OP_ID, @ID.name@, (table_lookup(@Lexpr.symbols@, @ID.name@)==NULL) ? 0 : table_lookup(@Lexpr.symbols@, @ID.name@)->stack_offset, (table_lookup(@Lexpr.symbols@, @ID.name@)==NULL) ? 0 : table_lookup(@Lexpr.symbols@, @ID.name@)->param_index); + + @i @Lexpr.has_call@ = 0; + @check check_variable(@Lexpr.symbols@, @ID.name@); + @} + + | Field + ; + +Expr: '-' Term + @{ + @i @Expr.node@ = new_node(OP_Negation, @Term.node@, (treenode *)NULL); + + @reg @Term.node@->reg = @Expr.node@->reg; + @} + + | Term + @{ @reg @Term.node@->reg = @Expr.node@->reg; @} + + | Term Plusterm + @{ + @i @Expr.node@ = new_node(OP_Addition, @Plusterm.node@, @Term.node@); + @i @Expr.immediate@ = @Term.immediate@ && @Plusterm.immediate@; + @i @Expr.has_call@ = @Term.has_call@ || @Plusterm.has_call@; + + @reg if(!@Plusterm.immediate@) { @Plusterm.node@->reg = @Expr.node@->reg; @Term.node@->reg = get_next_reg(@Plusterm.node@->reg, @Expr.node@->skip_reg); @Plusterm.node@->skip_reg = 1; } else { @Term.node@->reg = @Expr.node@->reg; @Plusterm.node@->reg = get_next_reg(@Term.node@->reg, @Expr.node@->skip_reg); } + @} + + | Term Malterm + @{ + @i @Expr.node@ = new_node(OP_Multiplication, @Malterm.node@, @Term.node@); + @i @Expr.immediate@ = @Term.immediate@ && @Malterm.immediate@; + @i @Expr.has_call@ = @Term.has_call@ || @Malterm.has_call@; + + @reg if(!@Malterm.immediate@) { @Malterm.node@->reg = @Expr.node@->reg; @Term.node@->reg = get_next_reg(@Malterm.node@->reg, @Expr.node@->skip_reg); @Malterm.node@->skip_reg = 1; } else { @Term.node@-> reg = @Expr.node@->reg; @Malterm.node@->reg = get_next_reg(@Term.node@->reg, @Expr.node@->skip_reg); } + @} + + ; + +Plusterm: '+' Term Plusterm + @{ + @i @Plusterm.node@ = new_node(OP_Addition, @Plusterm.1.node@, @Term.node@); + @i @Plusterm.immediate@ = @Term.immediate@ && @Plusterm.1.immediate@; + @i @Plusterm.has_call@ = @Term.has_call@ || @Plusterm.1.has_call@; + + @reg @Plusterm.1.node@->reg = @Plusterm.node@->reg; @Term.node@->reg = get_next_reg(@Plusterm.1.node@->reg, @Plusterm.node@->skip_reg); + @} + + | '+' Term + @{ @reg @Term.node@->reg = @Plusterm.node@->reg; @} + + ; + +Malterm: '*' Term Malterm + @{ + @i @Malterm.node@ = new_node(OP_Multiplication, @Malterm.1.node@, @Term.node@); + @i @Malterm.immediate@ = @Term.immediate@ && @Malterm.1.immediate@; + @i @Malterm.has_call@ = @Term.has_call@ || @Malterm.1.has_call@; + + @reg @Malterm.1.node@->reg = @Malterm.node@->reg; @Term.node@->reg = get_next_reg(@Malterm.1.node@->reg, @Malterm.node@->skip_reg); + @} + + | '*' Term + @{ @reg @Term.node@->reg = @Malterm.node@->reg; @} + + ; + +Term: '(' Expr ')' + @{ @reg @Expr.node@->reg = @Term.node@->reg; @} + + | ID + @{ + @i @Term.node@ = new_named_leaf_value(OP_ID, @ID.name@, (table_lookup(@Term.symbols@, @ID.name@)==NULL) ? 0 : table_lookup(@Term.symbols@, @ID.name@)->stack_offset, (table_lookup(@Term.symbols@, @ID.name@)==NULL) ? 0 : table_lookup(@Term.symbols@, @ID.name@)->param_index); + @i @Term.immediate@ = 0; + @i @Term.has_call@ = 0; + + @check check_variable(@Term.symbols@, @ID.name@); + @} + + | NUM + @{ + @i @Term.node@ = new_number_leaf(@NUM.value@); + @i @Term.immediate@ = 1; + @i @Term.has_call@ = 0; + @} + + | Call + @{ + @i @Term.immediate@ = 0; + + @reg @Call.node@->reg = @Term.node@->reg; + @} + + | Field + @{ + @i @Term.immediate@ = 0; + + @reg @Field.node@->reg = @Term.node@->reg; + @} + + ; + +/* TODO replace by Bool -> Subbool */ +Bool: Bterm + @{ + @i @Bool.negated@ = 0; + @i @Bool.negated2@ = 0; + @i @Bterm.negated@ = 0; + @i @Bterm.negated2@ = 0; + @i @Bool.top_level@ = 1; + @i @Bterm.top_level@ = 1; + + @codegen @revorder(1) if(@Bterm.node@->op!=OP_Disjunction) { printf("\tjmp %s # foo1\n", @Bool.jump_false@); } printf("%s:\n", @Bool.jump_true@); /* printf("\tjmp %s\n%s:\n", @Bool.jump_false@, @Bool.jump_true@); */ + @} + + | Bterm Orterm + @{ + @i @Bool.node@ = new_node(OP_Disjunction, @Bterm.node@, @Orterm.node@); + @i @Bool.negated@ = 0; + @i @Bool.negated2@ = 0; + @i @Bterm.negated@ = 0; + @i @Orterm.negated@ = 0; + @i @Bterm.negated2@ = 0; + @i @Orterm.negated2@ = 0; + @e Bterm.jump_true : Bool.negated Bool.jump_true Bool.if_in; if(!@Bool.negated@) { @Bterm.jump_true@ = malloc(100); sprintf(@Bterm.jump_true@, "bool_true%i", @Bool.if_in@); } else { @Bterm.jump_true@ = @Bool.jump_true@; } + @i @Orterm.jump_true@ = @Bterm.jump_true@; + @e Bterm.jump_false : Bool.negated Bool.jump_false Bool.if_in; if(@Bool.negated@) { @Bterm.jump_false@ = malloc(100); sprintf(@Bterm.jump_false@, "bool_false%i", @Bool.if_in@); } else { @Bterm.jump_false@ = @Bool.jump_false@; } + @i @Orterm.jump_false@ = @Bterm.jump_false@; + @i @Bterm.if_in@ = @Bool.if_in@ + 1; + @i @Orterm.if_in@ = @Bterm.if_out@; + @i @Bool.if_out@ = @Orterm.if_out@; + @i @Bterm.top_level@ = 0; + @i @Orterm.top_level@ = 0; + @i @Bool.top_level@ = 1; + @i @Bool.has_call@ = @Bterm.has_call@ || @Orterm.has_call@; + + @reg @Bterm.node@->reg = @Bool.node@->reg; @Orterm.node@->reg = @Bool.node@->reg; + + @codegen @revorder(1) printf("\tjmp %s # foo2\n", @Bool.jump_false@); printf(@Bool.negated@ ? "bool_false%i:\n" : "bool_true%i:\n", @Bool.if_in@); printf("%s:\n", @Bool.jump_true@); /* printf("\tjmp %s\n%s:\n", @Bool.jump_false@, @Bool.jump_true@); */ + @} + + | NOT Bterm + @{ + @i @Bool.node@ = new_node(OP_Not, @Bterm.node@, (treenode *)NULL); + @i @Bterm.jump_true@ = @Bool.jump_true@; + @i @Bool.negated@ = 0; + @i @Bool.negated2@ = 0; + @i @Bterm.negated@ = 1; + @i @Bterm.negated2@ = 1; + @i @Bterm.top_level@ = 0; + @i @Bool.top_level@ = 1; + + @reg @Bterm.node@-> reg = @Bool.node@->reg; + + @codegen @revorder(1) if(@Bterm.node@->op!=OP_Not) { printf("\tjmp %s # foo3\n", @Bool.jump_false@); } printf("%s:\n", @Bool.jump_true@); /* printf("\tjmp %s\nnot_break%i:\n\tjmp %s\n%s:\n", @Bool.jump_true@, 0, @Bool.jump_false@, @Bool.jump_true@); */ + @} + + ; + +Subbool: Bterm + @{ + @i @Bterm.negated@ = @Subbool.negated@; + @i @Bterm.negated2@ = @Subbool.negated2@; + @i @Bterm.top_level@ = @Subbool.top_level@; + @codegen @revorder(1) /* printf("\tjmp %s\n%s:\n", @Subbool.jump_false@, @Subbool.jump_true@); */ + @} + + | Bterm Orterm + @{ + @i @Subbool.node@ = new_node(OP_Disjunction, @Bterm.node@, @Orterm.node@); + @i @Bterm.negated@ = @Subbool.negated@; + @i @Orterm.negated@ = @Subbool.negated@; + @i @Bterm.negated2@ = 0; + @i @Orterm.negated2@ = 0; + @e Bterm.jump_true : Subbool.negated Subbool.negated2 Subbool.jump_true Subbool.if_in; if(!@Subbool.negated@ && @Subbool.negated2@) { @Bterm.jump_true@ = malloc(100); sprintf(@Bterm.jump_true@, "bool_true%i", @Subbool.if_in@); } else { @Bterm.jump_true@ = @Subbool.jump_true@; } + @i @Orterm.jump_true@ = @Bterm.jump_true@; + @e Bterm.jump_false : Subbool.negated Subbool.negated2 Subbool.jump_false Subbool.if_in; if(@Subbool.negated@ && @Subbool.negated2@) { @Bterm.jump_false@ = malloc(100); sprintf(@Bterm.jump_false@, "bool_false%i", @Subbool.if_in@); } else { @Bterm.jump_false@ = @Subbool.jump_false@; } + @i @Orterm.jump_false@ = @Bterm.jump_false@; + @i @Bterm.if_in@ = @Subbool.if_in@ + 1; + @i @Orterm.if_in@ = @Bterm.if_out@; + @i @Subbool.if_out@ = @Orterm.if_out@; + @i @Bterm.top_level@ = 0; + @i @Orterm.top_level@ = 0; + @i @Subbool.has_call@ = @Bterm.has_call@ || @Orterm.has_call@; + + @reg @Bterm.node@->reg = @Subbool.node@->reg; @Orterm.node@->reg = @Subbool.node@->reg; + + @codegen @revorder(1) /* TODO output if on top level */ if(@Subbool.negated2@ || @Subbool.top_level@) { printf("\tjmp %s # foo4\n", @Subbool.negated2@ ? @Subbool.jump_true@ : @Subbool.jump_false@); } printf(!@Subbool.negated@ ? "bool_true%i:\n" : "bool_false%i:\n", @Subbool.if_in@); /* printf("\tjmp %s\n# %s:\n", @Subbool.jump_true@, @Subbool.jump_true@); */ + @} + + | NOT Bterm + @{ + @i @Subbool.node@ = new_node(OP_Not, @Bterm.node@, (treenode *)NULL); + @i @Bterm.jump_true@ = @Subbool.jump_true@; + @i @Bterm.negated@ = 1 - @Subbool.negated@; + @i @Bterm.negated2@ = 1 - @Subbool.negated2@; + @i @Bterm.top_level@ = 0; + + @reg @Bterm.node@-> reg = @Subbool.node@->reg; /* printf("%s, %s\n", @Bterm.jump_true@, @Subbool.jump_false@); */ + + @codegen @revorder(1) printf("# !!\n"); if(@Subbool.negated2@ || @Subbool.top_level@) { printf("\tjmp %s # foo9\n", @Subbool.negated2@ ? @Subbool.jump_false@ : @Subbool.jump_false@); } /* printf("\tjmp %s\nnot_break%i:\n", @Subbool.negated@ ? @Bterm.jump_true@ : @Subbool.jump_false@, 0); printf("\tjmp %s\n%s:\n", @Subbool.jump_false@, @Subbool.jump_true@); */ + @} + + ; + + +Orterm: OR Bterm Orterm + @{ + @i @Orterm.node@ = new_node(OP_Disjunction, @Bterm.node@, @Orterm.1.node@); + @i @Bterm.negated@ = @Orterm.negated@; + @i @Orterm.1.negated@ = @Orterm.negated@; + @i @Bterm.negated2@ = 0; + @i @Orterm.1.negated2@ = 0; + @i @Orterm.1.if_in@ = @Bterm.if_out@; + @i @Orterm.if_out@ = @Orterm.1.if_out@; + @i @Bterm.top_level@ = 0; + @i @Orterm.1.top_level@ = 0; + @i @Orterm.has_call@ = @Bterm.has_call@ || @Orterm.1.has_call@; + + @reg @Bterm.node@->reg = @Orterm.node@->reg; @Orterm.1.node@->reg = @Orterm.node@->reg; + @} + + | OR Bterm + @{ + @i @Bterm.negated@ = @Orterm.negated@; + @i @Bterm.negated2@ = @Orterm.negated2@; + @i @Bterm.top_level@ = 0; + @} + + ; + +Bterm: Term GREATER Term + @{ + @i @Bterm.node@ = new_node(OP_Greater, @Term.node@, @Term.1.node@); + @i @Bterm.if_out@ = @Bterm.if_in@; + @i @Bterm.has_call@ = @Term.has_call@ || @Term.1.has_call@; + + @reg @Term.node@->reg = @Bterm.node@->reg; @Term.1.node@->reg = get_next_reg(@Bterm.node@->reg, 0); + + @codegen /* write_tree(@Term.node@, 0); */ burm_label(@Term.node@); burm_reduce(@Term.node@, 1); /* write_tree(@Term.1.node@, 0); */ burm_label(@Term.1.node@); burm_reduce(@Term.1.node@, 1); printf(@Bterm.negated2@ ? "\tcmp %%%s, %%%s\n\tjs %s # %s %s %i %i\n" : "\tcmp %%%s, %%%s\n\tjns %s # %s %s %i %i\n", @Term.1.node@->reg, @Term.node@->reg, ((@Bterm.negated2@ ^ @Bterm.negated@)) ? @Bterm.jump_false@ : @Bterm.jump_true@, @Bterm.jump_true@, @Bterm.jump_false@, @Bterm.negated2@, @Bterm.negated@); + @} + + | Term '=' Term + @{ + @i @Bterm.node@ = new_node(OP_Equal, @Term.node@, @Term.1.node@); + @i @Bterm.if_out@ = @Bterm.if_in@; + @i @Bterm.has_call@ = @Term.has_call@ || @Term.1.has_call@; + + @reg @Term.node@->reg = @Bterm.node@->reg; @Term.1.node@->reg = get_next_reg(@Bterm.node@->reg, 0); + + @codegen /* write_tree(@Term.node@, 0); */ burm_label(@Term.node@); burm_reduce(@Term.node@, 1); /* write_tree(@Term.1.node@, 0); */ burm_label(@Term.1.node@); burm_reduce(@Term.1.node@, 1); printf(@Bterm.negated2@ ? "\tcmp %%%s, %%%s\n\tjnz %s # %s %s %i %i\n" : "\tcmp %%%s, %%%s\n\tjz %s # %s %s %i %i\n", @Term.node@->reg, @Term.1.node@->reg, ((@Bterm.negated2@ ^ @Bterm.negated@)) ? @Bterm.jump_false@ : @Bterm.jump_true@, @Bterm.jump_true@, @Bterm.jump_false@, @Bterm.negated2@, @Bterm.negated@); + @} + + | '(' Subbool ')' + @{ + @i @Subbool.negated@ = @Bterm.negated@; + @i @Subbool.negated2@ = @Bterm.negated2@; + @i @Subbool.top_level@ = @Bterm.top_level@; + @} + + ; + +Field: Term '.' ID + @{ + @i @Field.node@ = new_node_value(OP_Field, @Term.node@, new_named_leaf(OP_ID, @ID.name@), table_lookup(@Field.symbols@, @ID.name@)==(struct symbol_t *)NULL ? 0 : table_lookup(@Field.symbols@, @ID.name@)->stack_offset, -1); + + @check check_field(@Field.symbols@, @ID.name@); + + @reg @Term.node@->reg = @Field.node@->reg; @Field.node@->kids[1]->reg = get_next_reg(@Field.node@->reg, 0); + @} + + ; + +Call: ID '(' Exprs ')' + @{ + @i @Call.node@ = new_named_node(OP_Call, @Exprs.node@, (treenode *)NULL, @ID.name@); + @i @Call.has_call@ = 1; + + @reg saved_reg = @Call.node@->reg; @Exprs.node@->reg = "rdi"; @Exprs.node@->name=@Call.node@->name; + + @codegen /* reg_return=@Call.node@->reg; function_name = @ID.name@; prepare_call(function_name); */ + @} + + | ID '(' ')' + @{ + @i @Call.node@ = new_node(OP_CallNoParam, (treenode *)NULL, (treenode *)NULL); + @i @Call.has_call@ = 1; + + @codegen /* reg_return=@Call.node@->reg; do_call(@ID.name@); */ + @} + + ; + +Exprs: Expr + @{ + @i @Exprs.node@ = new_node(OP_Arg, @Expr.node@, (treenode *)NULL); + + @reg @Expr.node@->reg = @Exprs.node@->reg; + + @codegen /* write_tree(@Expr.node@); */ /* burm_label(@Expr.node@); burm_reduce(@Expr.node@, 1); do_call(function_name); */ + @} + + | Expr ',' Exprs + @{ + @i @Exprs.node@ = new_node(OP_Exprs, new_node(OP_Arg, @Expr.node@, (treenode *)NULL), @Exprs.1.node@); + @i @Exprs.has_call@ = @Exprs.1.has_call@ || @Expr.has_call@; + + @reg @Expr.node@->reg = @Exprs.node@->reg; @Exprs.1.node@->reg = get_next_param_reg(@Exprs.node@->reg); @Exprs.node@->kids[0]->name = @Exprs.node@->name; @Exprs.1.node@->name = @Exprs.node@->name; + + @codegen /* write_tree(@Expr.node@); */ /* burm_label(@Expr.node@); burm_reduce(@Expr.node@, 1); */ + @} + + ; + +%% + +extern int yylex(); +extern int yylineno; + +int yyerror(char *error_text) { + fprintf(stderr,"Line %i: %s\n",yylineno, error_text); + exit(2); +} + +int main(int argc, char **argv) { + yyparse(); + return 0; +} +