新浪博客

Flex词法分析器学习笔记

2013-03-24 21:06阅读:

名称
flex-快速的词法分析器产生工具

概述
flex 是一个用来生成扫描器的工具,生成扫描器可以识别文本中的词汇模式。flex 从输入文件中或是从标准输入设备中(如果没给出输入文件名)读取信息来生成一个扫描器。信息以正则表达式和C 代码对的形式组成,这种形式称为规则( rule)。flex 生成C 源代码文件,lex.yy.c,其中定义了一个例程yylex()。这个文件通过编译,并用-lfl 链接生成可执行文件。当可执行文件被执行时,它分析输入中可能存在的符合正则表达的内容。当找到任何一个与正则表达式相匹配内容时,相应的
C 代码将被执行。
其对源文件的格式要求非常严格而且其查错能力非常弱。

工作原理
从文档中拷贝下来的工作原理如下:
当生成的扫描器开始运行时,它通过搜索匹配它的任何一个模式的字符串来分析输入的文件。如果找到多个匹配,那么会选取一个匹配最多文本的模式(对于上下文模式,这包括后续部分的长度,即使这会返回到输入?)。如果多个模式匹配的长度相同,那么会选择最先出现在flex 输入文件的模式。一当确实了模式,那么相对应的匹配称为token 可以从全局的字符指针yytext 获得,它的长度是全局整形变量的yyleng。接着会执行对应模式的动作,然后把再扫描剩余的文本寻找另一个匹配。如果一个匹配也没有发现,那么缺省的规则将被执行:将接下来从输入中得到的字符作为匹配的字符并拷贝到标准输出设备。所以,一个最简单的合法的flex 输入是:
%%
这个将生产一个扫描器,它只是简单的把输入的一个一个字符拷贝到输出上。注意yytext 可以用两种方法定义:作为字符指针或是字符数组。你可以通过在flex 的输入的第一段(定义段)中使用特殊的指令%pointer 或者%array 来控制flex 选择哪一种定义。缺省情况下是%pointer,除非你使用了-l lex 兼容选项,这种情况下, yytext 将是字符数组。使用%pointer 的好处在于可让扫描更快并且在扫描大的token 时不会造成缓冲溢出(除非再也没有内存可以使用了)。
不好的地方在于你控制那么能够修改yytext 的动作(action ),并且使用unput()函数来释放yytext 的内容,当在不同lex 版本间移植时,这会是很头痛的事情。使用%array 的好处是你可以尽情地修改yytext,调用unput()并不会释放yytext。还有,现在的lex 程序可能会通过如下的形式来外部使用yytext
extern char yytext[];
如果用到%pointer,那么这个声明是错误的,%array 则正确。%array yytex 定义成一个拥有YYLMAX 个字符的数组,缺省情况下,YYLMAX 是个相当大的数值。你可以在flex 输入的第一段中使用#define YYLMAX 定义成别的数据。如上面提到的一样,%pointer使yytext 动态增长以容纳下大型的token,这意味着使用%pointer 的扫描器可以扫描大型的token(如,匹配整个注释块),记得每一次扫描器都必须重置yytex 大小,还得重头扫描一遍token,所以匹配这样的token 是比较慢的。如果unput()使得太多文本被入到yytext 中,则yytext 不再自动增长,取而代之的是,产生一个run-time 错误。

源文件的格式
flex 的输入文件由三段组成,用一行中只有%%来分隔。
定义部份
%%
规则部份 
%%
用户附加C语言部份
定义部分
定义部份由C语言代码、模式的宏定义、条件模式的开始条件说明三部份组成。
其中C语言代码会被原封不动的拷贝到生成的lex.yy.c文件之中,由%{以及%}括起来。
模式的宏定义则是正则表达式的定义。从文档中摘抄的常用模式宏定义如下:
x
配置单个字母x
.
匹配除换行符’/n’之外的任意字符
[xyz]
匹配xyz
[abj-oz]
匹配abzjo之间的字母
[^A-Z]
除大写字母A-Z之外的其它字符
[^A-Z/n]
除大写字母A-Z和换行符之外的其它字符
r*
匹配0个或多个r
r+
匹配1个或多个r
r?
匹配0个或1r
规则部分
规则部份是LEX源文件的核心部份,它包括一组模式和在生成分析器识别相应模式后对相应模式进行处理的C语言动作(Action)。格式如下
C语言代码
模式1 动作1
模式2 |
模式3 动作3
同定义部分一样,C语言代码必须出现在第一个模式之前,包括在%{}%之中,且%{必须顶行书写。%{}%之间的代码部份可用来定义yylex()用到的局部变量。
模式必须顶行书写。模式可为正规式或用{}括起且在定义部份定义过的宏名。动作为用{}括起的C代码。且开始括号{与模式之间用白字符隔开,且须和模式在同一行上。注意,在模式后加一|表示模式23采用同一动作3.|和模式2以白字符隔开。
用户附加C语言部份
LEX对此部份不作任何处理,仅仅将之直接拷贝到输出文件

我的更多文章

下载客户端阅读体验更佳

APP专享