lex是构建词法分析程序的工具,词法分析程序把随机输入流标记化(tokenize),即,将它拆分成词法标记。当编写lex规范时,可以创建lex匹配输入所用的一套规则。每次匹配一个模式时,lex程序就调用你提供的C代码来处理被匹配的文本。lex程序把lex规范转化为包含C例程yylex()的文件,程序可以调用yylex()来运行词法分析程序。
lex规范
lex规范由三部分组成:定义段、规则段和用户子例程段。
定义段:处理lex用在词法分析程序中的选项,并且一般建立词法分析程序运行的执行环节。由"%{"和“%}”扩住的部分是C代码,它们将被逐字地拷贝到词法分析程序中。这些C代码一开始即被放入输出代码中,所以这里包含的定义部分可以由规则段中的代码引用。lex提供了一种简单的替换机制,使定义长的或复杂的模式变得容易。
%%
规则段:每个规则都由两个部分组成-模式和动作,由空白分开。模式是UNIX样式的正则表达式,即由工具(例如grep、sed和ed)使用的相同表达式的扩展版本。lex的多数版本将模式后的所有语句当做一个动作,而另一些版本只读取行的第一条语句并且默默地忽略其他的语句。如果动作包含多条语句或多个行,为了安全起见通常使用大括号。
%%
用户子例程段:包含任何有效的C代码,被逐字拷贝到生成的词法分析程序中。
Lex函数
yylex:这个函数开始分析工作,它由lex自动生成
yywrap:这个函数在文件(或输入)的末尾调用,如果函数的返回值是1,就停止解析。因此它可以用来解析多个文件,代码可以写在第三段,这样就能够解析多个文件。方法是使用yyin文件指针,指向不同的文件,直到所有的文件都被解析。最后,yywrap可以返回1来表示解析的结束
yyless:这一函数可以用来送回除了前n个字符外的所有读出标记
yymore:这一函数告诉lexer将下一个标记附加到当前标记后
lex生成的扫描器在成功识别模式后,通过lex变量存储该模式对应的值,并将其返回给上层调用者
yyin:FILE类型,指向lexer正在解析的当前文件
yyout:FILE类型,指向记录lexer输出的位置,缺省情况下,yyin和yyout都指向标准输入和输出
yytext:匹配模式的文本存储在这一变量中(字符串类型)
yyleng:给出匹配模式的长度
yylineno:提供当前的行数信息(某些lex的实现不支持)
示例
单词计数示例的定义段如下:
%{
unsigned charCount = 0, wordCount = 0, lineCount = 0;
%}word [^ \t\n]+
eol \n
单词计数示例的规则段如下:
%%
{word} {wordCount++; charCount+=yyleng;}
{eol} {charCount++; lineCount++;}
. charCount++;
yyleng是lex的内部变量,表示词法分析程序识别的字符串长度。
单词计数示例的用户子例程段:
main()
{yylex();printf("%d %d %d\n", lineCount, wordCount, charCount);
}