gesamt: noch zwei optimierungen ->
[uebersetzerbau-ss10.git] / gesamt / 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         /* funktioniert nicht fuer skinner33_00.0 @ gesamt (aber dafuer fuer ca.0) */
12         int ret_opt(struct treenode *x, int call)
13         {
14                 if(x->op == O_RET && x->kids[0] != TREENULL) {
15                         x = x->kids[0];
16                         if(x->op == O_CALL && x->kids[0] != TREENULL && x->kids[1] !=
17                                         TREENULL && x->kids[0]->op == O_NOTHING) {
18                                 x = x->kids[1];
19                                 if(x->op == O_ARG && x->kids[0] != TREENULL && x->kids[1] !=
20                                                 TREENULL && x->kids[0]->op == O_NOTHING &&
21                                                 x->kids[1]->op == O_NOTHING) {
22                                         return -1;
23                                 }
24                         }
25                 }
26                 return call;
27         }
28 %}
29
30 %start Input
31 %token STRUCT END METHOD VAR IF THEN ELSE WHILE DO RETURN NOT OR THIS IDENT NUM ASSIGN
32
33 @macro xxputsin(xx,)
34         @i xx = @Statement.sin@;
35 @end
36
37 @macro statinout()
38         @i @Statement.sout@ = @Statement.sin@;
39         /* das
40          *> xxputsin(@Statement.sout@,)
41          * geht nicht, weil verschachtelte macros deaktiviert sind */
42 @end
43
44 @macro lblcountinout()
45         @i @Statement.lblcnt_out@ = @Statement.lblcnt_in@;
46 @end
47
48 @macro varsinout()
49         @i @Statement.vars_out@ = @Statement.vars_in@;
50 @end
51
52 /* beschreibung der attribute
53  * s: symboltabelle
54  * f: symboltabelle fuer quirks mit structur und parameter
55  * gparamges: anzahl der parameter in einer methode
56  * parms: parametercounter
57  * node: baum fuer iburg
58  * sin: symboltabelle fuer statement ("eingabe")
59  * sout: symboltabelle die aus einem statement wieder rauskommt ("ausgabe")
60  * lblcnt_{in,out}: label counter
61  * vars_{in,out}: counter fuer lokale variablen
62  * call: enthaelt block einen call? (sonst kann man sich stack setup sparen)
63  * imm: fuer ein paar quirks mit immediates im ast
64  * paramcount: zum zaehlen der paramter eines methodenaufrufes
65  */
66 @autoinh s gparamges vars_in
67 @autosyn node imm call
68
69 @attributes { char *name; } IDENT
70 @attributes { long val; } NUM
71 @attributes { struct symbol *f; int paramges; int parms; } Parms
72 @attributes { struct symbol *f; } Program Structdef;
73 @attributes { struct symbol *f; int offsetcount; } FeldID
74 @attributes { struct symbol *s; } Methoddef
75 @attributes { struct symbol *s; int gparamges; int vars_in; int cnt; int paramcount; struct treenode *node; } Exprs
76 @attributes { struct symbol *s; int gparamges; int lblcnt_in; int lblcnt_out; int vars_in; int vars_out; int call; } Statseq
77 @attributes { struct symbol *s; int gparamges; int lblcnt_in; int lblcnt_out; int reallblcnt; int vars_in; int vars_out; int call; } Elsestat
78 @attributes { struct symbol *s; int gparamges; int vars_in; struct treenode *node; short imm; int call; } Expr Minusterm Multerm Orterm Feld Term
79 @attributes { struct symbol *s; int gparamges; int vars_in; struct treenode *node; } Lexpr IdentCommon
80 @attributes { struct symbol *sin; int gparamges; struct symbol *sout; struct treenode *node; int vars_in; int vars_out; int lblcnt_in; int lblcnt_out; int call; } Statement
81
82 @traversal @postorder c
83 @traversal @preorder reg
84 @traversal @preorder gen
85
86 %%
87 Input:
88           Program
89           @{
90             @i @Program.f@ = tab_new();
91             @gen printf("\t.text\n");
92           @}
93         ;
94
95 Program:
96           Methoddef ';' Program
97           @{
98             @i @Methoddef.s@ = @Program.0.f@;
99             @i @Program.1.f@ = @Program.0.f@;
100           @}
101
102         | Structdef ';' Program
103           @{
104             @i @Program.1.f@ = tab_merge(@Program.0.f@, @Structdef.f@, 1);
105           @}
106         |
107         ;
108
109 Methoddef:
110           METHOD IDENT '(' Parms ')' Statseq END
111           @{
112             @i @Parms.parms@ = 1;
113             @i @Statseq.s@ = tab_merge(@Methoddef.s@, @Parms.f@, 0);
114                 @i @Statseq.vars_in@ = 0;
115                 @i @Statseq.gparamges@ = @Parms.paramges@;
116                 @i @Statseq.lblcnt_in@ = 0;
117             @gen func_header(@IDENT.name@, @Statseq.vars_out@, @Parms.paramges@, @Statseq.call@);
118           @}
119         ;
120
121 Structdef:
122           STRUCT FeldID END
123           @{
124             @i @Structdef.f@ = @FeldID.f@;
125                 @i @FeldID.offsetcount@ = 0;
126           @}
127         ;
128
129 Parms:
130           /* lokale Vars werden in Statement in die tabelle eingefuegt */
131           IDENT Parms
132           @{
133             @i @Parms.1.parms@ = @Parms.0.parms@ + 1;
134                 @i @Parms.0.paramges@ = @Parms.1.paramges@;
135             @i @Parms.0.f@ = tab_add_symbol(@Parms.1.f@, @IDENT.name@, S_PARM, 1, @Parms.parms@, -1);
136           @}
137
138         |
139           @{
140             @i @Parms.f@ = tab_new();
141                 @i @Parms.paramges@ = @Parms.parms@;
142           @}
143         ;
144
145 FeldID:
146           IDENT FeldID
147           @{
148             @i @FeldID.1.offsetcount@ = @FeldID.0.offsetcount@ + 1;
149             @i @FeldID.0.f@ = tab_add_symbol(@FeldID.1.f@, @IDENT.name@, S_FIELD, 1, -1, @FeldID.0.offsetcount@);
150           @}
151
152         |
153           @{
154             @i @FeldID.f@ = tab_new();
155           @}
156         ;
157
158 Statseq:
159           Statement ';' Statseq
160           @{
161                 @i @Statement.sin@ = @Statseq.0.s@;
162                 @i @Statement.lblcnt_in@ = @Statseq.0.lblcnt_in@;
163
164                 @i @Statseq.1.s@ = @Statement.sout@;
165                 @i @Statseq.1.lblcnt_in@ = @Statement.lblcnt_out@;
166                 @i @Statseq.1.gparamges@ = @Statseq.0.gparamges@;
167
168                 @i @Statement.vars_in@ = @Statseq.0.vars_in@;
169                 @i @Statseq.1.vars_in@ = @Statement.vars_out@;
170
171                 @i @Statseq.0.lblcnt_out@ = @Statseq.1.lblcnt_out@;
172                 @i @Statseq.0.vars_out@ = @Statseq.1.vars_out@;
173
174                 @i @Statseq.0.call@ = @Statement.call@ | @Statseq.1.call@;
175           @}
176
177         |
178           @{
179                 @i @Statseq.0.lblcnt_out@ = @Statseq.0.lblcnt_in@;
180                 @i @Statseq.0.vars_out@ = @Statseq.0.vars_in@;
181                 @i @Statseq.0.call@ = 0;
182           @}
183         ;
184
185 Statement:
186           Lexpr ASSIGN Expr
187           @{
188                 statinout()
189                 lblcountinout()
190                 varsinout()
191                 xxputsin(@Lexpr.s@,)
192                 xxputsin(@Expr.s@,)
193             @i @Statement.node@ = new_node(O_ASSIGN, @Expr.node@, @Lexpr.node@);
194                 @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@);
195                 @reg @Lexpr.node@->reg = next_reg(@Expr.node@->reg, @Expr.gparamges@);
196
197                 @gen write_tree(@Statement.node@, 0); burm_label(@Statement.node@); burm_reduce(@Statement.node@, 1);
198           @}
199
200         | VAR IDENT ASSIGN Expr
201           @{
202                 /* tab_clone ist hier noetig, vgl. folgendes statement
203                  * > var x := x - 1; */
204                 @i @Statement.sout@ = tab_add_symbol(tab_clone(@Statement.sin@), @IDENT.name@, S_VAR, 1, @Statement.gparamges@ + @Statement.vars_in@, -1);
205                 lblcountinout()
206
207                 @i @Statement.vars_out@ = @Statement.vars_in@ + 1;
208
209                 xxputsin(@Expr.s@,)
210
211                 @i @Statement.node@ = new_node(O_ASSIGN, @Expr.node@, new_param(O_ID, @IDENT.name@, TREENULL, TREENULL, @Statement.gparamges@ + @Statement.vars_in@));
212                 @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@);
213
214                 @gen write_tree(@Statement.node@, 0); burm_label(@Statement.node@); burm_reduce(@Statement.node@, 1);
215           @}
216
217         | Expr
218           @{
219                 statinout()
220                 varsinout()
221                 lblcountinout()
222                 xxputsin(@Expr.s@,)
223                 @i @Statement.node@ = new_node(O_EXPR, @Expr.node@, TREENULL);
224                 @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@);
225
226                 @gen {
227                         just_calls(@Statement.node@);
228                 }
229           @}
230
231         | IF Expr THEN Statseq END
232           @{
233                 statinout()
234                 @i @Statseq.lblcnt_in@ =  @Statement.lblcnt_in@ + 1;
235                 @i @Statement.lblcnt_out@ = @Statseq.lblcnt_out@;
236
237                 @i @Statseq.vars_in@ = @Statement.vars_in@;
238                 @i @Statement.vars_out@ = @Statseq.vars_out@;
239
240                 @i @Statement.call@ = @Expr.call@ || @Statseq.call@;
241
242                 xxputsin(@Expr.s@,)
243                 xxputsin(@Statseq.s@,)
244
245                 @i @Statement.node@ = new_node(O_IF, @Expr.node@, TREENULL);
246
247                 @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@);
248                 @gen {
249                         printf(".%s_ifstart_%d:\n", get_func_name(), @Statement.lblcnt_in@);
250                         write_tree(@Statement.node@, 0); burm_label(@Statement.node@); burm_reduce(@Statement.node@, 1);
251                         printf("\tjz .%s_ifend_%d\n", get_func_name(), @Statement.lblcnt_in@);
252                 }
253                 @gen @revorder(1) printf(".%s_ifend_%d:\n", get_func_name(), @Statement.lblcnt_in@);
254           @}
255
256         | IF Expr THEN Statseq Elsestat END
257           @{
258                 statinout()
259                 @i @Statseq.0.lblcnt_in@ = @Statement.lblcnt_in@ + 1;
260                 @i @Elsestat.lblcnt_in@ = @Statseq.lblcnt_out@;
261                 @i @Statement.lblcnt_out@ = @Elsestat.lblcnt_out@;
262
263                 /* im Elsestat muss noch ein label numeriert werden */
264                 @i @Elsestat.reallblcnt@ = @Statement.lblcnt_in@;
265
266                 @i @Statseq.vars_in@ = @Statement.vars_in@;
267                 @i @Elsestat.vars_in@ = @Statement.vars_in@;
268                 @i @Statement.vars_out@ = MAX(@Statseq.vars_out@, @Elsestat.vars_out@);
269
270                 @i @Statement.call@ = @Expr.call@ || @Statseq.call@ || @Elsestat.call@;
271
272                 xxputsin(@Expr.s@,)
273                 xxputsin(@Statseq.0.s@,)
274                 xxputsin(@Elsestat.s@,)
275
276                 @i @Statement.node@ = new_node(O_IF, @Expr.node@, TREENULL);
277
278                 @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@);
279                 @gen {
280                         printf(".%s_ifstart_%d:\n", get_func_name(), @Statement.lblcnt_in@);
281                         write_tree(@Statement.node@, 0); burm_label(@Statement.node@); burm_reduce(@Statement.node@, 1);
282                         printf("\tjz .%s_ifelse_%d\n", get_func_name(), @Statement.lblcnt_in@);
283                 }
284                 @gen @revorder(1) printf(".%s_ifend_%d:\n", get_func_name(), @Statement.lblcnt_in@);
285           @}
286
287         | WHILE Expr DO Statseq END
288           @{
289                 statinout()
290                 @i @Statseq.lblcnt_in@ =  @Statement.lblcnt_in@ + 1;
291                 @i @Statement.lblcnt_out@ = @Statseq.lblcnt_out@;
292
293                 @i @Statseq.vars_in@ = @Statement.vars_in@;
294                 @i @Statement.vars_out@ = @Statseq.vars_out@;
295
296                 @i @Statement.call@ = @Expr.call@ || @Statseq.call@;
297
298                 xxputsin(@Expr.s@,)
299                 xxputsin(@Statseq.s@,)
300
301                 @i @Statement.node@ = new_node(O_IF, @Expr.node@, TREENULL);
302
303                 @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@);
304                 @gen {
305                         printf(".%s_whilestart_%d:\n", get_func_name(), @Statement.lblcnt_in@);
306                         write_tree(@Statement.node@, 0); burm_label(@Statement.node@); burm_reduce(@Statement.node@, 1);
307                         printf("\tjz .%s_whileend_%d\n", get_func_name(), @Statement.lblcnt_in@);
308                 }
309                 @gen @revorder(1) printf("\tjmp .%s_whilestart_%d\n.%s_whileend_%d:\n", get_func_name(), @Statement.lblcnt_in@, get_func_name(), @Statement.lblcnt_in@);
310           @}
311
312         | RETURN Expr
313           @{
314                 statinout()
315                 lblcountinout()
316                 varsinout()
317                 xxputsin(@Expr.s@,)
318
319                 @i @Statement.node@ = new_node(O_RET, @Expr.node@, TREENULL);
320                 @i @Statement.call@ = ret_opt(@Statement.node@, @Expr.call@);
321
322                 @reg @Statement.node@->reg = @Expr.node@->reg = next_reg((char *)NULL, @Expr.gparamges@);
323
324                 @gen write_tree(@Statement.node@, 0); burm_label(@Statement.node@); burm_reduce(@Statement.node@, 1); func_footer();
325           @}
326         ;
327
328 Elsestat:
329           ELSE Statseq
330           @{
331                 @i @Statseq.lblcnt_in@ =  @Elsestat.lblcnt_in@;
332                 @i @Elsestat.lblcnt_out@ =  @Statseq.lblcnt_out@;
333
334                 @i @Statseq.vars_in@ = @Elsestat.vars_in@;
335                 @i @Elsestat.vars_out@ = @Statseq.vars_out@;
336
337                 @gen printf("\tjmp .%s_ifend_%d\n.%s_ifelse_%d:\n", get_func_name(), @Elsestat.reallblcnt@, get_func_name(), @Elsestat.reallblcnt@);
338           @}
339
340 Lexpr:
341           IdentCommon
342         | Feld
343         ;
344
345 IdentCommon: 
346           IDENT
347           @{
348             @c check(@IdentCommon.s@, @IDENT.name@, S_VAR|S_PARM);
349
350             @i {
351                         @IdentCommon.node@ = TREENULL;
352                         if(tab_lookup(@IdentCommon.s@, @IDENT.name@, S_VAR|S_PARM) == SYMNULL) {
353                                 /* es handelt sich um ein feldzugriff auf this */
354                                 @IdentCommon.node@ = new_field(@IDENT.name@, new_param(O_ID, "this", TREENULL, TREENULL, 0), TREENULL, tab_lookup(@IdentCommon.s@, @IDENT.name@, S_FIELD) == SYMNULL ? -1 : tab_lookup(@IdentCommon.s@, @IDENT.name@, S_FIELD)->soffset);
355                         } else { /* param oder var */
356                                 int tmp = tab_lookup(@IdentCommon.s@, @IDENT.name@, S_VAR|S_PARM) == SYMNULL ? -1 : tab_lookup(@IdentCommon.s@, @IDENT.name@, S_VAR|S_PARM)->param_index;
357                                 @IdentCommon.node@ = new_param(O_ID, @IDENT.name@, TREENULL, TREENULL, tmp);
358                         }
359                 }
360
361                 @reg if(tab_lookup(@IdentCommon.s@, @IDENT.name@, S_VAR|S_PARM) == SYMNULL) {
362                         /* TODO: kein schoener hack? */
363                         @IdentCommon.node@->kids[0]->reg = @IdentCommon.node@->reg;
364                 }
365           @}
366         ;
367
368
369 Feld: Term '.' IDENT
370           @{
371             @c check(@Feld.s@, @IDENT.name@, S_FIELD);
372             @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);
373
374                 @reg @Term.node@->reg = next_reg(@Feld.node@->reg, @Term.gparamges@);
375           @}
376         ;
377
378 Expr:
379           Term
380           @{
381             @reg @Term.node@->reg = @Expr.node@->reg;
382           @}
383
384         | NOT Term
385           @{
386                 @i @Expr.node@ = new_node(O_BOOL, new_node(O_EQ, @Term.node@, new_node(O_NULL, TREENULL, TREENULL)), TREENULL);
387
388                 @reg @Term.node@->reg = @Expr.node@->kids[0]->reg = @Expr.node@->reg;
389           @}
390
391         | Term Minusterm
392           @{
393             @i @Expr.node@ = new_node(O_SUB, @Term.node@, @Minusterm.node@);
394                 @i @Expr.imm@ = @Term.imm@ && @Minusterm.imm@;
395                 @i @Expr.call@ = @Term.call@ || @Minusterm.call@;
396
397                 @reg {
398                         if(!(@Expr.node@->kids[0] == TREENULL && @Expr.node@->kids[1] == TREENULL)) {
399                                 @Term.node@->reg = @Expr.node@->reg;
400                                 if(@Minusterm.imm@) {
401                                         @Minusterm.node@->reg = @Expr.node@->reg;
402                                 } else {
403                                         @Minusterm.node@->reg = next_reg(@Term.node@->reg, @Expr.gparamges@);
404                                 }
405                         }
406                 }
407           @}
408
409         | Term Multerm
410           @{
411             @i @Expr.node@ = new_node(O_MUL, @Term.node@, @Multerm.node@);
412                 @i @Expr.imm@ = @Term.imm@ && @Multerm.imm@;
413                 @i @Expr.call@ = @Term.call@ || @Multerm.call@;
414
415                 @reg {
416                         @Term.node@->reg = @Expr.node@->reg;
417                         if(@Term.imm@) {
418                                 @Multerm.node@->reg = @Expr.node@->reg;
419                         } else {
420                                 @Multerm.node@->reg = next_reg(@Term.node@->reg, @Expr.gparamges@);
421                         }
422                 }
423           @}
424
425         | Term Orterm
426           @{
427             @i @Expr.node@ = new_node(O_OR, @Term.node@, @Orterm.node@);
428                 @i @Expr.imm@ = @Term.imm@ && @Orterm.imm@;
429                 @i @Expr.call@ = @Term.call@ || @Orterm.call@;
430
431                 @reg {
432                         @Term.node@->reg = @Expr.node@->reg;
433                         @Orterm.node@->reg = next_reg(@Term.node@->reg, @Expr.gparamges@);
434                 }
435           @}
436
437         | Term '<' Term
438           @{
439             @i @Expr.node@ = new_node(O_BOOL, new_node(O_LESS, @Term.0.node@, @Term.1.node@), TREENULL);
440                 @i @Expr.imm@ = @Term.0.imm@ && @Term.1.imm@;
441                 @i @Expr.call@ = @Term.0.call@ || @Term.1.call@;
442
443                 @reg {
444                         @Term.0.node@->reg = @Expr.node@->kids[0]->reg = @Expr.node@->reg;
445                         @Term.1.node@->reg = next_reg(@Term.0.node@->reg, @Expr.gparamges@);
446                 }
447           @}
448
449         | Term '=' Term
450           @{
451             @i @Expr.node@ = new_node(O_BOOL, new_node(O_EQ, @Term.0.node@, @Term.1.node@), TREENULL);
452                 @i @Expr.imm@ = @Term.0.imm@ && @Term.1.imm@;
453                 @i @Expr.call@ = @Term.0.call@ || @Term.1.call@;
454
455                 @reg {
456                         @Term.0.node@->reg = @Expr.node@->kids[0]->reg = @Expr.node@->reg;
457                         @Term.1.node@->reg = next_reg(@Term.0.node@->reg, @Expr.gparamges@);
458                 }
459           @}
460         ;
461
462 Minusterm:
463           '-' Term Minusterm
464           @{
465             @i @Minusterm.node@ = new_node(O_ADD, @Minusterm.1.node@, @Term.node@);
466                 @i @Minusterm.0.imm@ = @Term.imm@ && @Minusterm.1.imm@;
467                 @i @Minusterm.0.call@ = @Term.call@ || @Minusterm.1.call@;
468
469             @reg {
470                         @Minusterm.1.node@->reg = @Minusterm.node@->reg;
471                         if(@Minusterm.1.imm@) {
472                                 @Term.node@->reg = @Minusterm.node@->reg;
473                         } else {
474                                 @Term.node@->reg = next_reg(@Minusterm.1.node@->reg, @Minusterm.gparamges@);
475                         }
476                 }
477           @}
478
479         | '-' Term
480           @{
481             @reg @Term.node@->reg = @Minusterm.node@->reg;
482           @}
483         ;
484
485 Multerm:
486           '*' Term Multerm
487           @{
488             @i @Multerm.node@ = new_node(O_MUL, @Multerm.1.node@, @Term.node@);
489                 @i @Multerm.0.imm@ = @Term.imm@ && @Multerm.1.imm@;
490                 @i @Multerm.0.call@ = @Term.call@ || @Multerm.1.call@;
491
492             @reg {
493                         @Multerm.1.node@->reg = @Multerm.node@->reg;
494                         if(@Multerm.1.imm@) {
495                                 @Term.node@->reg = @Multerm.node@->reg;
496                         } else {
497                                 @Term.node@->reg = next_reg(@Multerm.1.node@->reg, @Multerm.gparamges@);
498                         }
499                 }
500           @}
501
502         | '*' Term
503           @{
504             @reg @Term.node@->reg = @Multerm.node@->reg;
505           @}
506         ;
507
508 Orterm:
509           OR Term Orterm
510           @{
511             @i @Orterm.node@ = new_node(O_OR, @Orterm.1.node@, @Term.node@);
512                 @i @Orterm.0.imm@ = @Term.imm@ && @Orterm.1.imm@;
513                 @i @Orterm.0.call@ = @Term.call@ || @Orterm.1.call@;
514
515             @reg {
516                         @Orterm.1.node@->reg = @Orterm.node@->reg;
517                         if(@Orterm.1.imm@) {
518                                 @Term.node@->reg = @Orterm.node@->reg;
519                         } else {
520                                 @Term.node@->reg = next_reg(@Orterm.1.node@->reg, @Orterm.gparamges@);
521                         }
522                 }
523           @}
524         | OR Term
525           @{
526             @reg @Term.node@->reg = @Orterm.node@->reg;
527           @}
528
529         ;
530
531 Term:
532           '(' Expr ')'
533           @{
534             @i @Term.node@ = @Expr.node@;
535           @}
536
537         | NUM
538           @{
539             @i @Term.node@ = new_number(@NUM.val@);
540                 @i @Term.imm@ = 1;
541                 @i @Term.call@ = 0;
542           @}
543
544         | '-' NUM
545           @{
546             @i @Term.node@ = new_number(-1 * (@NUM.val@));
547                 @i @Term.imm@ = 1;
548                 @i @Term.call@ = 0;
549           @}
550
551         | THIS
552           @{
553             @i @Term.node@ = new_param(O_ID, "this", TREENULL, TREENULL, 0);
554                 @i @Term.imm@ = 0;
555                 @i @Term.call@ = 0;
556           @}
557
558         | IdentCommon
559           @{
560                 @i @Term.imm@ = 0;
561                 @i @Term.call@ = 0;
562           @}
563
564         | Feld
565           @{
566             @i @Term.node@ = @Feld.node@;
567                 @i @Term.imm@ = 0;
568           @}
569
570         | IDENT '(' Exprs ')'
571           @{
572             @i {
573                         @Term.node@ = new_call(@IDENT.name@, @Exprs.node@, new_arg(new_nothing(), new_nothing(), 0) /*this*/,
574                                         @Term.gparamges@, @Term.vars_in@);
575                         @Term.node@->soffset = MAX(@Exprs.paramcount@, @Term.gparamges@);
576                         @Term.node@->sc = @Term.node@->kids[1]->sc = @Exprs.node@->sc;
577                 }
578                 @i @Exprs.cnt@ = 1;
579                 @i @Term.imm@ = 0;
580                 @i @Term.call@ = 1;
581                 @reg @Exprs.node@->reg = @Term.node@->reg;
582           @}
583
584         | Term '.' IDENT '(' Exprs ')'
585           @{
586             @i {
587                         @Term.node@ = new_call(@IDENT.name@, @Exprs.node@, new_arg(@Term.1.node@, new_nothing(), 0) /*this*/,
588                                         @Term.gparamges@, @Term.vars_in@);
589                         @Term.node@->soffset = MAX(@Exprs.paramcount@, @Term.gparamges@);
590                         @Term.node@->sc = @Term.node@->kids[1]->sc = @Exprs.node@->sc;
591                 }
592                 @i @Exprs.cnt@ = 1;
593                 @i @Term.imm@ = 0;
594                 @i @Term.call@ = 1;
595                 @reg @Exprs.node@->reg = @Term.1.node@->reg = @Term.node@->kids[1]->reg = @Term.node@->reg;
596           @}
597
598         ;
599
600 Exprs:
601           Expr ',' Exprs
602           @{
603                 @i {
604                         @Exprs.0.node@ = new_arg(@Exprs.1.node@, @Expr.0.node@, @Exprs.0.cnt@);
605                         @Exprs.0.node@->sc = @Exprs.1.node@->sc;
606                 }
607                 @i @Exprs.0.paramcount@ = @Exprs.1.paramcount@;
608                 @i @Exprs.1.cnt@ = @Exprs.0.cnt@ + 1;
609                 @reg {
610                         @Expr.node@->reg = @Exprs.0.node@->reg;
611                         @Exprs.1.node@->reg = next_reg(@Exprs.0.node@->reg, @Exprs.gparamges@);
612                 }
613           @}
614         | Expr
615           @{
616                 @i {
617                         @Exprs.0.node@ = new_arg(@Expr.0.node@, new_nothing(), @Exprs.cnt@);
618                         @Exprs.0.node@->sc = malloc(8 * sizeof(short));
619                 }
620                 @i @Exprs.paramcount@ = @Exprs.cnt@ + 1;
621                 @reg @Expr.node@->reg = @Exprs.0.node@->reg;
622           @}
623         |
624           @{
625                 @i {
626                         @Exprs.0.node@ = new_nothing();
627                         @Exprs.0.node@->sc = malloc(8 * sizeof(short));
628                 }
629                 @i @Exprs.paramcount@ = @Exprs.cnt@;
630           @}
631         ;
632 %%
633
634 extern int yylex();
635 extern int yylineno;
636
637 int yyerror(char *error_text)
638 {
639         fprintf(stderr,"Zeile %i: %s\n", yylineno, error_text);
640         exit(2);
641 }
642
643 int main(int argc, char **argv)
644 {
645         #if 0
646         yydebug=1;
647         #endif
648         yyparse();
649         return 0;
650 }
651