一、实验目的
1. 学习使用语法分析程序自动构造工具 Bison
3
2. 熟悉YACC源程序语法
3. 掌握语法分析程序的自动构造方法
二、实验平台
Windows + Flex + Bison
三、基础内容
1. 实现以下步骤, 掌握Flex和Bison的工作过程
a) 在 DOS 命令提示符下依次执行以下两行命令
flex calc.lex
bison -ocalc.c calc.y
b) 编译运行 calc.c
2. 测试目录 SRC_BISON中的范例程序,了解其功能及实现。
3. 参考范例程序, 用Flex和 Bison实现一个功能更为强大的计算器,包含以下运算:
a) 加、减、乘、除运算
b) 乘方、开方运算
c) 位运算
– 与 & 、或 |、非 ~...
d) 阶乘运算 !
calc.lex文件如下:
%{
/*
* 一个简单计算器的Lex词法文件
*/
#include <stdlib.h>
void yyerror(char*);
/* #include "calc.tab.h" */
%}
%%
/* a-z为变量 */
[a-z] {
yylval = *yytext - 'a';
return VARIABLE;
}
/* 整数 */
[0-9]+ {
yylval = atoi(yytext);
return INTEGER;
}
/* 运算符 */
[-+()=/*^&|~[!SCTL%\n] {return *yytext;}
/* 空白被忽略 */
[ \t] ;
/* 其他字符都是非法的 */
. yyerror("无效的输入字符");
%%
int yywrap(void)
{
return 1;
}
calc.y文件如下:
%token INTEGER VARIABLE
%left '+' '-'
%left '*' '/'
%left '^' '['
%left '!' '&'
%left '|' '~'
%left 'S' 'C''T'
%left 'L' '%'
%{
#define YYSTYPE double
#define w (0.017453292519943)
#include <math.h>
#define __STDC__ 0
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 '[' expr {$$ = pow($3,1.0/$1);}
|expr '!' {int i,s=1;
for(i=1;i<=$1;i++)
s=s*i;
$$=s;
}
|expr '&' expr { $$ = (int)($1)&(int)($3);}
|expr '|' expr { $$ = (int)($1)|(int)($3);}
|'~'expr { $$ = !($2);}
|'S''('expr')' { $$=sin($2*(w));}
|'C''('expr')' { $$=cos($2*(w));}
|'T''('expr')' { $$ = tan($2*(w));}
|'L''('expr')' { $$ = log($3);}
|expr '%' expr {$$ = (int)($1)%(int)($3);}
|'('expr')' {$$ = $2;}
;
%%
void yyerror(char* s)
{
fprintf(stderr, "%s\n", s);
}
#include "lex.yy.c"
int main(void)
{
printf("A simple calculator.\n");
printf("加(+),减(-),乘(*),除(/),乘方(^),开方([),阶乘(!).\n");
printf("与(&),或(|),非(~)\n");
printf("S (sin)、C (cos)、T (tan):三角函数\n");
printf("求对数(L),求模(%)"\n");
printf("START:\n");
yyparse();
return 0;
}
心得体会:
经过这次的实验,我学到了很多新的知识和好的学习方法。说实话,刚开始并不知道这门课程的实验到底要怎么做,不知道从何做起。但是经过调试老师给的事例,不断的失败不断的重复实验,不会的问同学,看书,百度,总之就是不断重复。终于,我做出来了,这离不开同学的耐心讲解和一直坚持的自己。或许,有些事开始认为不可能,只有在自己坚持做了,才会取得成果!下次继续努力吧!