要求
基于词法分析程序自动构造工具Flex与语法分析程序自动构造工具Bison,编制简单的计算器程序。
参考示例程序, 用Flex和Bison实现一个功能更为强大的计算器,尽可能多的包含以下运算(支持浮点数):
a) 加、减、乘、除运算
b) 乘方power、开方sqrt运算
c) 位运算 – 与、或、非...(不做)
d) 三角函数运算 – sin、cos...
e) 求阶乘
f) 求模(不做)
g) 求log以e为底的对数(不做)
h) 求log以10为底的对数
测试样例
52+ 21*2 - 2.1
91.9
(25*2+3)*(1-25)
-1272
pow(4,2)+sqrt(144)
28
sin(30)*cos(60)
0.25
log(100)+3!
8
具体实现
具体步骤见https://blog.csdn.net/artherlex/article/details/103455632
下面是calc.l和calc.y的具体实现
calc.l
%{
#include "calc.tab.h"
#define YYSTYPE double
#include <stdlib.h>
void yyerror(char*);
%}
%%
(0(\.[0-9]+)?)|([1-9][0-9]*(\.[0-9]+)?) { yylval = atof(yytext); return NUMBER; }
[-+()=/*!,\n] {
return *yytext;
}
"sin" {return SIN;}
"cos" {return COS;}
"tan" {return TAN;}
"pow" {return POW;}
"sqrt" {return SQRT;}
"log" {return LOG;}
"//".*
[ \t] { /* ignore white space */ }
. {}
%%
int yywrap()
{return 1;}
calc.y
%token NUMBER SIN COS TAN LOG SQRT POW
%left '+' '-'
%left '*' '/'
%left '!'
%left ','
%{
#include <stdio.h>
#include <math.h>
#define YYSTYPE double
#define pi 3.1415926
int yylex();
void yyerror(char*);
%}
%%
program:
program statement '\n'
|
;
statement:
expr {printf("%g\n",$1);}
|
;
expr:
NUMBER
|expr '+' expr {$$ = $1 + $3;}
|expr '-' expr {$$ = $1 - $3;}
|expr '*' expr {$$ = $1 * $3;}
|expr '/' expr {$$ = $1 / $3;}
|expr '!' {int i=1,s=1;for(;i<=$1;i++){s*=i;}$$=s;}
|'('expr')' {$$ = $2;}
|LOG'('expr')' { $$ = log10($3); }
|POW '('expr','expr')' { $$ = pow($3,$5); }
|SQRT '('expr')' { $$ = sqrt($3); }
|SIN'('expr')' {$$ = sin($3*pi/180.0);}
|COS'('expr')' {$$ = cos($3*pi/180.0);}
|TAN'('expr')' {$$ = tan($3*pi/180.0);}
;
%%
int main()
{
yyparse();
return 0;
}
yyerror(char *s)
{
fprintf(stderr, "error: %s\n", s);
}