ag: paulchen init
[uebersetzerbau-ss10.git] / ag / parser.y
diff --git a/ag/parser.y b/ag/parser.y
new file mode 100644 (file)
index 0000000..7634069
--- /dev/null
@@ -0,0 +1,204 @@
+%{
+       #include <stdio.h>
+       #include <stdlib.h>
+       #include <string.h>
+       #include "symbol_table.h"
+%}
+
+%start         Input
+%token         FUNC END STRUCT VAR IF THEN ELSE WHILE DO RETURN OR NOT
+%token         ID NUM ASSIGN GREATER
+
+@autoinh symbols
+
+@attributes    { char *name; } ID
+@attributes    { struct symbol_t *fields; struct symbol_t *symbols; } Program
+@attributes    { struct symbol_t *fields; } Ids Structdef
+@attributes    { struct symbol_t *pars; } Pars
+@attributes    { struct symbol_t *symbols; } Funcdef Stats Bool Expr Call Lexpr Field Term Plusterm Malterm Bterm Orterm Exprs
+@attributes    { struct symbol_t *in_symbols; struct symbol_t *out_symbols; } Stat
+
+@traversal @postorder t
+
+%%
+
+Input:           Program
+               @{ @i @Program.symbols@ = @Program.fields@; @}
+
+               ;
+
+Program:         Funcdef ';' Program
+               @{
+                  @i @Program.fields@ = @Program.1.fields@;
+               @}
+
+               | Structdef ';' Program
+               @{
+                  @i @Program.fields@ = table_merge(@Structdef.fields@, @Program.1.fields@, 1);
+                  @i @Program.1.symbols@ = @Program.0.symbols@;
+               @}
+
+               |
+               @{ @i @Program.fields@ = new_table(); @}
+
+               ;
+Funcdef:         FUNC ID '(' Pars ')' Stats END
+                       @{ @i @Stats.symbols@ = table_merge(@Funcdef.symbols@, @Pars.pars@, 0); @}
+
+               |
+                 FUNC ID '(' ')' Stats END
+                       @{ @i @Stats.symbols@ = table_merge(@Funcdef.symbols@, new_table(), 0); @}
+
+               ;  
+Structdef:       STRUCT Ids END
+               @{ @i @Structdef.fields@ = @Ids.fields@; @}
+
+               ;  
+
+Ids:             ID Ids
+               @{ @i @Ids.fields@ = table_add_symbol(@Ids.1.fields@, @ID.name@, SYMBOL_TYPE_FIELD, 1); @}
+
+               |
+               @{ @i @Ids.fields@ = new_table(); @}
+
+               ;
+
+Pars:            Pars ',' ID
+               @{ @i @Pars.pars@ = table_add_symbol(@Pars.1.pars@, @ID.name@, SYMBOL_TYPE_VAR, 0); @}
+
+               | ID
+               @{ @i @Pars.pars@ = table_add_symbol(new_table(), @ID.name@, SYMBOL_TYPE_VAR, 0); @}
+
+               ; 
+Stats:           Stat ';' Stats
+               @{
+                  @i @Stat.in_symbols@ = @Stats.symbols@;
+                  @i @Stats.1.symbols@ = @Stat.out_symbols@;
+               @}
+
+               |
+               ;  
+Stat:            VAR ID ASSIGN Expr
+               @{
+                  @i @Stat.out_symbols@ = table_add_symbol(clone_table(@Stat.in_symbols@), @ID.name@, SYMBOL_TYPE_VAR, 0);
+                  @i @Expr.symbols@ = @Stat.in_symbols@;
+               @}
+
+               | Lexpr ASSIGN Expr
+               @{
+                  @i @Stat.out_symbols@ = @Stat.in_symbols@;
+                  @i @Lexpr.symbols@ = @Stat.in_symbols@;
+                  @i @Expr.symbols@ = @Stat.in_symbols@;
+               @}
+
+               | IF Bool THEN Stats END
+               @{
+                  @i @Bool.symbols@ = @Stat.in_symbols@;
+                  @i @Stats.symbols@ = @Stat.in_symbols@;
+                  @i @Stat.out_symbols@ = @Stat.in_symbols@;
+               @}
+
+               | IF Bool THEN Stats ELSE Stats END
+               @{
+                  @i @Bool.symbols@ = @Stat.in_symbols@;
+                  @i @Stats.symbols@ = @Stat.in_symbols@;
+                  @i @Stats.1.symbols@ = @Stat.in_symbols@;
+                  @i @Stat.out_symbols@ = @Stat.in_symbols@;
+               @}
+
+               | WHILE Bool DO Stats END
+               @{
+                  @i @Bool.symbols@ = @Stat.in_symbols@;
+                  @i @Stats.symbols@ = @Stat.in_symbols@;
+                  @i @Stat.out_symbols@ = @Stat.in_symbols@;
+               @}
+
+               | Call
+               @{
+                  @i @Call.symbols@ = @Stat.in_symbols@;
+                  @i @Stat.out_symbols@ = @Stat.in_symbols@;
+               @}
+
+               | RETURN Expr
+               @{
+                  @i @Expr.symbols@ = @Stat.in_symbols@;
+                  @i @Stat.out_symbols@ = @Stat.in_symbols@;
+               @}
+
+               ;
+Lexpr:           ID
+               @{ @t check_variable(@Lexpr.symbols@, @ID.name@); @}
+
+               | Field
+               ;
+Expr:            '-' Term
+               | Term
+               | Term Plusterm
+               | Term Malterm
+               ;
+
+Plusterm:        '+' Term Plusterm
+               | '+' Term
+               ;
+
+Malterm:         '*' Term Malterm
+                       | '*' Term
+               ;
+Term:            '(' Expr ')'
+               | ID
+               @{ @t check_variable(@Term.symbols@, @ID.name@); @}
+
+               | NUM
+               | Call
+               | Field
+               ;
+
+Bool:            Bterm
+               | Bterm Orterm
+               | NOT Bterm
+               ;
+
+Orterm:                  OR Bterm Orterm
+               | OR Bterm
+               ;
+
+Bterm:           Term GREATER Term
+               | Term '=' Term
+               | '(' Bool ')'
+               ;
+
+Field:           Term '.' ID
+               @{ @t check_field(@Field.symbols@, @ID.name@); @}
+
+               ;
+
+Call:            ID '(' Exprs ')'
+               | ID '(' ')'
+               ;
+
+Exprs:           Expr
+               | Exprs ',' Expr
+               ;
+
+%%
+
+extern int yylex();
+extern int yylineno;
+
+int yyerror(char *error_text) {
+       fprintf(stderr,"Line %i: %s\n",yylineno, error_text);
+       exit(2);
+}
+
+int main(int argc, char **argv) {
+       yyparse();
+       return 0;
+}
+