1、使用Flex來生成一個詞法分析器
創(chuàng)建名為a.l的文件,在其內(nèi)輸入:
%{
#include "b.tab.h"
int yylval;
%}
%%
"+" {return ADD;}
"-" {return SUB;}
"*" {return MUL;}
"/" {return DIV;}
"|" {return ABS;}
[0-9]+ {yylval=atoi(yytext);return NUMBER;}
\n {return EOL;}
%%
說明
- 第一部分,即
%{...%}之內(nèi)的內(nèi)容,是聲明部分,會被照原樣抄到生成的C文件頭部。在這里,變量yylvl將會用來存儲識別的數(shù)。而#include "b.tab.h"表示包含由bison生成的包含一個符號表的頭文件。該代碼中第二部分的ADD、SUB等等這些都是在"b.tab.h"中定義的。 - 第二部分,即
%%...%%中定義的是模式部分,花括號中是匹配到該符號(Token)時的行為,如果是return將會返回這個符號(如ADD、SUB等等。) - 實際上應(yīng)該還有第三部分,即一個C語言的主程序,但是,因為我們需要它和Bison生成的語法分析器協(xié)同工作,也就不必有這個部分了。
執(zhí)行文件
使用命令行,目錄切換至當(dāng)前,使用命令
flex a.l
從而會生成一個名為lex.yy.c的C語言文件。
2、使用Bison來生成一個語法分析器
創(chuàng)建名為b.y的文件,在其內(nèi)輸入:
%{
#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);
}
說明
- 第一部分,即
%{...%}之內(nèi)的內(nèi)容,是聲明部分,會被照原樣抄到生成的C文件頭部。在這里,引用stdio.h頭文件,會在第三部分中使用。 - 第二部分,即
%%...%%中定義的是模式部分,定義BNF規(guī)則,以冒號:分隔。每條規(guī)則以分號;結(jié)束。在花括號中,$$表示冒號左邊的值,而$1、$2…等等依次表示冒號后面的值。第一條規(guī)則左邊是起始符號。
執(zhí)行文件
使用命令行,目錄切換至當(dāng)前,使用命令
bison -d b.y
注意,一定要有-d,否則沒有頭文件生成。
此時會生成兩個文件:一個名為b.tab.h的頭文件,一個是b.tab.c文件。
3、聯(lián)合編譯
命令行中輸入:
gcc -o out b.tab.c lex.yy.c -lfl
沒有錯誤的話,就會生成一個名為out.exe的可執(zhí)行文件,我們在命令行中可以測試:

運行結(jié)果
4、雜記
-
fatal error:y.tab.h: No such file or directory on fedora?
...
Check these things:
● That the file actually is generated. You may have to give the flag -d to Bison/Yacc.
● That the file is called y.tab.h. The name can be different depending on program versions, and if you start Bison with the command bison or with the command yacc.
● That the file is in a directory where GCC can find it.