本文参考网页“Flex和Bison简介和Windows下使用入门”( Flex和Bison简介和Windows下使用入门 | 码农家园 ),使用Win-flex bison生成生成一个计算器(VS2022)。
1. 使用VS2022创建空项目
使用VS2022创建名为MyProject的空项目。项目所在目录为“D:\temp\MyProject”。
2. 编写lex及yacc(bison)程序(文本文件)
2.1 lex程序
在目录“D:\temp\MyProject”中,使用文本编辑器(比如Notepad++)创建名为“bo.l”文本文件(即lex程序),内容如下:
%{
#include "b.y.h"
%}
%%
"+" {return ADD;}
"-" {return SUB;}
"*" {return MUL;}
"/" {return DIV;}
"|" {return ABS;}
[0-9]+ {yylval=atoi(yytext);return NUMBER;}
\n {return EOL;}
%%
int yywrap()
{
return(1);
}
2.2 yacc(bison)程序
在目录“D:\temp\MyProject”中,使用文本编辑器(比如Notepad++)创建名为“b.y”文本文件(即yacc程序),内容如下:
%{
#include
%}
%token NUMBER
%token ADD SUB MUL DIV ABS
%token EOL
%%
calclist: /*空规则*/
|calclist exp EOL {printf("=%d\n",$2);};
exp:factor{$$=$1;}
|exp ADD factor {$$=$1+$3;}
|exp SUB factor{$$=$1-$3;};
factor: term {$$=$1;}
|factor MUL term{$$=$1*$3;}
|factor DIV term{$$=$1/$3;};
term:NUMBER {$$=$1;}
|ABS term {$$=$2>0?$2:-$2;};
%%
int main(int argc,char ** argv){
yyparse();
}
yyerror(char *s){
fprintf(stderr,"error:%s\n",s);
}
3. 使用flex和bison生成C语言程序
在命令行窗口输入下列命令生成C语言程序(wincompat参数,命令lex编译器创建Windows兼容的程序):
path=D:\Programs\win_flex_bison-latest;%path%
cd D:\temp\MyProject
D:
win_bison --defines=b.y.h --output=b.y.c b.y
win_flex --wincompat --outfile=bo.yy.c bo.l
我的win_flex程序所在目录为“D:\Programs\win_flex_bison-latest”。
上述命令正常执行后,生成文件“bo.yy.c”、“b.y.h”、“b.y.c”。
经上述步骤之后,目录“D:\temp\MyProject”中的内容如下图所示:
4. 在VS2022编译程序
在VS2022的中(即项目的“解决方案资源管理器”视图),将“bo.yy.c”、“b.y.h”、“b.y.c”添加到上文创建的空项目MyProject中。
编译程序即可运行。
为了达到更好的调试效果,需要将预编译指令“#line”注释掉,因为使用预编译指令“#line”时,调试时会到其使用的文件中(为了提高效率,可以使用替换窗口将字符串“#line”替换为“//#line”)
运行效果如下:
5. 程序的改进
上述步骤生成的程序只能进行整数的加减乘除运算,不能进行浮点数的预算,为了进行浮点数的运算,可做如下修改。
(1)lex程序“bo.l”文本文件的修改。将
[0-9]+ {yylval=atoi(yytext);return NUMBER;}
改为
[0-9]+(.[0-9]+)? {yylval=atof(yytext);return NUMBER;}
(2)yacc程序“b.y”文本文件的修改。将
|calclist exp EOL {printf("=%d\n",$2);};
改为
|calclist exp EOL {printf("=%3.3lf\n",$2);};
(3)使用win_bison和win_flex生成文件“bo.yy.c”、“b.y.h”、“b.y.c”。
(4)头文件“b.y.h”的修改。将
typedef int YYSTYPE;
改为
typedef double YYSTYPE;
(5)文件“b.y.c”的修改。将
typedef int YYSTYPE;
改为
typedef double YYSTYPE;
(5)在VS2022中重新编译生成项目。
运行效果如下图所示: