|
%{ #include "stdio.h" #define NSYMS 20 /* maximum number of symbols */
struct symtab { char *name; double (*funcptr)(); double value; } symtab[NSYMS];
struct symtab *symlook(); #include <string.h> #include <math.h> %}
%union { double dval; struct symtab *symp; } %token <symp> NAME %token <dval> NUMBER %left '-' '+' %left '*' '/' %nonassoc UMINUS
%type <dval> expression %% statement_list: statement '\n' | statement_list statement '\n' ;
statement: NAME '=' expression { $1->value = $3; } | expression { printf("= %g\n", $1); } ;
expression: expression '+' expression { $$ = $1 + $3; } | expression '-' expression { $$ = $1 - $3; } | expression '*' expression { $$ = $1 * $3; } | expression '/' expression { if($3 == 0.0) printf("divide by zero\n"); else $$ = $1 / $3; } | '-' expression %prec UMINUS { $$ = -$2; } | '(' expression ')' { $$ = $2; } | NUMBER | NAME { $$ = $1->value; } | NAME '(' expression ')' { if($1->funcptr) $$ = ($1->funcptr)($3); else { printf("%s not a function\n", $1->name); $$ = 0.0; } } ; %% /* look up a symbol table entry, add if not present */ struct symtab *symlook(char* s) { char *p; struct symtab *sp; for(sp = symtab; sp < &symtab[NSYMS]; sp++) { /* is it already here? */ if(sp->name && !strcmp(sp->name, s)) return sp; /* is it free */ if(!sp->name) { sp->name = strdup(s); return sp; } /* otherwise continue to next */ } printf("Too many symbols\n"); exit(1); /* cannot continue */ } /* symlook */
addfunc(name, func) char *name; double (*func)(); { struct symtab *sp = symlook(name); sp->funcptr = func; }
main() { extern double sqrt(), exp(), log();
addfunc("sqrt", sqrt); addfunc("exp", exp); addfunc("log", log); yyparse(); } yyerror(char *s) { fprintf(stderr,"%s\n",s); }
int yywrap() { return(1); }
|