一个扫瞄器(语法分析器)是一个文本中识别模式的程序.扫瞄器可以手写或用一个语法分析生成器根据被识别的模式描述自动生成.描述使用正则表达式.
Lex是一个由贝尔实验室的M.E.Lesk和E.Schmidt开发的词法分析自动生成器.Lex的输入是一个包含用正则表达式定义记号的文件.Lex生成一个可以被编译和链接到其它编译模版的完整的扫瞄器模块.一个Lex输入文件的形式如下:
Lex生成一个包含函数yylex()的文件,yylex()返回一个整数来指示所识别的记号.
C and scanner declarrations
%%
Token definitions and actions
%%
C subroutines
Lex文件第一段包含C声明,如包含由Yacc/Bison生成包含多字符记号定义的(simple.tab.h)文件.第一段也可以包含用正则表达式的Lex定义.在这个例子中,DIGIT被定义成一个0到9的符号而ID被定义为一个小写字母后跟0个或多个字母或数字.
%{
#include "Simple.tab.h" /*The token*/
%}
DIGIT [0-9]
ID [a-z][a-z0-9]*
%%
Token definitions and actions
%%
C subroutines
Lex文件的第二段给出每个将并识别的记号的正则表达式和其相应的行为.一个或多个数字组成的字符串被识为一个整数,并返回值INT给语法分析器.语言的保留字是小写字母串(小写可以使用但必须不同地处理).空白,制表和换行符被忽略.所有的其它单个字符符号返回其本身.(扫瞄器把所有的输入放在字符串变量yytext中)
C and scanner declarations
%%
":=" {return(ASSGNOP);}
{DIGIT}+ {return(NUMBER);}
do {return(DO); }
else {return(ELSE); }
end {return(END); }
fi {return(FI); }
if {return(IF); }
in {return(IN); }
integer {return(INTEGER);}
let {return(LET); }
read {return(READ); }
then {return(THEN); } while {return(WRITE); }
{ID} {return(IDENTIFIER);}
[ /t/n] /*Blank,tab,new line;eat up whitespace*/
. {return(yytext[0]); }
%%
C subroutines
与记号相关联的值是一个当扫瞄器一识别记号就返回给语法分析器的整数值.
Figure 3.1给出了一些可能被用于定义记号的正则表达式的形式.这里有一个全局全量yylval,它是与扫瞄器和语法分析器相关联的,用于储存记号附加信息的.
文件的第三段是在这个例子中是空,而这本可以包含一些与行为有关的C代码.
用命令lex file.lex(flex file.lex)编译Lex文件,将生成一个定义了yylex()函数的生成文件,lex.yy.c.每次引用时,函数yylex()扫瞄输入文件并返回下一个记号.
. 除换行的任何字符
x 匹配字符'x'
rs 正则表达式r后跟一个正则表达式s;称为连接
r|s 或r或s
(r) 匹配一个r;圆括符用于提供分类
r* 0或多个r,这里r是任何一个正则表达式
r+ 一个或多个r
[xyz] 一个"字符类",在这种情况下,模式识别一个x或一个y或一个z
[abj-oZ] 一个范围的"字符类",匹配一个'a',一个'b',任何由'j'到'o'的字母,或一个'Z'
{name} "name"的展开定义
/X 如果X是一个'a','b','f','n','r','t'或'v',那么ANSI-C解释为/x,就是解释为转义字符.
"[+xyz]+/"+foo" 字符常量:[xyz]"foo
Figure 3.1: Lex/Flex 正则表达式
Lex是Unix操作系统的一个工具,而FLex是一个自由软件的产品.
更多有关使用Lex/Flex的信息请参考手册lex,flex和flexdoc,或阅读论文M.E.Lesk和E.Schmidt的LEX-Lexical Analyzer Generator