, 打开 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?/home
- Administrator@2012-20121224HD?/home
- $?cd?flexlinux
- Administrator@2012-20121224HD?/home/flexlinux
- $?flex?test1.l
- Administrator@2012-20121224HD?/home/flexlinux
- $
可以看到目录中的 lex.yy.c 就是刚生成的 C 源码, 可分析词法.
- Administrator@2012-20121224HD?/home/flexlinux
- $?ls
- lex.yy.c??test1.l
二, flex 和 bison 联合工作
本博客所有内容是原创, 如果转载请注明来源
http://blog.csdn.net/myhaspl/
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.l
- Administrator@2012-20121224HD?/home/flexlinux
- $?gcc?lex.yy.c?-lfl
3, 运行
- Administrator@2012-20121224HD?/home/flexlinux
- $?./a
- -?12?66
- 260
- 258=12
- 258=66
- 264
- Administrator@2012-20121224HD?/home/flexlinux
- $?./a
- /?56?2?+?|32
- 262
- 258=56
- 258=2
- 259
- 263
- 258=32
- 264
- Administrator@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.y
- t$ ls
- test2.tab.c? test2.tab.h? test2.y? test2.y~
- 然后, 修改刚才的 flex 文件, 将其命名为 test21.l
- test2.tab.h 中包含了记号编号的定义和 yylval 的定义, 因此, 将其第一部分的相关定义删除, 并改为:
- / 计算器 /
- %{
- ??#include?"test2.tab.h"
- %}
- 然后删除, 其第三部分的 main 函数.
- 最后, 进行编译.
- bison?-d?test2.y
- flex?test21.l
- gcc?test2.tab.c?lex.yy.c?-lfl
- 可以测试一下
- root@myhaspl:~#?./a.out
- 12?+?36?*?2
- =84
- 12?/?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$?make
- bison?-d?calculator.y
- flex?calculator.l
- gcc?calculator.tab.c??lex.yy.c?-lfl
- myhaspl@myhaspl:~/flex_bison/2$?ls
- a.out?????????calculator.tab.c??calculator.y??makefile
- calculator.l??calculator.tab.h??lex.yy.c
- myhaspl@myhaspl:~/flex_bison/2$?./a.out
- 12-36*10/(1+2+3)#compute
- =-48
- ^C
- myhaspl@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# make
- bison -d calculator.y
- flex calculator.l
- gcc calculator.tab.c ?lex.yy.c -lfl
- root@myhaspl:~/test/3# ./a.out mycpt1.cpt mycpt2.cpt
- =158
- =-8
- root@myhaspl:~/test/3#?
其中两个 CPT 文件内容类似 为:
12*66/(10-5)
来源: http://www.bubuko.com/infodetail-2867832.html