本文參考網頁“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 <stdio.h>
%}
%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中重新編譯生成項目。
運作效果如下圖所示:
1. 若幹錯誤的解決方法
1.1. error C4996
error C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
錯誤解決方法可參看網頁:
在項目屬性對話框的預處理器中添加“_CRT_SECURE_NO_WARNINGS”。