%{
#include <stdio.h>
#include <stdlib.h>
+ #include <string.h>
+ #include "symtable.h"
%}
-%start Program
+%start Input
%token STRUCT END METHOD VAR IF THEN ELSE WHILE DO RETURN NOT OR THIS
-%token IDENT NUM
+%token IDENT NUM ASSIGN
+
+/* TODO: macro, see oxURM.ps @ p. 25 */
+
+@autoinh s
+/* f .. fields
+ * s .. symbols */
+@attributes { char *name; } IDENT
+@attributes { struct symbol *f; struct symbol *s; } Program
+@attributes { struct symbol *f; } Idents Structdef
+@attributes { struct symbol *p; } Parms
+@attributes { struct symbol *s; } Methoddef Statseq Lexpr Expr Minusterm Multerm Orterm
+Term Exprs
+@attributes { struct symbol *sin; struct symbol *sout; } Statement
+
+@traversal @postorder c
%%
+Input:
+ Program
+ @{
+ @i @Program.s@ = @Program.f@;
+ @}
+ ;
+
Program:
Methoddef ';' Program
+ @{
+ @i @Program.0.f@ = @Program.1.f@;
+ @}
+
| Structdef ';' Program
+ @{
+ @i @Program.0.f@ = tab_merge(@Structdef.f@, @Program.1.f@, 1);
+ @}
+
|
+ @{
+ @i @Program.0.f@ = new_tab();
+ @}
+
+ ;
+
+Methoddef:
+ METHOD IDENT '(' Parms ')' Statseq END
+ @{
+ @i @Statseq.s@ = tab_merge(@Methoddef.s@, @Parms.p@, 0);
+ @}
+
;
Structdef:
STRUCT Idents END
+ @{
+ @i @Structdef.f@ = @Idents.f@;
+ @}
+
;
-Methoddef:
- METHOD IDENT '(' Idents ')' Statseq END
+Parms:
+ /* lokale Vars werden in Statement in die tabelle eingefuegt */
+ IDENT Parms
+ @{
+ @i @Parms.0.p@ = tab_add_symbol(@Parms.1.p@, @IDENT.name@, S_VAR, 1);
+ @}
+
+ |
+ @{
+ @i @Parms.p@ = new_tab();
+ @}
+
;
Idents:
IDENT Idents
+ @{
+ @i @Idents.0.f@ = tab_add_symbol(@Idents.1.f@, @IDENT.name@, S_FIELD, 1);
+ @}
+
|
+ @{
+ @i @Idents.f@ = new_tab();
+ @}
+
;
Statseq:
Statement ';' Statseq
+ @{
+ @i @Statement.sin@ = @Statseq.0.s@;
+ @i @Statseq.1.s@ = @Statement.sout@;
+ @}
+
|
+
;
Statement:
- Lexpr ':=' Expr
- | VAR IDENT ':=' Expr
+ Lexpr ASSIGN Expr
+ @{
+ @i @Statement.sout@ = @Statement.sin@;
+ @i @Lexpr.s@ = @Statement.sin@;
+ @i @Expr.s@ = @Statement.sin@;
+ @}
+
+ | VAR IDENT ASSIGN Expr
+ @{
+ @i @Statement.sout@ = tab_add_symbol(clone_tab(@Statement.sin@), @IDENT.name@, S_VAR, 0);
+ @i @Expr.s@ = @Statement.sin@;
+ @}
+
| Expr
+ @{
+ @i @Expr.s@ = @Statement.sin@;
+ @i @Statement.sout@ = @Statement.sin@;
+ @}
+
| IF Expr THEN Statseq END
+ @{
+ @i @Expr.s@ = @Statement.sin@;
+ @i @Statseq.s@ = @Statement.sin@;
+ @i @Statement.sout@ = @Statement.sin@;
+ @}
+
| IF Expr THEN Statseq ELSE Statseq END
+ @{
+ @i @Expr.s@ = @Statement.sin@;
+ @i @Statseq.0.s@ = @Statement.sin@;
+ @i @Statseq.1.s@ = @Statement.sin@;
+ @i @Statement.sout@ = @Statement.sin@;
+ @}
+
| WHILE Expr DO Statseq END
+ @{
+ @i @Expr.s@ = @Statement.sin@;
+ @i @Statseq.s@ = @Statement.sin@;
+ @i @Statement.sout@ = @Statement.sin@;
+ @}
+
| RETURN Expr
+ @{
+ @i @Expr.s@ = @Statement.sin@;
+ @i @Statement.sout@ = @Statement.sin@;
+ @}
+
;
Lexpr:
IDENT
+ @{
+ @c check_variable(@Lexpr.s@, @IDENT.name@);
+ @}
+
| Term '.' IDENT
+ @{
+ @c check_variable(@Lexpr.s@, @IDENT.name@);
+ @}
+
;
Expr:
| '-' NUM
| THIS
| IDENT
+ @{
+ @c check_variable(@Term.s@, @IDENT.name@);
+ @}
+
| Term '.' IDENT
+ @{
+ @c check_variable(@Term.s@, @IDENT.name@);
+ @}
+
| IDENT '(' Exprs ')'
+ @{
+ @c check_variable(@Term.s@, @IDENT.name@);
+ @}
+
| Term '.' IDENT '(' Exprs ')'
+ @{
+ @c check_variable(@Term.s@, @IDENT.name@);
+ @}
+
;
/* beachte dass hier auch "nichts" vorkommen kann