`
konsise
  • 浏览: 10814 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
最近访客 更多访客>>
社区版块
存档分类
最新评论

Lex&Yacc(2) 第一个flex的例子

阅读更多
在《lex&yacc第二版》开篇就给出了一个最简单的lex程序
//第一部分
%%
//第二部分
.|\n        ECHO;
%%
//第三部分

程序分为三个部分,第一部分为定义部分,包括宏定义和变量定义、Lex参数定义等。在定义变量和函数的时候,需要用%{和}%括起来,括起来的部分内容将在使用lex命令将lex源程序输出为.c文件的时候,被直接输出。如:
%{
#include <string.h>        //这里的代码将在生成的.c文件中,原封不动地复制过去。
...
}%
第二部分为lex程序主体部分。如:代码".|\n"表示的是匹配任何字符,ECHO表示打印解析到的内容。整个程序的主题代码只有一行,这一行的作用跟Unix中不带参数运行的cat命令很类似。
第三部分为用户子例程序部分,你可以重写lex中的一些函数,也可以重写main函数等。它接受任意合法的C代码组成。lex将会将第三部分的内容完整复制到C代码中。lex的main默认main函数为:
%%
main()
{
   yylex();
}

程序完成后,用下面三条命令进行编译并运行:
flex -och01.c ch1-01.l    //将ch1-01.l翻译为ch01.c程序
gcc ch01.c -o first -lfl  //将ch01.c用gcc命令编译,并引入库包:libfl.a
./first   //运行程序。运行程序后,当输入任意字符回车后,字符被重新打印出来。
如果使用lex命令而不是flex命令编译运行,则使用下面的三条命令:
lex -och01.c ch1-01.l
gcc ch01.c -o first -ll         //这里引入的库包为libl.a而不是flex的库。
./first 

了解了第一个lex程序的工作原理,我们写一个稍微复杂点儿的例子。
解析一个文件中的每一行的英文单词数以及单字总数。
分析需求,我们要修改lex的输入函数,让它从文件读取输入而不是从标准IO中读取。
其次,要设置变量显示每一行的单词数和总的单词数。
fl2.l 源码如下:
%{
#include <string.h>
int lineno = 1;                        //行号
int verbs_all = 0;  //总的单词数
int verbs_line = 0; //行内的单词数
%}

%%
[\t\r ]+ ;                 //忽略行空白
[A-Za-z]+    { verbs_line++; verbs_all++ ;}
\n           { printf("第 %d 行的单词数:%d\n",lineno,verbs_line); verbs_line = 0; lineno++;}

%%

main(int ac, char **av)
{
        //重新定义yyin,使其从文件输入。文件名字来源于程序运行的命令的第一个参数
        if(ac > 1 && (yyin = fopen(av[1], "r")) == NULL) {
                perror(av[1]);
                exit(1);
        }

        //解析输入内容
        if(!yylex())
                printf("文件解析结果:成功,单词总数:%d\n",verbs_all);
        else
                printf("解析失败,错误发生在第 %d 行。\n",lineno);
        
} /* main */

使用命令:
flex -ofl2.c fl2.l //翻译命令
gcc fl2.c -o fl2 -lfl //编译命令
./fl2 fl2.txt //运行结果
翻译、编译并查看运行结果。
fl2.txt问输入文件,在里面输入任意单词进行测试。测试结果为:

$ ./fl2 fl2.txt
第 1 行的单词数:4
文件解析结果:成功,单词总数:10
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics