flex
是用来生成程序的工具(最初用来生成编译器),它所生成的程序能够处理结构化输入
。
基础:了解正则表达式
和编译原理
相关知识(词法分析器、语法分析器、自动机等)。
一个简单的Flex程序:
这个程序实现字数统计
功能,这个程序可以读入一个文件,然后报告这个文件的行数
、单词数
和字符数
。
$ vim WordCount.l
用vim创建文件拓展名为l
或lt
的文件,输入以下内容:
/*声明部分*/
%{
int chars = 0; //字符数
int words = 0; //单词个数
int lines = 0; //行数
%}
%%
/*规则部分*/
[a-zA-Z]+ { words++; chars += strlen(yytext); } //用于匹配单词,并作出对相应变量自增的动作
\n { chars++; lines++; } //匹配换行
. { chars++; } //匹配其它任意字符
%%
/*C代码部分*/
main(int argc, char **argv)
{
yylex(); //调用词法分析程序
printf("%8d%8d%8d\n", lines, words, chars); //打印结果
}
flex程序包含三个部分,各部分之间通过仅有%%的行来分割,三个部分介绍如下:
(1)声明部分
%{
和%}
之间的代码会被原样照抄到生成的C文件的开头部分。
在这个例子中,它只是用来设定行数、单词数和字符数的变量。
(2)规则部分
模式处在一行的开头
处,接着是模式匹配
时所需要执行的C代码
(这儿的C代码是用{}
括住的一或多行语句。)
模式必须在行首
出现。(flex认为空白开始的行都是代码)
(3)C代码部分
末尾的C代码是我们的主程序,它负责调用flex提供的词法分析例程yylex(),并输出结果。
接下来将它编译:
$ flex -o WordCount.yy.c WordCount.lt
$ cc -o WordCount WordCount.yy.c -lfl
-o
用于确定输出文件,如果不加,flex默认生成lex.yy.c
,gcc默认生成a.out
-lfl
用于链接flex库( flex library)
cc
命令其实就是gcc
,以后将全部写为gcc,可以证实如下:
$ ls -l /usr/bin/cc
lrwxrwxrwx 1 root root 3 11月 29 19:48 /usr/bin/cc -> gcc
执行的方式有许多(第一种直接输入,后两种将文件作为标准输入):
$ ./WordCount
Hello World~
Yeah
2 3 18
# 或者
$ ./WordCount < file
1 1 10
# 或者
$ cat file | ./WordCount
1 1 10
真正的wc(字符统计)程序与上述定义有所不同:没有空白字符的字符串。
所以需略作修改:
[^\t\n\r\f\v ]+ { words++; chars += strlen(yytext); }