%start program /* SEMANTIC RECORD */ /* char *id: For returning identifiers */ /* Place to easily pasting/cutting the union declaration */ %union { char *id; } /* Simple identifier */ /* Place to exchange the IDENTIFIER token declarations */ %token IDENTIFIER %type IDENTIFIER %token LET IN /* "integer" keyword */ /* both INT e INTEGER exist? Removed INT, occurrences changed. %token INT */ %token INTEGER /* Same question for NUMBER: should it exist? Replaced all of its occurrences with INTEGER -> wrong, written numbers X 'integer' keyword. Changes undone */ %token NUMBER /* FI was missing */ %token SKIP IF THEN ELSE FI END WHILE DO READ WRITE /* ASSGNOP was missing */ %token ASSGNOP %left '-' '+' %left '*' '/' %left '<' '>' '=' '' /* these where missing on the book, added */ %right '^ ' %{ #include /* For malloc in symbol table */ #include /* For strcmp in symbol table */ #include /* For error messages */ #include "st.h" /* The Symbol Table Module */ /* Redeclaration? Should not be #define YYDEBUG 1 / * for debugging / para depuração */ /* Global variable 'Errors' to substitute the previously undeclared variable 'errors' */ int Errors = 0; int yyerror (char *s); // function header, removes a warning int install( char* sym_name) { symrec *s; s = getsym(sym_name); if (s == 0) s = putsym (sym_name); else { Errors++; printf("%s is already defined\n", sym_name); return 0; } return 1; } int context_check(char* sym_name) { if ( getsym( sym_name ) == 0 ) { printf("%s is an undeclared identifier\n", sym_name); return 0; } return 1; } %} %% /* Grammar rules and actions */ program : LET declarations IN commands END ; declarations : /* empty */ | INTEGER id_seq IDENTIFIER '.' { install( $3 ); } ; id_seq : /* empty */ | id_seq IDENTIFIER ',' { install( $2 ); } ; commands : /* empty */ | commands command ';' ; command : SKIP | READ IDENTIFIER { context_check( $2 ); } | WRITE exp | IDENTIFIER ASSGNOP exp { context_check( $1 ); } | IF exp THEN commands ELSE commands FI | WHILE exp DO commands END ; /* expressions */ exp : NUMBER /* in book it is $2, wrong */ | IDENTIFIER { context_check( $1 ); } | exp '<' exp | exp '=' exp | exp '>' exp | exp '+' exp | exp '-' exp | exp '' exp | exp '/' exp | exp '^ ' exp | '(' exp ')' ; %% /* C subroutines */ /* não tem saída, a árvore de reconhec. fica implícita */ /* no output, implicit parse tree */ int main( int argc, char *argv[] ) { extern FILE *yyin; ++argv; --argc; yyin = fopen( argv[0], "r" ); // yydebug = 1; // line commented -> bad fix // errors = 0; // initialization unneeded => line removed yyparse (); return 0; } int yyerror (char *s) /* called by yyparse() in error situations */ { printf ("%s\n", s); return 0; }