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