实现以下步骤, 掌握 Flex 和 Bison 的工作过程
a) 在 DOS 命令提示符下依次执行以下两行命令
flex calc.lex
bison -ocalc.c calc.y
b) 编译运行 calc.c
文件中内容如下:
编译运行完后:
题目要求:
用 Flex 和 Bison 实现一个功能更为强大的计算器,包含以下运算:
a) 加、减、乘、除运算
b) 乘方、开方运算
c) 位运算 – 与 & 、或 |、非 ~...
d) 阶乘运算 !
进一步完善计算器功能,实现对以下语法结构的分析。还可以进一步扩充功能。
12+23*34+sin(45)/cos(56)-67
calc.lex文件
<pre name="code" class="plain">%{
/*
* 一个简单计算器的Lex词法文件
*/
#include <stdlib.h>
#include <math.h>
void yyerror(char*);
/* #include "calc.tab.h" */
%}
%%
/* a-z为变量 */
[a-z] {
yylval = *yytext - 'a';
return VARIABLE;
}
/* 整数或浮点数 */
[0-9]+\.?|[0-9]*\.[0-9]+ {
yylval = atof(yytext);
return INTEGER;
}
/* 运算符 */
[-+()=/*^@&|~!\n] {return *yytext;}
sin {
return SIN;
}
cos {
return COS;
}
/* 空白被忽略 */
[ \t] ;
/* 其他字符都是非法的 */
. yyerror("无效的输入字符");
%%
int yywrap(void)
{
return 1;
}
calc.y文件
%token INTEGER VARIABLE SIN COS
%left '+' '-'
%left '*' '/'
%left '&'
%left '|'
%right SIN COS
%left '^'
%right '@' '~'
%left '!'
%{
#include <math.h>
#define pi 3.1415926
#define __STDC__ 0
#define YYSTYPE double
void yyerror(char*);
int yylex(void);
double sym[26];
%}
%%
program:
program statement '\n'
|
;
statement:
expr {printf("%f\n", $1);}
|VARIABLE '=' expr {sym[(int)$1] = $3;}
;
expr:
INTEGER
|VARIABLE {$$ = sym[(int)$1];}
|expr '+' expr {$$ = $1 + $3;}
|expr '-' expr {$$ = $1 - $3;}
|expr '*' expr {$$ = $1 * $3;}
|expr '/' expr {$$ = $1 / $3;}
|expr '^' expr {$$ = pow($1,$3);}
|'@' expr {$$ = sqrt($2);}
|expr '&' expr {$$ = (int)$1 & (int)$3;}
|expr '|' expr {$$ = (int)$1 | (int)$3;}
|'~' expr {$$ = ~ (int)$2;}
|expr '!' {int i=0;int s=1;for(i=1;i<=$1;i++){s=s*i;} $$ = s;}
|SIN '('expr ')' {$$ = sin($3*pi/180.0);}
|COS '('expr ')' {$$ = cos($3*pi/180.0);}
|'('expr')' {$$ = $2;}
;
%%
void yyerror(char* s){fprintf(stderr, "%s\n", s);}
#include "lex.yy.c"
int main(void)
{
printf("A simple calculator.\n");
yyparse();
return 0;
}
运行结果: