%{ #include #include #include "scanType.h" extern int yylex(); extern int yylineno; extern int line; extern char *nextToken; #define YYERROR_VERBOSE void yyerror(const char *msg) { if (line != yylineno) printf("LINE: %d %d \n", line, yylineno); if (nextToken[0] == '\n') nextToken = (char *)"\\n"; // memory leak printf("ERROR(%d):%s. I got: \"%s\"\n", yylineno, msg, nextToken); fflush(stdout); } // variable storage double vars[26]; %} %union { TokenData *tokenData; double value; } // token specifies the token classes from the scanner %token NUMBER ID QUIT // type specifies the token classes used only in the parser %type expression term varornum statement %% statementlist : statement '\n' | error '\n' { yyerrok; } // catch all errors + has synchronizing token in newline so yyerrok | statementlist statement '\n' ; statement : ID '=' statement { vars[$1->idValue] = $3; $$=$3; } | ID '=' error { $$ = 0; } // right side error with no following token | ID error { $$ = 0; } // right side error with no following token | expression { printf("ANS: %f\n", $1); } | QUIT { exit(0); } ; expression: expression '+' term { $$ = $1 + $3; } | expression '-' term { $$ = $1 - $3; } | expression '+' error { $$ = $1; } | expression '-' error { $$ = $1; } | term { $$ = $1; } ; term : term '*' varornum { $$ = $1 * $3; } | term '/' varornum { if ($3==0) { printf("ERROR: Divide %f by zero\n", $1); } else { $$ = $1 / $3; } } | varornum { $$ = $1; } | term '*' error { $$ = 0; } | term '/' error { $$ = $1; } ; varornum : NUMBER { $$ = $1->numValue; } | ID { $$ = vars[$1->idValue]; } | '(' expression ')' { $$ = $2; } | '-' varornum { $$ = -$2; } // unary minus | '(' error { $$ = 0; } | '-' error { $$ = 0; } ; %% int main(int argc, char *argv[]) { int i; yydebug=(argc>1 ? 1 : 0); // do the calculator for (i=0; i<26; i++) vars[i] = 0.0; yyparse(); // call the parser return 0; }