doc: paulchen beispiele {code{a,b},gesamt} entpackt (jedes mal entpacken nervt langsa...
[uebersetzerbau-ss10.git] / aus_sammelwut / paulchen / ublu / ss08 / abgabe / codea / parser.y
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
10 %start          Input
11 %token          FUNC END STRUCT VAR IF THEN ELSE WHILE DO RETURN OR NOT
12 %token          ID NUM ASSIGN GREATER
13
14 @autoinh symbols stack_offset all_pars
15 @autosyn node defined_vars immediate
16
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
28
29 @traversal @postorder check
30 @traversal @preorder reg
31 @traversal @postorder codegen
32
33 %%
34
35 Input:            Program
36                 @{
37                    @i @Program.symbols@ = @Program.fields@;
38
39                    @codegen @revorder(1) printf("\t.text\n");
40                 @}
41
42                 ;
43
44 Program:          Funcdef ';' Program
45                 @{
46                    @i @Program.fields@ = @Program.1.fields@;
47                 @}
48
49                 | Structdef ';' Program
50                 @{
51                    @i @Program.fields@ = table_merge(@Structdef.fields@, @Program.1.fields@, 1);
52                    @i @Program.1.symbols@ = @Program.0.symbols@;
53                 @}
54
55                 |
56                 @{ @i @Program.fields@ = new_table(); @}
57
58                 ;
59  
60 Funcdef:          FUNC ID '(' Pars ')' Stats END
61                 @{
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@;
65
66                    @codegen @revorder(1) function_header(@ID.name@);
67                 @}
68
69                 | FUNC ID '(' ')' Stats END
70                 @{
71                    @i @Stats.symbols@ = table_merge(@Funcdef.symbols@, new_table(), 0);
72                    @i @Stats.stack_offset@ = 0;
73
74                    @codegen @revorder(1) function_header(@ID.name@);
75                 @}
76
77                 ;  
78  
79 Structdef:        STRUCT Ids END
80                 @{
81                    @i @Structdef.fields@ = @Ids.fields@;
82                    @i @Ids.offset@ = 0;
83                 @}
84
85                 ;  
86
87 Ids:              ID Ids
88                 @{
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;
91                 @}
92
93                 |
94                 @{ @i @Ids.fields@ = new_table(); @}
95
96                 ;
97
98 Pars:             Pars ',' ID
99                 @{
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;
102                 @}
103
104                 | ID
105                 @{
106                    @i @Pars.pars@ = table_add_param(new_table(), @ID.name@, 1);
107                    @i @Pars.num_pars@ = 1;
108                 @}
109
110                 ; 
111  
112 Stats:            Stat ';' Stats
113                 @{
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;
118
119                    @codegen /* write_tree(@Stat.node@, 0); */ burm_label(@Stat.node@); burm_reduce(@Stat.node@, 1);
120                 @}
121
122                 |
123                 @{ @i @Stats.defined_vars@ = 0; @}
124
125                 ;  
126  
127 Stat:             VAR ID ASSIGN Expr
128                 @{
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;
133                 @}
134
135                 | Lexpr ASSIGN Expr
136                 @{
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;
142                 @}
143
144                 | IF Bool THEN Stats END
145                 @{
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;
150                 @}
151
152                 | IF Bool THEN Stats ELSE Stats END
153                 @{
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@;
160                 @}
161
162                 | WHILE Bool DO Stats END
163                 @{
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;
168                 @}
169
170                 | Call
171                 @{
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;
176                 @}
177
178                 | RETURN Expr
179                 @{
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);
183
184                    @reg @Stat.node@->reg = get_next_reg((char *)NULL, 0); @Expr.node@->reg = @Stat.node@->reg;
185                    @i @Stat.defined_vars@ = 0;
186                 @}
187
188                 ;
189  
190 Lexpr:            ID
191                 @{
192                    @i @Lexpr.node@ = (treenode *)NULL;
193                    @check check_variable(@Lexpr.symbols@, @ID.name@);
194                 @}
195
196                 | Field
197                 ;
198  
199 Expr:             '-' Term
200                 @{
201                    @i @Expr.node@ = new_node(OP_Negation, @Term.node@, (treenode *)NULL);
202
203                    @reg @Term.node@->reg = @Expr.node@->reg;
204                 @}
205
206                 | Term
207                 @{ @reg @Term.node@->reg = @Expr.node@->reg; @}
208
209                 | Term Plusterm
210                 @{
211                    @i @Expr.node@ = new_node(OP_Addition, @Plusterm.node@, @Term.node@);
212                    @i @Expr.immediate@ = @Term.immediate@ && @Plusterm.immediate@;
213
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); }
215                 @}
216
217                 | Term Malterm
218                 @{
219                    @i @Expr.node@ = new_node(OP_Multiplication, @Malterm.node@, @Term.node@);
220                    @i @Expr.immediate@ = @Term.immediate@ && @Malterm.immediate@;
221
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); }
223                 @}
224
225                 ;
226
227 Plusterm:         '+' Term Plusterm
228                 @{
229                    @i @Plusterm.node@ = new_node(OP_Addition, @Plusterm.1.node@, @Term.node@);
230                    @i @Plusterm.immediate@ = @Term.immediate@ && @Plusterm.1.immediate@;
231
232                    @reg @Plusterm.1.node@->reg = @Plusterm.node@->reg; @Term.node@->reg = get_next_reg(@Plusterm.1.node@->reg, @Plusterm.node@->skip_reg); 
233                 @}
234
235                 | '+' Term
236                 @{ @reg @Term.node@->reg = @Plusterm.node@->reg; @}
237
238                 ;
239
240 Malterm:          '*' Term Malterm
241                 @{
242                    @i @Malterm.node@ = new_node(OP_Multiplication, @Malterm.1.node@, @Term.node@);
243                    @i @Malterm.immediate@ = @Term.immediate@ && @Malterm.1.immediate@;
244
245                    @reg @Malterm.1.node@->reg = @Malterm.node@->reg; @Term.node@->reg = get_next_reg(@Malterm.1.node@->reg, @Malterm.node@->skip_reg); 
246                 @}
247
248                 | '*' Term
249                 @{ @reg @Term.node@->reg = @Malterm.node@->reg; @}
250
251                 ;
252  
253 Term:             '(' Expr ')'
254                 @{ @reg @Expr.node@->reg = @Term.node@->reg; @}
255
256                 | ID
257                 @{
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;
260
261                    @check check_variable(@Term.symbols@, @ID.name@);
262                 @}
263
264                 | NUM
265                 @{
266                    @i @Term.node@ = new_number_leaf(@NUM.value@);
267                    @i @Term.immediate@ = 1;
268                 @}
269
270                 | Call
271                 @{ @i @Term.immediate@ = 0; @}
272
273                 | Field
274                 @{
275                    @i @Term.immediate@ = 0;
276
277                    @reg @Field.node@->reg = @Term.node@->reg;
278                 @}
279
280                 ;
281
282 Bool:             Bterm
283                 | Bterm Orterm
284                 @{ @i @Bool.node@ = new_node(OP_Disjunction, @Bterm.node@, @Orterm.node@); @}
285
286                 | NOT Bterm
287                 @{ @i @Bool.node@ = new_node(OP_Not, @Bterm.node@, (treenode *)NULL); @}
288
289                 ;
290
291 Orterm:           OR Bterm Orterm
292                 @{ @i @Orterm.node@ = new_node(OP_Disjunction, @Bterm.node@, @Orterm.1.node@); @}
293
294                 | OR Bterm
295                 ;
296
297 Bterm:            Term GREATER Term
298                 @{ @i @Bterm.node@ = new_node(OP_Greater, @Term.node@, @Term.1.node@); @}
299
300                 | Term '=' Term
301                 @{ @i @Bterm.node@ = new_node(OP_Equal, @Term.node@, @Term.1.node@); @}
302
303                 | '(' Bool ')'
304                 ;
305
306 Field:            Term '.' ID
307                 @{
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);
309
310                    @check check_field(@Field.symbols@, @ID.name@);
311
312                    @reg @Term.node@->reg = @Field.node@->reg; @Field.node@->kids[1]->reg = get_next_reg(@Field.node@->reg, 0); 
313                 @}
314
315                 ;
316
317 Call:             ID '(' Exprs ')'
318                 @{ @i @Call.node@ = new_node(OP_Call, new_named_leaf(OP_ID, @ID.name@), @Exprs.node@); @}
319
320                 | ID '(' ')'
321                 @{ @i @Call.node@ = new_node(OP_Call, new_named_leaf(OP_ID, @ID.name@), NULL); @}
322
323                 ;
324
325 Exprs:            Expr
326                 | Exprs ',' Expr
327                 @{ @i @Exprs.node@ = new_node(OP_Exprs, @Exprs.1.node@, @Expr.node@); @}
328
329                 ;
330
331 %%
332
333 extern int yylex();
334 extern int yylineno;
335
336 int yyerror(char *error_text) {
337         fprintf(stderr,"Line %i: %s\n",yylineno, error_text);
338         exit(2);
339 }
340
341 int main(int argc, char **argv) {
342         yyparse();
343         return 0;
344 }
345