585b19be4f86f2e0addba192f350665ac6285035
[uebersetzerbau-ss10.git] / aus_sammelwut / paulchen / ublu / ss08 / abgabe / gesamt / .svn / text-base / parser.y.svn-base
1 %{
2         #include <stdio.h>
3         #include <stdlib.h>
4         #include <string.h>
5         #include "symbol_table.h"
6         #include "code_gen.h"
7         #include "tree.h"
8
9         #define imm_prefix "$"
10
11         char *saved_reg;
12
13 /* TODO failed test case: func f(a) if not (a=0 or a=1) then return 0; end; end; */
14 %}
15
16 %start          Input
17 %token          FUNC END STRUCT VAR IF THEN ELSE WHILE DO RETURN OR NOT
18 %token          ID NUM ASSIGN GREATER
19
20 @autoinh symbols stack_offset all_pars if_in jump_true jump_false
21 @autosyn node defined_vars immediate if_out has_call
22
23 @attributes     { char *name; } ID
24 @attributes     { long value; } NUM
25 @attributes     { struct symbol_t *fields; struct symbol_t *symbols; int if_in; } Program
26 @attributes     { struct symbol_t *fields; } Structdef
27 @attributes     { struct symbol_t *fields; int offset; } Ids
28 @attributes     { struct symbol_t *pars; int num_pars; int all_pars; } Pars
29 @attributes     { struct symbol_t *symbols; int defined_vars; int if_in; int if_out; } Funcdef 
30 @attributes     { struct symbol_t *symbols; int defined_vars; int stack_offset; treenode *node; int if_in; int if_out; int has_call; } Stats
31 @attributes     { struct symbol_t *symbols; treenode *node; int immediate; int has_call; } Expr Term Plusterm Malterm
32 @attributes     { struct symbol_t *symbols; treenode *node; int has_call; } Call Lexpr Field Exprs
33 @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
34 @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
35 @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
36
37 @traversal @postorder check
38 @traversal @preorder reg
39 @traversal @preorder codegen
40
41 %%
42
43 Input:            Program
44                 @{
45                    @i @Program.symbols@ = @Program.fields@;
46                    @i @Program.if_in@ = 0;
47
48                    @codegen printf("\t.text\n");
49                 @}
50
51                 ;
52
53 Program:          Funcdef ';' Program
54                 @{
55                    @i @Program.fields@ = @Program.1.fields@;
56                    @i @Program.1.if_in@ = @Funcdef.if_out@;
57                 @}
58
59                 | Structdef ';' Program
60                 @{
61                    @i @Program.fields@ = table_merge(@Structdef.fields@, @Program.1.fields@, 1);
62                    @i @Program.1.symbols@ = @Program.0.symbols@;
63                 @}
64
65                 |
66                 @{ @i @Program.fields@ = new_table(); @}
67
68                 ;
69  
70 Funcdef:          FUNC ID '(' Pars ')' Stats END
71                 @{
72                    @i @Stats.symbols@ = table_merge(@Funcdef.symbols@, @Pars.pars@, 0);
73                    @i @Stats.stack_offset@ = 0;
74                    @i @Pars.all_pars@ = @Pars.num_pars@;
75
76                    @codegen function_header(@ID.name@, @Funcdef.defined_vars@, @Stats.has_call@, @Pars.num_pars@);
77                 @}
78
79                 | FUNC ID '(' ')' Stats END
80                 @{
81                    @i @Stats.symbols@ = table_merge(@Funcdef.symbols@, new_table(), 0);
82                    @i @Stats.stack_offset@ = 0;
83
84                    @codegen function_header(@ID.name@, @Funcdef.defined_vars@, @Stats.has_call@, 0);
85                 @}
86
87                 ;  
88  
89 Structdef:        STRUCT Ids END
90                 @{
91                    @i @Structdef.fields@ = @Ids.fields@;
92                    @i @Ids.offset@ = 0;
93                 @}
94
95                 ;  
96
97 Ids:              ID Ids
98                 @{
99                    @i @Ids.fields@ = table_add_symbol(@Ids.1.fields@, @ID.name@, SYMBOL_TYPE_FIELD, 1, @Ids.offset@);
100                    @i @Ids.1.offset@ = @Ids.offset@ + 1;
101                 @}
102
103                 |
104                 @{ @i @Ids.fields@ = new_table(); @}
105
106                 ;
107
108 Pars:             Pars ',' ID
109                 @{
110                    @i @Pars.pars@ = table_add_param(@Pars.1.pars@, @ID.name@, @Pars.num_pars@);
111                    @i @Pars.num_pars@ = @Pars.1.num_pars@ + 1;
112                 @}
113
114                 | ID
115                 @{
116                    @i @Pars.pars@ = table_add_param(new_table(), @ID.name@, 1);
117                    @i @Pars.num_pars@ = 1;
118                 @}
119
120                 ; 
121  
122 Stats:            Stat ';' Stats
123                 @{
124                    @i @Stat.in_symbols@ = @Stats.symbols@;
125                    @i @Stats.1.symbols@ = @Stat.out_symbols@;
126                    @i @Stats.defined_vars@ = @Stat.defined_vars@ + @Stats.1.defined_vars@;
127                    @i @Stats.1.stack_offset@ = @Stats.stack_offset@ + @Stat.defined_vars@ * 8;
128                    @i @Stats.node@ = new_node(OP_Stats, @Stat.node@, @Stats.1.node@);
129                    @i @Stat.if_in@ = @Stats.if_in@;
130                    @i @Stats.1.if_in@ = @Stat.if_out@;
131                    @i @Stats.if_out@ = @Stats.1.if_out@;
132                    @i @Stats.has_call@ = @Stat.has_call@ || @Stats.1.has_call@;
133                 @}
134
135                 |
136                 @{
137                    @i @Stats.node@ = new_leaf(OP_Empty); /* TODO */
138                    @i @Stats.defined_vars@ = 0;
139                    @i @Stats.if_out@ = @Stats.if_in@;
140                    @i @Stats.has_call@ = 0;
141                 @}
142
143                 ;  
144  
145 Stat:             VAR ID ASSIGN Expr /* Nodes necessary for IF, DO, ... ? */
146                 @{
147                    @i @Stat.out_symbols@ = table_add_symbol(clone_table(@Stat.in_symbols@), @ID.name@, SYMBOL_TYPE_VAR, 0, @Stat.stack_offset@);
148                    @i @Expr.symbols@ = @Stat.in_symbols@;
149                    @i @Stat.node@ = new_node(OP_Assign, new_named_leaf_value(OP_ID, @ID.name@, @Stat.stack_offset@, -1), @Expr.node@);
150                    @i @Stat.defined_vars@ = 1;
151                    @i @Stat.if_out@ = @Stat.if_in@;
152
153                    @reg @Expr.node@->reg = get_next_reg((char *)NULL, 0); @Stat.node@->reg = @Expr.node@->reg;
154
155                    @codegen /* write_tree(@Stat.node@, 0); */ burm_label(@Stat.node@); burm_reduce(@Stat.node@, 1);
156                 @}
157
158                 | Lexpr ASSIGN Expr
159                 @{
160                    @i @Stat.out_symbols@ = @Stat.in_symbols@;
161                    @i @Lexpr.symbols@ = @Stat.in_symbols@;
162                    @i @Expr.symbols@ = @Stat.in_symbols@;
163                    @i @Stat.node@ = new_node(OP_Assign, @Lexpr.node@, @Expr.node@);
164                    @i @Stat.defined_vars@ = 0;
165                    @i @Stat.if_out@ = @Stat.if_in@;
166                    @i @Stat.has_call@ = @Lexpr.has_call@ || @Expr.has_call@;
167
168                    @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;
169
170                    @codegen /* write_tree(@Stat.node@, 0); */ burm_label(@Stat.node@); burm_reduce(@Stat.node@, 1);
171                 @}
172
173                 | IF Bool THEN Stats END
174                 @{
175                    @i @Bool.symbols@ = @Stat.in_symbols@;
176                    @i @Stats.symbols@ = @Stat.in_symbols@;
177                    @i @Stat.out_symbols@ = @Stat.in_symbols@;
178                    @i @Stat.node@ = new_node(OP_If, @Bool.node@, @Stats.node@);
179                    @i @Bool.if_in@ = @Stat.if_in@ + 1;
180                    @i @Stats.if_in@ = @Bool.if_out@;
181                    @i @Stat.if_out@ = @Stats.if_out@;
182                    @e Bool.jump_true : Stats.if_in; @Bool.jump_true@ = malloc(100); sprintf(@Bool.jump_true@, "if_then%i", @Stats.if_in@);
183                    @e Bool.jump_false : Stats.if_in; @Bool.jump_false@ = malloc(100); sprintf(@Bool.jump_false@, "if_end%i", @Stats.if_in@);
184                    @i @Stat.has_call@ = @Bool.has_call@ || @Stats.has_call@;
185
186                    @reg @Bool.node@->reg = get_next_reg((char *)NULL, 0);
187
188                    @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@); */
189                    @codegen @revorder(1) printf("if_end%i:\n", @Stats.if_in@);
190                 @}
191
192                 | IF Bool THEN Stats Blubb END 
193                 @{
194                    @i @Bool.symbols@ = @Stat.in_symbols@;
195                    @i @Blubb.symbols@ = @Stat.in_symbols@;
196                    @i @Stat.out_symbols@ = @Stat.in_symbols@;              
197                    @i @Stats.symbols@ = @Stat.in_symbols@;
198                    @i @Stat.node@ = new_node(OP_Ifstats, @Stats.node@, @Blubb.node@);
199                    @i @Stat.defined_vars@ = @Stats.defined_vars@ + @Blubb.defined_vars@;
200                    @i @Bool.if_in@ = @Stat.if_in@ + 1;
201                    @i @Stats.if_in@ = @Bool.if_out@;
202                    @i @Blubb.if_in@ = @Stats.if_out@;
203                    @i @Stat.if_out@ = @Blubb.if_out@;
204                    @i @Blubb.if_nr@ = @Stats.if_in@;
205                    @e Bool.jump_true : Stats.if_in; @Bool.jump_true@ = malloc(100); sprintf(@Bool.jump_true@, "if_then%i", @Stats.if_in@);
206                    @e Bool.jump_false : Stats.if_in; @Bool.jump_false@ = malloc(100); sprintf(@Bool.jump_false@, "if_else%i", @Stats.if_in@);
207                    @i @Stat.has_call@ = @Bool.has_call@ || @Stats.has_call@ || @Blubb.has_call@;
208
209                    @reg @Bool.node@->reg = get_next_reg((char *)NULL, 0);
210
211                    @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@); */
212                    @codegen @revorder(1) printf("if_end%i:\n", @Stats.if_in@);
213                 @}
214
215                 | WHILE Bool DO Stats END
216                 @{
217                    @i @Bool.symbols@ = @Stat.in_symbols@;
218                    @i @Stats.symbols@ = @Stat.in_symbols@;
219                    @i @Stat.out_symbols@ = @Stat.in_symbols@;
220                    @i @Stat.node@ = new_node(OP_While, @Bool.node@, @Stats.node@);
221                    @i @Bool.if_in@ = @Stat.if_in@ + 1;
222                    @i @Stats.if_in@ = @Bool.if_out@;
223                    @i @Stat.if_out@ = @Stats.if_out@;
224                    @e Bool.jump_true : Stats.if_in; @Bool.jump_true@ = malloc(100); sprintf(@Bool.jump_true@, "do_enter%i", @Stats.if_in@);
225                    @e Bool.jump_false : Stats.if_in; @Bool.jump_false@ = malloc(100); sprintf(@Bool.jump_false@, "do_end%i", @Stats.if_in@);
226                    @i @Stat.has_call@ = @Bool.has_call@ || @Stats.has_call@;
227
228                    @reg @Bool.node@->reg = get_next_reg((char *)NULL, 0);
229
230                    @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@); */
231                    @codegen @revorder(1) printf("\tjmp do_start%i\ndo_end%i:\n", @Stats.if_in@, @Stats.if_in@);
232                 @}
233
234                 | Call
235                 @{
236                    @i @Call.symbols@ = @Stat.in_symbols@;
237                    @i @Stat.out_symbols@ = @Stat.in_symbols@;
238                    @i @Stat.node@ = (treenode *)NULL;
239                    @i @Stat.defined_vars@ = 0;
240                    @i @Stat.if_out@ = @Stat.if_in@;
241
242                    @reg @Call.node@->reg = "rax";
243                 @}
244
245                 | RETURN Expr
246                 @{
247                    @i @Expr.symbols@ = @Stat.in_symbols@;
248                    @i @Stat.out_symbols@ = @Stat.in_symbols@;
249                    @i @Stat.node@ = new_node(OP_Return, @Expr.node@, (treenode *)NULL);
250                    @i @Stat.defined_vars@ = 0;
251                    @i @Stat.if_out@ = @Stat.if_in@;
252
253                    @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;
254
255                    @codegen /* write_tree(@Stat.node@, 0); */ burm_label(@Stat.node@); burm_reduce(@Stat.node@, 1);
256                 @}
257
258                 ;
259
260 Blubb:            ELSE Stats
261                 @{
262                    @codegen printf("\tjmp if_end%i\nif_else%i:\n", @Blubb.if_nr@, @Blubb.if_nr@);
263                 @}
264
265 Lexpr:            ID
266                 @{
267                    @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);
268
269                    @i @Lexpr.has_call@ = 0;
270                    @check check_variable(@Lexpr.symbols@, @ID.name@);
271                 @}
272
273                 | Field
274                 ;
275  
276 Expr:             '-' Term
277                 @{
278                    @i @Expr.node@ = new_node(OP_Negation, @Term.node@, (treenode *)NULL);
279
280                    @reg @Term.node@->reg = @Expr.node@->reg;
281                 @}
282
283                 | Term
284                 @{ @reg @Term.node@->reg = @Expr.node@->reg; @}
285
286                 | Term Plusterm
287                 @{
288                    @i @Expr.node@ = new_node(OP_Addition, @Plusterm.node@, @Term.node@);
289                    @i @Expr.immediate@ = @Term.immediate@ && @Plusterm.immediate@;
290                    @i @Expr.has_call@ = @Term.has_call@ || @Plusterm.has_call@;
291
292                    @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); }
293                 @}
294
295                 | Term Malterm
296                 @{
297                    @i @Expr.node@ = new_node(OP_Multiplication, @Malterm.node@, @Term.node@);
298                    @i @Expr.immediate@ = @Term.immediate@ && @Malterm.immediate@;
299                    @i @Expr.has_call@ = @Term.has_call@ || @Malterm.has_call@;
300
301                    @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); }
302                 @}
303
304                 ;
305
306 Plusterm:         '+' Term Plusterm
307                 @{
308                    @i @Plusterm.node@ = new_node(OP_Addition, @Plusterm.1.node@, @Term.node@);
309                    @i @Plusterm.immediate@ = @Term.immediate@ && @Plusterm.1.immediate@;
310                    @i @Plusterm.has_call@ = @Term.has_call@ || @Plusterm.1.has_call@;
311
312                    @reg @Plusterm.1.node@->reg = @Plusterm.node@->reg; @Term.node@->reg = get_next_reg(@Plusterm.1.node@->reg, @Plusterm.node@->skip_reg); 
313                 @}
314
315                 | '+' Term
316                 @{ @reg @Term.node@->reg = @Plusterm.node@->reg; @}
317
318                 ;
319
320 Malterm:          '*' Term Malterm
321                 @{
322                    @i @Malterm.node@ = new_node(OP_Multiplication, @Malterm.1.node@, @Term.node@);
323                    @i @Malterm.immediate@ = @Term.immediate@ && @Malterm.1.immediate@;
324                    @i @Malterm.has_call@ = @Term.has_call@ || @Malterm.1.has_call@;
325
326                    @reg @Malterm.1.node@->reg = @Malterm.node@->reg; @Term.node@->reg = get_next_reg(@Malterm.1.node@->reg, @Malterm.node@->skip_reg); 
327                 @}
328
329                 | '*' Term
330                 @{ @reg @Term.node@->reg = @Malterm.node@->reg; @}
331
332                 ;
333  
334 Term:             '(' Expr ')'
335                 @{ @reg @Expr.node@->reg = @Term.node@->reg; @}
336
337                 | ID
338                 @{
339                    @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);
340                    @i @Term.immediate@ = 0;
341                    @i @Term.has_call@ = 0;
342
343                    @check check_variable(@Term.symbols@, @ID.name@);
344                 @}
345
346                 | NUM
347                 @{
348                    @i @Term.node@ = new_number_leaf(@NUM.value@);
349                    @i @Term.immediate@ = 1;
350                    @i @Term.has_call@ = 0;
351                 @}
352
353                 | Call
354                 @{
355                    @i @Term.immediate@ = 0;
356
357                    @reg @Call.node@->reg = @Term.node@->reg;
358                 @}
359
360                 | Field
361                 @{
362                    @i @Term.immediate@ = 0;
363
364                    @reg @Field.node@->reg = @Term.node@->reg;
365                 @}
366
367                 ;
368
369 /* TODO replace by Bool -> Subbool */
370 Bool:             Bterm
371                 @{
372                    @i @Bool.negated@ = 0;
373                    @i @Bool.negated2@ = 0;
374                    @i @Bterm.negated@ = 0;
375                    @i @Bterm.negated2@ = 0;
376                    @i @Bool.top_level@ = 1;
377                    @i @Bterm.top_level@ = 1;
378
379                    @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@); */
380                 @}
381
382                 | Bterm Orterm
383                 @{
384                    @i @Bool.node@ = new_node(OP_Disjunction, @Bterm.node@, @Orterm.node@);
385                    @i @Bool.negated@ = 0;
386                    @i @Bool.negated2@ = 0;
387                    @i @Bterm.negated@ = 0;
388                    @i @Orterm.negated@ = 0;
389                    @i @Bterm.negated2@ = 0;
390                    @i @Orterm.negated2@ = 0;
391                    @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@; }
392                    @i @Orterm.jump_true@ = @Bterm.jump_true@;
393                    @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@; }
394                    @i @Orterm.jump_false@ = @Bterm.jump_false@;
395                    @i @Bterm.if_in@ = @Bool.if_in@ + 1;
396                    @i @Orterm.if_in@ = @Bterm.if_out@;
397                    @i @Bool.if_out@ = @Orterm.if_out@;
398                    @i @Bterm.top_level@ = 0;
399                    @i @Orterm.top_level@ = 0;
400                    @i @Bool.top_level@ = 1;
401                    @i @Bool.has_call@ = @Bterm.has_call@ || @Orterm.has_call@;
402
403                    @reg @Bterm.node@->reg = @Bool.node@->reg; @Orterm.node@->reg = @Bool.node@->reg;
404
405                    @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@); */
406                 @}
407
408                 | NOT Bterm
409                 @{
410                    @i @Bool.node@ = new_node(OP_Not, @Bterm.node@, (treenode *)NULL);
411                    @i @Bterm.jump_true@ = @Bool.jump_true@;
412                    @i @Bool.negated@ = 0;
413                    @i @Bool.negated2@ = 0;
414                    @i @Bterm.negated@ = 1;
415                    @i @Bterm.negated2@ = 1;
416                    @i @Bterm.top_level@ = 0;
417                    @i @Bool.top_level@ = 1;
418
419                    @reg @Bterm.node@-> reg = @Bool.node@->reg;
420
421                    @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@); */
422                 @}
423
424                 ;
425
426 Subbool:          Bterm
427                 @{
428                    @i @Bterm.negated@ = @Subbool.negated@;
429                    @i @Bterm.negated2@ = @Subbool.negated2@;
430                    @i @Bterm.top_level@ = @Subbool.top_level@;
431                    @codegen @revorder(1) /* printf("\tjmp %s\n%s:\n", @Subbool.jump_false@, @Subbool.jump_true@); */
432                 @}
433
434                 | Bterm Orterm
435                 @{
436                    @i @Subbool.node@ = new_node(OP_Disjunction, @Bterm.node@, @Orterm.node@);
437                    @i @Bterm.negated@ = @Subbool.negated@;
438                    @i @Orterm.negated@ = @Subbool.negated@;
439                    @i @Bterm.negated2@ = 0;
440                    @i @Orterm.negated2@ = 0;
441                    @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@; }
442                    @i @Orterm.jump_true@ = @Bterm.jump_true@;
443                    @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@; }
444                    @i @Orterm.jump_false@ = @Bterm.jump_false@;
445                    @i @Bterm.if_in@ = @Subbool.if_in@ + 1;
446                    @i @Orterm.if_in@ = @Bterm.if_out@;
447                    @i @Subbool.if_out@ = @Orterm.if_out@;
448                    @i @Bterm.top_level@ = 0;
449                    @i @Orterm.top_level@ = 0;
450                    @i @Subbool.has_call@ = @Bterm.has_call@ || @Orterm.has_call@;
451
452                    @reg @Bterm.node@->reg = @Subbool.node@->reg; @Orterm.node@->reg = @Subbool.node@->reg;
453
454                    @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@);  */
455                 @}
456
457                 | NOT Bterm
458                 @{
459                    @i @Subbool.node@ = new_node(OP_Not, @Bterm.node@, (treenode *)NULL);
460                    @i @Bterm.jump_true@ = @Subbool.jump_true@;
461                    @i @Bterm.negated@ = 1 - @Subbool.negated@;
462                    @i @Bterm.negated2@ = 1 - @Subbool.negated2@;
463                    @i @Bterm.top_level@ = 0;
464
465                    @reg @Bterm.node@-> reg = @Subbool.node@->reg; /* printf("%s, %s\n", @Bterm.jump_true@, @Subbool.jump_false@); */
466
467                    @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@); */
468                 @}
469
470                 ;
471
472
473 Orterm:           OR Bterm Orterm
474                 @{
475                    @i @Orterm.node@ = new_node(OP_Disjunction, @Bterm.node@, @Orterm.1.node@);
476                    @i @Bterm.negated@ = @Orterm.negated@;
477                    @i @Orterm.1.negated@ = @Orterm.negated@;
478                    @i @Bterm.negated2@ = 0;
479                    @i @Orterm.1.negated2@ = 0;
480                    @i @Orterm.1.if_in@ = @Bterm.if_out@;
481                    @i @Orterm.if_out@ = @Orterm.1.if_out@;
482                    @i @Bterm.top_level@ = 0;
483                    @i @Orterm.1.top_level@ = 0;
484                    @i @Orterm.has_call@ = @Bterm.has_call@ || @Orterm.1.has_call@;
485
486                    @reg @Bterm.node@->reg = @Orterm.node@->reg; @Orterm.1.node@->reg = @Orterm.node@->reg;
487                 @}
488
489                 | OR Bterm
490                 @{
491                    @i @Bterm.negated@ = @Orterm.negated@;
492                    @i @Bterm.negated2@ = @Orterm.negated2@;
493                    @i @Bterm.top_level@ = 0;
494                 @}
495
496                 ;
497
498 Bterm:            Term GREATER Term
499                 @{
500                    @i @Bterm.node@ = new_node(OP_Greater, @Term.node@, @Term.1.node@);
501                    @i @Bterm.if_out@ = @Bterm.if_in@;
502                    @i @Bterm.has_call@ = @Term.has_call@ || @Term.1.has_call@;
503                    
504                    @reg @Term.node@->reg = @Bterm.node@->reg; @Term.1.node@->reg = get_next_reg(@Bterm.node@->reg, 0);
505
506                    @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@);
507                 @}
508
509                 | Term '=' Term
510                 @{
511                    @i @Bterm.node@ = new_node(OP_Equal, @Term.node@, @Term.1.node@);
512                    @i @Bterm.if_out@ = @Bterm.if_in@;
513                    @i @Bterm.has_call@ = @Term.has_call@ || @Term.1.has_call@;
514
515                    @reg @Term.node@->reg = @Bterm.node@->reg; @Term.1.node@->reg = get_next_reg(@Bterm.node@->reg, 0);
516
517                    @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@);
518                 @}
519
520                 | '(' Subbool ')'
521                 @{
522                    @i @Subbool.negated@ = @Bterm.negated@;
523                    @i @Subbool.negated2@ = @Bterm.negated2@;
524                    @i @Subbool.top_level@ = @Bterm.top_level@;
525                 @}
526
527                 ;
528
529 Field:            Term '.' ID
530                 @{
531                    @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);
532
533                    @check check_field(@Field.symbols@, @ID.name@);
534
535                    @reg @Term.node@->reg = @Field.node@->reg; @Field.node@->kids[1]->reg = get_next_reg(@Field.node@->reg, 0); 
536                 @}
537
538                 ;
539
540 Call:             ID '(' Exprs ')'
541                 @{
542                    @i @Call.node@ = new_named_node(OP_Call, @Exprs.node@, (treenode *)NULL, @ID.name@);
543                    @i @Call.has_call@ = 1;
544
545                    @reg saved_reg = @Call.node@->reg; @Exprs.node@->reg = "rdi"; @Exprs.node@->name=@Call.node@->name;
546
547                    @codegen /* reg_return=@Call.node@->reg; function_name = @ID.name@; prepare_call(function_name); */
548                 @}
549
550                 | ID '(' ')'
551                 @{
552                    @i @Call.node@ = new_node(OP_CallNoParam, (treenode *)NULL, (treenode *)NULL);
553                    @i @Call.has_call@ = 1;
554
555                    @codegen /* reg_return=@Call.node@->reg; do_call(@ID.name@); */
556                 @}
557
558                 ;
559
560 Exprs:            Expr
561                 @{
562                    @i @Exprs.node@ = new_node(OP_Arg, @Expr.node@, (treenode *)NULL);
563                    
564                    @reg @Expr.node@->reg = @Exprs.node@->reg;
565
566                    @codegen /* write_tree(@Expr.node@); */ /* burm_label(@Expr.node@); burm_reduce(@Expr.node@, 1); do_call(function_name); */
567                 @}
568
569                 | Expr ',' Exprs
570                 @{
571                    @i @Exprs.node@ = new_node(OP_Exprs, new_node(OP_Arg, @Expr.node@, (treenode *)NULL), @Exprs.1.node@);
572                    @i @Exprs.has_call@ = @Exprs.1.has_call@ || @Expr.has_call@;
573
574                    @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;
575
576                    @codegen /* write_tree(@Expr.node@); */ /* burm_label(@Expr.node@); burm_reduce(@Expr.node@, 1); */
577                 @}
578
579                 ;
580
581 %%
582
583 extern int yylex();
584 extern int yylineno;
585
586 int yyerror(char *error_text) {
587         fprintf(stderr,"Line %i: %s\n",yylineno, error_text);
588         exit(2);
589 }
590
591 int main(int argc, char **argv) {
592         yyparse();
593         return 0;
594 }
595