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