/* * SACALC EXAMPLE */ %{ #include #define YYDEBUG #define YYSTYPE double /* data type of yacc stack */ #define QUIT ( (double) 101010 ) %} %token NUMBER %left '+' '-' /* left associative, same precedence */ %left '*' '/' /* left associative, higher precedence */ %left UNARYMINUS %% list: /* nothing */ { prompt(); } | list '\n' { prompt(); } | list expr '\n' { if ($2 == QUIT) { return(0); } else { fprintf(stdout, " RESULT ==========> %.8g\n", $2); prompt(); } } | list error '\n' { yyerrok; prompt(); } ; expr: NUMBER { $$ = $1; } | '-' expr %prec UNARYMINUS { $$ = -$2; } | expr '+' expr { $$ = $1 + $3; } | expr '-' expr { $$ = $1 - $3; } | expr '*' expr { $$ = $1 * $3; } | expr '/' expr { $$ = $1 / $3; } | '(' expr ')' { $$ = $2; } ; %% #include #include char *progname; /* for error messages */ int lineno = 1; extern int yyparse( void ); void main( int, char ** ); int yylex( void ); void prompt( void ); void yyerror( char * ); void warning( char *, char * ); void main( int argc, char **argv ) { if (argc > 1) fprintf(stderr, "nonmeaningful arguments\n"); progname = *argv; fprintf(stdout, "\n****************************************************\n"); fprintf(stdout, "* SACALC: a Simple Arithmetic Calculator *\n"); fprintf(stdout, "* *\n"); fprintf(stdout, "* 1)at the prompt READY> *\n"); fprintf(stdout, "* you type in an expression, e.g. 1+2*3 *\n"); fprintf(stdout, "* SACALC will evaluate the expression *\n"); fprintf(stdout, "* and the result is displayed *\n"); fprintf(stdout, "* 2)to terminate the program *\n"); fprintf(stdout, "* type QUIT *\n"); fprintf(stdout, "* 3)if you make a mistake *\n"); fprintf(stdout, "* SACALC will complain and start over again *\n"); fprintf(stdout, "* *\n"); fprintf(stdout, "****************************************************\n\n\n"); yyparse(); fprintf(stdout, "\n****************************************************\n"); fprintf(stdout, "* SACALC: a Simple Arithmetic Calculator *\n"); fprintf(stdout, "* *\n"); fprintf(stdout, "* normal termination -- bye! *\n"); fprintf(stdout, "****************************************************\n"); } int yylex( void ) { int c; while ((c=getchar()) == ' ' || c == '\t' ) ; if (c == EOF) return 0; if (c == '.' || isdigit(c)) { /* number */ ungetc(c, stdin); scanf("%lf", &yylval); return NUMBER; } if (c == '\n') lineno++; if (c == 'Q' || c == 'q') /* ugly code */ if ((c=getchar()) == 'U' || c == 'u') if ((c=getchar()) == 'I' || c == 'i') if ((c=getchar()) == 'T' || c == 't') { yylval = QUIT; return( EOF ); } else return '?'; return( c ); } void yyerror( char *s ) /* called for yacc syntax error */ { warning(s, (void *) 0); } void warning( char *s, char *t ) /* print warning message */ { fprintf(stderr, "%s: %s", progname, s); if (t) fprintf(stderr, " %s", t); fprintf(stderr, " near line %d\n", lineno); } void prompt( void ) { fprintf(stdout, "READY> "); }