symtab.h
#define NSYMS 20 /* max number of symbols */
struct symtab
{
char *name;
double (*funcptr)();
double value;
} symtab[NSYMS];
struct symtab *symlook(char*);
/*************************************************************/
y.tab.h
#define PIVAL 257
#define NAME 258
#define NUMB 259
#define UMINUS 260
#ifdef YYSTYPE
#undef YYSTYPE_IS_DECLARED
#define YYSTYPE_IS_DECLARED 1
#endif
#ifndef YYSTYPE_IS_DECLARED
#define YYSTYPE_IS_DECLARED 1
typedef union
{
double dval;
struct symtab *symp;
} YYSTYPE;
#endif /* !YYSTYPE_IS_DECLARED */
extern YYSTYPE yylval;
/*************************************************************/
lex.l
%{
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "symtab.h"
#include "y.tab.h"
%}
%%
pi return PIVAL;
[ t] ;
[A-Za-z][A-Za-z0-9]* {yylval.symp = symlook(yytext); return NAME;}
([0-9]+|([0-9]*.[0-9]+)([eE][-+]?[0-9]+)?) {yylval.dval = atof(yytext); return NUMB;}
"$" return 0;
n |
. return yytext[0];
%%
int yywrap(void)
{
return 1;
}
/*************************************************************/
yacc.y
%{
#include "symtab.h"
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
int nsym = 0;
%}
%union
{
double dval;
struct symtab *symp;
}
%token PIVAL
%token <symp> NAME
%token <dval> NUMB
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
%type <dval> expr
%%
line : stmt 'n'
| line stmt 'n'
;
stmt : NAME '=' expr {$1->value=$3;}
| expr { printf("=%gn", $1);}
;
expr : expr '+' expr {$$ = $1 +$3;}
| expr '-' expr {$$ = $1 - $3;}
| expr '*' expr {$$ = $1 * $3;}
| expr '/' expr
{
if($3==0.0)
yyerror("Divided by zero!n");
else
$$ = $1 / $3;
}
| '-' expr %prec UMINUS {$$ = -$2;}
| '(' expr ')' {$$ = $2;}
| NUMB
| NAME {$$ = $1->value;}
| NAME '(' expr ')'
{
if ($1->funcptr)
$$ = ($1->funcptr)($3);
else
{
printf("%s is not a function!n", $1->name);
$$ = 0.0;
}
}
| NAME '(' expr ',' expr ')'
{
if ($1->funcptr)
$$ = ($1->funcptr)($3, $5);
else
{
printf("%s is not a function!n", $1->name);
$$ = 0.0;
}
}
| PIVAL {$$ = M_PI;}
;
%%
int yyerror (char *err)
{
fprintf(stderr, "%s", err);
}
struct symtab *symlook(char *s)
{
int i;
for (i = 0; i < nsym; ++i)
{
if (!strcmp(symtab[i].name, s))
return &symtab[i];
}
if (nsym < NSYMS)
{
symtab[nsym].name = strdup(s);
++nsym;
return &symtab[nsym-1];
}
yyerror("Too many symbols!n");
exit(1);
}
void addfunc( char *name, double(*func)() )
{
struct symtab *sp = symlook(name);
sp->funcptr = func;
}
int main(void)
{
extern double pow(), sqrt(), log(), exp(), sin(), cos(), tan();
addfunc("pow", pow);
addfunc("sqrt", sqrt);
addfunc("log", log);
addfunc("exp", exp);
addfunc("sin", sin);
addfunc("cos", cos);
addfunc("tan", tan);
yyparse();
return 0;
}
Lex&yacc简单计算器
最新推荐文章于 2021-07-28 23:49:07 发布