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