1、打開cygwin,進入home目錄,home目錄在WINDOWS系統的cygwin安裝目錄映射為home目錄。
2、首先,在home目錄中新建文件夾,在文件夾中放置如下內容的test1.l
/*統計字數*/%{int chars=0;int words=0;int lines=0;%}%%[a-zA-Z]+ {words++;chars+=strlen(yytext);}/n {chars++;lines++;}. {chars++;}%%main(int argc,char**argv){ yylex(); printf("%d%d%d/n",lines,words,chars);}
然后調用flex生成詞法分析器
Administrator@2012-20121224HD /home/flexlinux$ cd /homeAdministrator@2012-20121224HD /home$ cd flexlinuxAdministrator@2012-20121224HD /home/flexlinux$ flex test1.lAdministrator@2012-20121224HD /home/flexlinux$
可以看到目錄中的lex.yy.c就是剛生成的C源碼,可分析詞法。
Administrator@2012-20121224HD /home/flexlinux$ lslex.yy.c test1.l
二、flex和bison聯合工作
1 、我們開始構造一個計算器程序。
創建flex代碼
/*計算器*/%{enum yytokentype{ NUMBER=258, ADD=259, SUB=260, MUL=261, DIV=262, ABS=263, EOL=264};int yylval;%}%%"+" {return ADD;}"-" {return SUB;}"*" {return MUL;}"/" {return DIV;}"|" {return ABS;}[0-9]+ {yylval=atoi(yytext);return NUMBER;}/n {return EOL;}[ /t] {/*空白忽略*/}. {printf("非法字符 %c/n",*yytext);}%%main(int argc,char**argv){ int tok; while(tok=yylex()){ printf("%d",tok); if (tok==NUMBER) printf("=%d/n",yylval); else printf("/n"); }}
2、編譯
Administrator@2012-20121224HD /home/flexlinux$ flex test2.lAdministrator@2012-20121224HD /home/flexlinux$ gcc lex.yy.c -lfl
3、運行
Administrator@2012-20121224HD /home/flexlinux$ ./a- 12 66260258=12258=66264Administrator@2012-20121224HD /home/flexlinux$ ./a/ 56 2 + |32262258=56258=2259263258=32264Administrator@2012-20121224HD /home/flexlinux$
(2)計算器的BISON程序
%{#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;} ;%%main(int argc,char **argv){yyparse();}yyerror(char *s){ fprintf(stderr,"error:%s/n",s);}$ bison -d test2.yt$ lstest2.tab.c test2.tab.h test2.y test2.y~
然后,修改剛才的flex文件,將其命名為test21.l
test2.tab.h中包含了記號編號的定義和yylval的定義,因此,將其第一部分的相關定義刪除,并改為:
/計算器/
%{
#include "test2.tab.h"
%}
然后刪除,其第三部分的main函數。
最后,進行編譯。
bison -d test2.yflex test21.lgcc test2.tab.c lex.yy.c -lfl
可以測試一下
root@myhaspl:~# ./a.out12 + 36 * 2=8412 / 6 + 2 * 3=8
(2)擴充計算器
加入對括號和注釋的支持,
首先修改flex文件,在第二部分加入更多的詞法規則(對于注釋直接忽略):
"(" {return LEFTBRACKET;}
")" {return RIGHTBRACKET;}
"#". /忽略注釋*/
然后,修改bison文件,在第二部分加入更多的語法規則:
term:NUMBER {$$=$1;}
|ABS term {$$=$2>=0?$2:-$2;}
|LEFTBRACKET exp RIGHTBRACKET {$$=$2;}
;
我們的注釋以“#”表示
測試結果
myhaspl@myhaspl:~/flex_bison/2$ makebison -d calculator.yflex calculator.lgcc calculator.tab.c lex.yy.c -lflmyhaspl@myhaspl:~/flex_bison/2$ lsa.out calculator.tab.c calculator.y makefilecalculator.l calculator.tab.h lex.yy.cmyhaspl@myhaspl:~/flex_bison/2$ ./a.out12-36*10/(1+2+3)#compute=-48^Cmyhaspl@myhaspl:~/flex_bison/2$
前面都是以鍵盤輸入 的方式進行計算器運算,我們下面以文件方式提供給該解釋器進行計算,首先,將flex文件改為(將其中中文去除,然后對于非法字符的出現進行忽略):
%{#include "calculator.tab.h"%}%%"+" {return ADD;}"-" {return SUB;}"" {return MUL;}"/" {return DIV;}"|" {return ABS;}"(" {return LEFTBRACKET;}")" {return RIGHTBRACKET;}"#". /comment/[0-9]+ {yylval=atoi(yytext);return NUMBER;}/n {return EOL;}[ /t] /blank/. /invalid char/%
接著,改bison文件,加入對文件的讀寫
%{#include <stdio.h>%}%token NUMBER%token ADD SUB MUL DIV ABS LEFTBRACKET RIGHTBRACKET%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;} |LEFTBRACKET exp RIGHTBRACKET {$$=$2;} ;%%main(int argc,char **argv){int i;if (argc<2){ yyparse();}else{ for(i=1;i<argc;i++) { FILE *f=fopen(argv[i],"r"); if (!f){ perror(argv[i]); return (1); } yyrestart(f); yyparse(); fclose(f); }}}yyerror(char *s){ fprintf(stderr,"error:%s/n",s);}
最后 測試一下
root@myhaspl:~/test/3# makebison -d calculator.yflex calculator.lgcc calculator.tab.c lex.yy.c -lflroot@myhaspl:~/test/3# ./a.out mycpt1.cpt mycpt2.cpt=158=-8root@myhaspl:~/test/3#
其中兩個CPT文件內容類似 為:
12*66/(10-5)
我們接著完善這個計算器程序,讓算式能顯示出來,修改calculator.l
通過加入printf語句,打印詞法分析器解析到的字符。比如 :
..................
[0-9]+ {yylval=atoi(yytext);printf("%d",yylval);return NUMBER;}
/n {return EOL;}
[ /t] /blank/
. /invalid char/
%%
然后編譯執行。
root@myhaspl:~/test/4# makebison -d calculator.yflex calculator.lgcc calculator.tab.c lex.yy.c -lflroot@myhaspl:~/test/4# ./a.out12+6612+66=78^Croot@myhaspl:~/test/4# ./a.out mycpt1.cpt mycpt2.cpt 12*66/(10-5)=15877/(10+1)-15=-8
接下來加上讀取的行號,將結果的顯示更加人性化
flex文件要改:
/n {printf("<line:%4d>",yylineno);yylineno++;return EOL;}
然后,bison文件也改:
calclist:/**/
|calclist exp EOL{printf ("the result is:%d/n",$2);}
;
最后 ,編譯運行測試一下。
root@myhaspl:~/test/4# makebison -d calculator.yflex calculator.lgcc calculator.tab.c lex.yy.c -lflroot@myhaspl:~/test/4# ./a.out mycpt1.cpt mycpt2.cpt1266/(10-5)<line: 1>the result is:15812/22-8<line: 2>the result is:-877(6-2)<line: 3>the result is:30877/(10+1)-15<line: 4>the result is:-8root@myhaspl:~/test/4#
新聞熱點
疑難解答
圖片精選