%{ #include #include #include #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; }