5 #include "symbol_table.h"
11 %token FUNC END STRUCT VAR IF THEN ELSE WHILE DO RETURN OR NOT
12 %token ID NUM ASSIGN GREATER
14 @autoinh symbols stack_offset all_pars
15 @autosyn node defined_vars immediate
17 @attributes { char *name; } ID
18 @attributes { long value; } NUM
19 @attributes { struct symbol_t *fields; struct symbol_t *symbols; } Program
20 @attributes { struct symbol_t *fields; } Structdef
21 @attributes { struct symbol_t *fields; int offset; } Ids
22 @attributes { struct symbol_t *pars; int num_pars; int all_pars; } Pars
23 @attributes { struct symbol_t *symbols; int defined_vars; } Funcdef
24 @attributes { struct symbol_t *symbols; int defined_vars; int stack_offset; } Stats
25 @attributes { struct symbol_t *symbols; treenode *node; int immediate; } Expr Term Plusterm Malterm
26 @attributes { struct symbol_t *symbols; treenode *node; } Bool Call Lexpr Field Bterm Orterm Exprs
27 @attributes { struct symbol_t *in_symbols; struct symbol_t *out_symbols; treenode *node; int defined_vars; int stack_offset; } Stat
29 @traversal @postorder check
30 @traversal @preorder reg
31 @traversal @postorder codegen
37 @i @Program.symbols@ = @Program.fields@;
39 @codegen @revorder(1) printf("\t.text\n");
44 Program: Funcdef ';' Program
46 @i @Program.fields@ = @Program.1.fields@;
49 | Structdef ';' Program
51 @i @Program.fields@ = table_merge(@Structdef.fields@, @Program.1.fields@, 1);
52 @i @Program.1.symbols@ = @Program.0.symbols@;
56 @{ @i @Program.fields@ = new_table(); @}
60 Funcdef: FUNC ID '(' Pars ')' Stats END
62 @i @Stats.symbols@ = table_merge(@Funcdef.symbols@, @Pars.pars@, 0);
63 @i @Stats.stack_offset@ = 0;
64 @i @Pars.all_pars@ = @Pars.num_pars@;
66 @codegen @revorder(1) function_header(@ID.name@);
69 | FUNC ID '(' ')' Stats END
71 @i @Stats.symbols@ = table_merge(@Funcdef.symbols@, new_table(), 0);
72 @i @Stats.stack_offset@ = 0;
74 @codegen @revorder(1) function_header(@ID.name@);
79 Structdef: STRUCT Ids END
81 @i @Structdef.fields@ = @Ids.fields@;
89 @i @Ids.fields@ = table_add_symbol(@Ids.1.fields@, @ID.name@, SYMBOL_TYPE_FIELD, 1, @Ids.offset@);
90 @i @Ids.1.offset@ = @Ids.offset@ + 1;
94 @{ @i @Ids.fields@ = new_table(); @}
100 @i @Pars.pars@ = table_add_param(@Pars.1.pars@, @ID.name@, @Pars.num_pars@);
101 @i @Pars.num_pars@ = @Pars.1.num_pars@ + 1;
106 @i @Pars.pars@ = table_add_param(new_table(), @ID.name@, 1);
107 @i @Pars.num_pars@ = 1;
112 Stats: Stat ';' Stats
114 @i @Stat.in_symbols@ = @Stats.symbols@;
115 @i @Stats.1.symbols@ = @Stat.out_symbols@;
116 @i @Stats.defined_vars@ = @Stat.defined_vars@ + @Stats.1.defined_vars@;
117 @i @Stats.1.stack_offset@ = @Stats.stack_offset@ + @Stat.defined_vars@ * 8;
119 @codegen /* write_tree(@Stat.node@, 0); */ burm_label(@Stat.node@); burm_reduce(@Stat.node@, 1);
123 @{ @i @Stats.defined_vars@ = 0; @}
127 Stat: VAR ID ASSIGN Expr
129 @i @Stat.out_symbols@ = table_add_symbol(clone_table(@Stat.in_symbols@), @ID.name@, SYMBOL_TYPE_VAR, 0, 0);
130 @i @Expr.symbols@ = @Stat.in_symbols@;
131 @i @Stat.node@ = (treenode *)NULL;
132 @i @Stat.defined_vars@ = 1;
137 @i @Stat.out_symbols@ = @Stat.in_symbols@;
138 @i @Lexpr.symbols@ = @Stat.in_symbols@;
139 @i @Expr.symbols@ = @Stat.in_symbols@;
140 @i @Stat.node@ = (treenode *)NULL;
141 @i @Stat.defined_vars@ = 0;
144 | IF Bool THEN Stats END
146 @i @Bool.symbols@ = @Stat.in_symbols@;
147 @i @Stats.symbols@ = @Stat.in_symbols@;
148 @i @Stat.out_symbols@ = @Stat.in_symbols@;
149 @i @Stat.node@ = (treenode *)NULL;
152 | IF Bool THEN Stats ELSE Stats END
154 @i @Bool.symbols@ = @Stat.in_symbols@;
155 @i @Stats.symbols@ = @Stat.in_symbols@;
156 @i @Stats.1.symbols@ = @Stat.in_symbols@;
157 @i @Stat.out_symbols@ = @Stat.in_symbols@;
158 @i @Stat.node@ = (treenode *)NULL;
159 @i @Stat.defined_vars@ = @Stats.defined_vars@ + @Stats.1.defined_vars@;
162 | WHILE Bool DO Stats END
164 @i @Bool.symbols@ = @Stat.in_symbols@;
165 @i @Stats.symbols@ = @Stat.in_symbols@;
166 @i @Stat.out_symbols@ = @Stat.in_symbols@;
167 @i @Stat.node@ = (treenode *)NULL;
172 @i @Call.symbols@ = @Stat.in_symbols@;
173 @i @Stat.out_symbols@ = @Stat.in_symbols@;
174 @i @Stat.node@ = (treenode *)NULL;
175 @i @Stat.defined_vars@ = 0;
180 @i @Expr.symbols@ = @Stat.in_symbols@;
181 @i @Stat.out_symbols@ = @Stat.in_symbols@;
182 @i @Stat.node@ = new_node(OP_Return, @Expr.node@, (treenode *)NULL);
184 @reg @Stat.node@->reg = get_next_reg((char *)NULL, 0); @Expr.node@->reg = @Stat.node@->reg;
185 @i @Stat.defined_vars@ = 0;
192 @i @Lexpr.node@ = (treenode *)NULL;
193 @check check_variable(@Lexpr.symbols@, @ID.name@);
201 @i @Expr.node@ = new_node(OP_Negation, @Term.node@, (treenode *)NULL);
203 @reg @Term.node@->reg = @Expr.node@->reg;
207 @{ @reg @Term.node@->reg = @Expr.node@->reg; @}
211 @i @Expr.node@ = new_node(OP_Addition, @Plusterm.node@, @Term.node@);
212 @i @Expr.immediate@ = @Term.immediate@ && @Plusterm.immediate@;
214 @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); }
219 @i @Expr.node@ = new_node(OP_Multiplication, @Malterm.node@, @Term.node@);
220 @i @Expr.immediate@ = @Term.immediate@ && @Malterm.immediate@;
222 @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); }
227 Plusterm: '+' Term Plusterm
229 @i @Plusterm.node@ = new_node(OP_Addition, @Plusterm.1.node@, @Term.node@);
230 @i @Plusterm.immediate@ = @Term.immediate@ && @Plusterm.1.immediate@;
232 @reg @Plusterm.1.node@->reg = @Plusterm.node@->reg; @Term.node@->reg = get_next_reg(@Plusterm.1.node@->reg, @Plusterm.node@->skip_reg);
236 @{ @reg @Term.node@->reg = @Plusterm.node@->reg; @}
240 Malterm: '*' Term Malterm
242 @i @Malterm.node@ = new_node(OP_Multiplication, @Malterm.1.node@, @Term.node@);
243 @i @Malterm.immediate@ = @Term.immediate@ && @Malterm.1.immediate@;
245 @reg @Malterm.1.node@->reg = @Malterm.node@->reg; @Term.node@->reg = get_next_reg(@Malterm.1.node@->reg, @Malterm.node@->skip_reg);
249 @{ @reg @Term.node@->reg = @Malterm.node@->reg; @}
254 @{ @reg @Expr.node@->reg = @Term.node@->reg; @}
258 @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);
259 @i @Term.immediate@ = 0;
261 @check check_variable(@Term.symbols@, @ID.name@);
266 @i @Term.node@ = new_number_leaf(@NUM.value@);
267 @i @Term.immediate@ = 1;
271 @{ @i @Term.immediate@ = 0; @}
275 @i @Term.immediate@ = 0;
277 @reg @Field.node@->reg = @Term.node@->reg;
284 @{ @i @Bool.node@ = new_node(OP_Disjunction, @Bterm.node@, @Orterm.node@); @}
287 @{ @i @Bool.node@ = new_node(OP_Not, @Bterm.node@, (treenode *)NULL); @}
291 Orterm: OR Bterm Orterm
292 @{ @i @Orterm.node@ = new_node(OP_Disjunction, @Bterm.node@, @Orterm.1.node@); @}
297 Bterm: Term GREATER Term
298 @{ @i @Bterm.node@ = new_node(OP_Greater, @Term.node@, @Term.1.node@); @}
301 @{ @i @Bterm.node@ = new_node(OP_Equal, @Term.node@, @Term.1.node@); @}
308 @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);
310 @check check_field(@Field.symbols@, @ID.name@);
312 @reg @Term.node@->reg = @Field.node@->reg; @Field.node@->kids[1]->reg = get_next_reg(@Field.node@->reg, 0);
317 Call: ID '(' Exprs ')'
318 @{ @i @Call.node@ = new_node(OP_Call, new_named_leaf(OP_ID, @ID.name@), @Exprs.node@); @}
321 @{ @i @Call.node@ = new_node(OP_Call, new_named_leaf(OP_ID, @ID.name@), NULL); @}
327 @{ @i @Exprs.node@ = new_node(OP_Exprs, @Exprs.1.node@, @Expr.node@); @}
336 int yyerror(char *error_text) {
337 fprintf(stderr,"Line %i: %s\n",yylineno, error_text);
341 int main(int argc, char **argv) {