codeb: var-assignments
[uebersetzerbau-ss10.git] / codeb / parser.y
1 %{
2         #include <stdio.h>
3         #include <stdlib.h>
4         #include <string.h>
5         #include "symtable.h"
6         #include "chelper.h"
7         #include "tree.h"
8
9         #define MAX(A,B) (A > B ? A : B)
10 %}
11
12 %start Input
13 %token STRUCT END METHOD VAR IF THEN ELSE WHILE DO RETURN NOT OR THIS IDENT NUM ASSIGN
14
15 @macro xxputsin(xx,)
16         @i xx = @Statement.sin@;
17 @end
18
19 @macro statinout()
20         @i @Statement.sout@ = @Statement.sin@;
21         /* das
22          *> xxputsin(@Statement.sout@,)
23          * geht nicht, weil verschachtelte macros deaktiviert sind */
24 @end
25
26 /* beschreibung der attribute
27  * s: symboltabelle
28  * f: symboltabelle fuer quirks mit structur und parameter
29  * gparamges: anzahl der parameter in einer methode
30  * parms: parametercounter
31  * node: baum fuer iburg
32  * sin: symboltabelle fuer statement ("eingabe")
33  * sout: symboltabelle die aus einem statement wieder rauskommt ("ausgabe")
34  */
35 @autoinh s gparamges
36 @autosyn node imm
37
38 @attributes { char *name; } IDENT
39 @attributes { long val; } NUM
40 @attributes { struct symbol *f; int paramges; int parms; } Parms
41 @attributes { struct symbol *f; } Program Structdef;
42 @attributes { struct symbol *f; int offsetcount; } FeldID
43 @attributes { struct symbol *s; } Methoddef
44 @attributes { struct symbol *s; int gparamges; } Statseq Exprs
45 @attributes { struct symbol *s; int gparamges; struct treenode *node; short imm; } Expr Minusterm Multerm Orterm Feld Term
46 @attributes { struct symbol *s; int gparamges; struct treenode *node; } Lexpr
47 @attributes { struct symbol *sin; int gparamges; struct symbol *sout; struct
48 treenode *node; int vars; } Statement
49
50 @traversal @postorder c
51 @traversal @preorder reg
52 @traversal @preorder gen
53
54 %%
55 Input:
56           Program
57           @{
58             @i @Program.f@ = tab_new();
59             @gen printf("\t.text\n");
60           @}
61         ;
62
63 Program:
64           Methoddef ';' Program
65           @{
66             @i @Methoddef.s@ = @Program.0.f@;
67             @i @Program.1.f@ = @Program.0.f@;
68           @}
69
70         | Structdef ';' Program
71           @{
72             @i @Program.1.f@ = tab_merge(@Program.0.f@, @Structdef.f@, 1);
73           @}
74         |
75         ;
76
77 Methoddef:
78           METHOD IDENT '(' Parms ')' Statseq END
79           @{
80             @i @Parms.parms@ = 1;
81             @i @Statseq.s@ = tab_merge(@Methoddef.s@, @Parms.f@, 0);
82                 @i @Statseq.gparamges@ = @Parms.paramges@;
83             @gen func_header(@IDENT.name@);
84           @}
85         ;
86
87 Structdef:
88           STRUCT FeldID END
89           @{
90             @i @Structdef.f@ = @FeldID.f@;
91                 @i @FeldID.offsetcount@ = 0;
92           @}
93         ;
94
95 Parms:
96           /* lokale Vars werden in Statement in die tabelle eingefuegt */
97           IDENT Parms
98           @{
99             @i @Parms.1.parms@ = @Parms.0.parms@ + 1;
100                 @i @Parms.0.paramges@ = @Parms.1.paramges@;
101             @i @Parms.0.f@ = tab_add_symbol(@Parms.1.f@, @IDENT.name@, S_PARM, 1, @Parms.parms@, -1);
102           @}
103
104         |
105           @{
106             @i @Parms.f@ = tab_new();
107                 @i @Parms.paramges@ = @Parms.parms@;
108           @}
109         ;
110
111 FeldID:
112           IDENT FeldID
113           @{
114             @i @FeldID.1.offsetcount@ = @FeldID.0.offsetcount@ + 1;
115             @i @FeldID.0.f@ = tab_add_symbol(@FeldID.1.f@, @IDENT.name@, S_FIELD, 1, -1, @FeldID.0.offsetcount@);
116           @}
117
118         |
119           @{
120             @i @FeldID.f@ = tab_new();
121           @}
122         ;
123
124 Statseq:
125           Statement ';' Statseq
126           @{
127                 @i @Statement.sin@ = @Statseq.0.s@;
128                 @i @Statseq.1.s@ = @Statement.sout@;
129                 @i @Statseq.1.gparamges@ = @Statseq.0.gparamges@ + @Statement.vars@;
130           @}
131
132         |
133         ;
134
135 Statement:
136           Lexpr ASSIGN Expr
137           @{
138                 statinout()
139                 xxputsin(@Lexpr.s@,)
140                 xxputsin(@Expr.s@,)
141             @i @Statement.node@ = TREENULL;
142                 @i @Statement.vars@ = 0;
143           @}
144
145         | VAR IDENT ASSIGN Expr
146           @{
147                 /* tab_clone ist hier noetig, vgl. folgendes statement
148                  * > var x := x - 1; */
149                 @i @Statement.sout@ = tab_add_symbol(tab_clone(@Statement.sin@), @IDENT.name@, S_VAR, 1, @Statement.gparamges@, -1);
150                 xxputsin(@Expr.s@,)
151                 @i @Statement.vars@ = 1;
152
153                 @i @Statement.node@ = new_node(O_ASSIGN, new_param(O_ID, @IDENT.name@, TREENULL, TREENULL, @Statement.gparamges@), @Expr.node@);
154                 @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@);
155
156                 @gen write_tree(@Statement.node@, 0); burm_label(@Statement.node@); burm_reduce(@Statement.node@, 1);
157           @}
158
159         | Expr
160           @{
161                 statinout()
162                 xxputsin(@Expr.s@,)
163             @i @Statement.node@ = TREENULL;
164                 @i @Statement.vars@ = 0;
165           @}
166
167         | IF Expr THEN Statseq END
168           @{
169                 statinout()
170                 xxputsin(@Expr.s@,)
171                 xxputsin(@Statseq.s@,)
172             @i @Statement.node@ = TREENULL;
173                 @i @Statement.vars@ = 0;
174           @}
175
176         | IF Expr THEN Statseq ELSE Statseq END
177           @{
178                 statinout()
179                 xxputsin(@Expr.s@,)
180                 xxputsin(@Statseq.0.s@,)
181                 xxputsin(@Statseq.1.s@,)
182             @i @Statement.node@ = TREENULL;
183                 @i @Statement.vars@ = 0;
184           @}
185
186         | WHILE Expr DO Statseq END
187           @{
188                 statinout()
189                 xxputsin(@Expr.s@,)
190                 xxputsin(@Statseq.s@,)
191             @i @Statement.node@ = TREENULL;
192                 @i @Statement.vars@ = 0;
193           @}
194
195         | RETURN Expr
196           @{
197                 statinout()
198                 xxputsin(@Expr.s@,)
199                 @i @Statement.vars@ = 0;
200                 @i @Statement.node@ = new_node(O_RET, @Expr.node@, TREENULL);
201                 @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@);
202
203                 @gen write_tree(@Statement.node@, 0); burm_label(@Statement.node@); burm_reduce(@Statement.node@, 1);
204           @}
205         ;
206
207 Lexpr:
208           IDENT
209           @{
210             @i @Lexpr.node@ = TREENULL;
211             @c check(@Lexpr.s@, @IDENT.name@, S_VAR|S_PARM);
212                 /* this.feldname */
213                 /* TODO fuer zuweisungen ... (codeb?) */
214           @}
215
216         | Feld
217         ;
218
219 Feld: Term '.' IDENT
220           @{
221             @c check(@Feld.s@, @IDENT.name@, S_FIELD);
222             @i @Feld.node@ = new_field(@IDENT.name@, @Term.node@, TREENULL, tab_lookup(@Feld.s@, @IDENT.name@, S_FIELD) == SYMNULL ? -1 : tab_lookup(@Feld.s@, @IDENT.name@, S_FIELD)->soffset);
223
224                 @reg @Term.node@->reg = @Feld.node@->reg;
225           @}
226         ;
227
228 Expr:
229           Term
230           @{
231             @reg @Term.node@->reg = @Expr.node@->reg;
232           @}
233
234         | NOT Term
235           @{
236                 @i @Expr.node@ = new_node(O_EQ, @Term.node@, new_node(O_NULL, TREENULL, TREENULL));
237
238                 @reg @Term.node@->reg = @Expr.node@->reg;
239           @}
240
241         | Term Minusterm
242           @{
243             @i @Expr.node@ = new_node(O_SUB, @Term.node@, @Minusterm.node@);
244                 @i @Expr.imm@ = @Term.imm@ && @Minusterm.imm@;
245
246                 @reg {
247                         if(!(@Expr.node@->kids[0] == TREENULL && @Expr.node@->kids[1] == TREENULL)) {
248                                 @Term.node@->reg = @Expr.node@->reg;
249                                 if(@Minusterm.imm@) {
250                                         @Minusterm.node@->reg = @Expr.node@->reg;
251                                 } else {
252                                         @Minusterm.node@->reg = next_reg(@Term.node@->reg, @Expr.gparamges@);
253                                 }
254                         }
255                 }
256           @}
257
258         | Term Multerm
259           @{
260             @i @Expr.node@ = new_node(O_MUL, @Term.node@, @Multerm.node@);
261                 @i @Expr.imm@ = @Term.imm@ && @Multerm.imm@;
262
263                 @reg {
264                         @Term.node@->reg = @Expr.node@->reg;
265                         if(@Term.imm@) {
266                                 @Multerm.node@->reg = @Expr.node@->reg;
267                         } else {
268                                 @Multerm.node@->reg = next_reg(@Term.node@->reg, @Expr.gparamges@);
269                         }
270                 }
271           @}
272
273         | Term Orterm
274           @{
275             @i @Expr.node@ = new_node(O_OR, @Term.node@, @Orterm.node@);
276                 @i @Expr.imm@ = @Term.imm@ && @Orterm.imm@;
277
278                 @reg {
279                         @Term.node@->reg = @Expr.node@->reg;
280                         @Orterm.node@->reg = next_reg(@Term.node@->reg, @Expr.gparamges@);
281                 }
282           @}
283
284         | Term '<' Term
285           @{
286             @i @Expr.node@ = new_node(O_LESS, @Term.0.node@, @Term.1.node@);
287                 @i @Expr.imm@ = @Term.0.imm@ && @Term.0.imm@;
288
289                 @reg {
290                         @Term.0.node@->reg = @Expr.node@->reg;
291                         @Term.1.node@->reg = next_reg(@Term.0.node@->reg, @Expr.gparamges@);
292                 }
293           @}
294
295         | Term '=' Term
296           @{
297             @i @Expr.node@ = new_node(O_EQ, @Term.0.node@, @Term.1.node@);
298                 @i @Expr.imm@ = @Term.0.imm@ && @Term.0.imm@;
299
300                 @reg {
301                         @Term.0.node@->reg = @Expr.node@->reg;
302                         @Term.1.node@->reg = next_reg(@Term.0.node@->reg, @Expr.gparamges@);
303                 }
304           @}
305         ;
306
307 Minusterm:
308           '-' Term Minusterm
309           @{
310             @i @Minusterm.node@ = new_node(O_ADD, @Minusterm.1.node@, @Term.node@);
311                 @i @Minusterm.0.imm@ = @Term.imm@ && @Minusterm.1.imm@;
312
313             @reg {
314                         @Minusterm.1.node@->reg = @Minusterm.node@->reg;
315                         if(@Minusterm.1.imm@) {
316                                 @Term.node@->reg = @Minusterm.node@->reg;
317                         } else {
318                                 @Term.node@->reg = next_reg(@Minusterm.1.node@->reg, @Minusterm.gparamges@);
319                         }
320                 }
321           @}
322
323         | '-' Term
324           @{
325             @reg @Term.node@->reg = @Minusterm.node@->reg;
326           @}
327         ;
328
329 Multerm:
330           '*' Term Multerm
331           @{
332             @i @Multerm.node@ = new_node(O_MUL, @Multerm.1.node@, @Term.node@);
333                 @i @Multerm.0.imm@ = @Term.imm@ && @Multerm.1.imm@;
334
335             @reg {
336                         @Multerm.1.node@->reg = @Multerm.node@->reg;
337                         if(@Multerm.1.imm@) {
338                                 @Term.node@->reg = @Multerm.node@->reg;
339                         } else {
340                                 @Term.node@->reg = next_reg(@Multerm.1.node@->reg, @Multerm.gparamges@);
341                         }
342                 }
343           @}
344
345         | '*' Term
346           @{
347             @reg @Term.node@->reg = @Multerm.node@->reg;
348           @}
349         ;
350
351 Orterm:
352           OR Term Orterm
353           @{
354             @i @Orterm.node@ = new_node(O_OR, @Orterm.1.node@, @Term.node@);
355                 @i @Orterm.0.imm@ = @Term.imm@ && @Orterm.1.imm@;
356
357             @reg {
358                         @Orterm.1.node@->reg = @Orterm.node@->reg;
359                         if(@Orterm.1.imm@) {
360                                 @Term.node@->reg = @Orterm.node@->reg;
361                         } else {
362                                 @Term.node@->reg = next_reg(@Orterm.1.node@->reg, @Orterm.gparamges@);
363                         }
364                 }
365           @}
366         | OR Term
367           @{
368             @reg @Term.node@->reg = @Orterm.node@->reg;
369           @}
370
371         ;
372
373 Term:
374           '(' Expr ')'
375           @{
376             @i @Term.node@ = @Expr.node@;
377           @}
378
379         | NUM
380           @{
381             @i @Term.node@ = new_number(@NUM.val@);
382                 @i @Term.imm@ = 1;
383           @}
384
385         | '-' NUM
386           @{
387             @i @Term.node@ = new_number(-1 * (@NUM.val@));
388                 @i @Term.imm@ = 1;
389           @}
390
391         | THIS
392           @{
393             @i @Term.node@ = new_param(O_ID, strdup("this"), TREENULL, TREENULL, 0);
394                 @i @Term.imm@ = 0;
395           @}
396
397         | IDENT
398           @{
399             @c check(@Term.s@, @IDENT.name@, S_VAR|S_PARM);
400
401                 @i @Term.imm@ = 0;
402             @i {
403                         @Term.node@ = TREENULL;
404                         if(tab_lookup(@Term.s@, @IDENT.name@, S_VAR|S_PARM) == SYMNULL) {
405                                 /* es handelt sich um ein feldzugriff auf this */
406                                 @Term.node@ = new_field(@IDENT.name@, new_param(O_ID, strdup("this"), TREENULL, TREENULL, 0), TREENULL, tab_lookup(@Term.s@, @IDENT.name@, S_FIELD) == SYMNULL ? -1 : tab_lookup(@Term.s@, @IDENT.name@, S_FIELD)->soffset);
407                         } else { /* param oder var */
408                                 int tmp = tab_lookup(@Term.s@, @IDENT.name@, S_VAR|S_PARM) == SYMNULL ? -1 : tab_lookup(@Term.s@, @IDENT.name@, S_VAR|S_PARM)->param_index;
409                                 fprintf(stderr, "WTF: %d\n", tmp);
410                                 @Term.node@ = new_param(O_ID, @IDENT.name@, TREENULL, TREENULL, tmp);
411                         }
412                 }
413
414                 @reg if(tab_lookup(@Term.s@, @IDENT.name@, S_VAR|S_PARM) == SYMNULL) {
415                         /* TODO: kein schoener hack? */
416                         @Term.node@->kids[0]->reg = @Term.node@->reg;
417                 }
418           @}
419
420         | Feld
421           @{
422             @i @Term.node@ = @Feld.node@;
423                 @i @Term.imm@ = 0;
424           @}
425
426         | IDENT '(' Exprs ')'
427           @{
428             @i @Term.node@ = TREENULL;
429                 @i @Term.imm@ = 0;
430           @}
431
432         | Term '.' IDENT '(' Exprs ')'
433           @{
434             @i @Term.node@ = TREENULL;
435                 @i @Term.imm@ = 0;
436           @}
437
438         ;
439
440 Exprs:
441           Expr ',' Exprs
442         | Expr
443         |
444         ;
445 %%
446
447 extern int yylex();
448 extern int yylineno;
449
450 int yyerror(char *error_text)
451 {
452         fprintf(stderr,"Zeile %i: %s\n", yylineno, error_text);
453         exit(2);
454 }
455
456 int main(int argc, char **argv)
457 {
458         #if 0
459         yydebug=1;
460         #endif
461         yyparse();
462         return 0;
463 }
464