Lex(Lexical Analyzar 词法分析生成器),Yacc(Yet Another Compiler Compiler编译器代码生成器)是Unix下十分重要的词法分析,语法分析的工具。经常用于语言分析,公式编译等广泛领域,详细内容可参考http://dinosaur.compilertools.net/.
先来看最简单的例子(xtgxiso.l)
%{ #include "stdio.h" %} %% [/n] ; [0-9]+ printf("Int:%s/n",yytext); . printf("Unknown:%c/n",yytext[0]); %%
执行如下命令
到此我们会对lex有个直观的用法了解 1.定义Lex描述文件 2.通过lex工具解析成lex.yy.c文件 3.使用cc编译lex.yy.c生成可执行程序
现在我们来写一个相对比较完整的例子
%{ #include "stdio.h" %} %% [/n] ; [0-9]+ printf("Int:%s/n",yytext); . printf("Unknown:%c/n",yytext[0]); %% int main() { yylex(); return 0; } int yywrap() { return 1; }
执行如下命令
这次编译没有加ll选项,那是因为加了main函数.
现在我们来大致了解lex的描述文件结构,
一般可以分为<定义部分><规则部分><用户子程序部分>。其中规则部分是必须的,定义和用户子程序部分是任选的
1:定义部分起始于 %{ 符号,终止于 %} 符号,其间可以是包括include语句、声明语句在内的C语句。这部分跟普通C程序开头没什么区别
2:规则部分起始于”%%”符号,终止于”%%”符号,其间则是词法规则。词法规则由模式和动作两部分组成。模式部分可以由任意的正则表达式组成,动作部分是由C语言语句组成,这些语句用来对所匹配的模式进行相应处理。需要注意的是,lex将识别出来的单词存放在yytext[]字符数据中,因此该数组的内容就代表了所识别出来的单词的内容.
3:用户子程序部分,可以包含用C语言编写的子程序,而这些子程序可以用在前面的动作中,这样就可以达到简化编程的目的
Lex内部变量和函数
yytext char * 当前匹配的字符串
yyleng int 当前匹配的字符串长度
yyin FILE * lex当前的解析文件,默认为标准输出
yyout FILE * lex解析后的输出文件,默认为标准输入
yylineno int 当前的行数信息
ECHO #define ECHO fwrite(yytext, yyleng, 1, yyout) 也是未匹配字符的默认动作
int yylex(void) 调用Lex进行词法分析
int yywrap(void) 在文件(或输入)的末尾调用。如果函数的返回值是1,就停止解析
Lex其实就是词法分析器,通过配置文件*.l,依据正则表达式逐字符去顺序解析文件,并动态更新内存的数据解析状态。不过Lex只有状态和状态转换能力。因为它没有堆栈,它不适合用于剖析外壳结构。而yacc增加了一个堆栈,并且能够轻易处理像括号这样的结构。Lex善长于模式匹配,如果有更多的运算要求就需要yacc了.