LEX简介
LEX是LEXical compiler 的缩写,是UNIX环境下非常著名的工具软件,其主要功能是根据LEX源程序生成一个用C语言描述的词法分析程序(scanner)。
LEX源程序是词法分析程序的规格说明文件,文件名约定为lex.l,经过LEX编译程序的编译,生成一个C语言程序lex.yy.c。若用C语言作为编译程序的实现语言,则lex.yy.c可以和其他源文件一起编译,生成编译程序的目标程序。若用C语言编译程序对lex.yy.c进行单独编译,可生成目标文件lex.yy.o,或直接生成可执行程序a.out。目标文件lex.yy.o作为编译程序目标代码的组成部分,可以和其他高级语言或汇编语言产生的目标代码连接。词法分析程序a.out运行时,可以将输入的字符串转换成相应的记号序列。
下图展示了LEX生成词法分析程序的流程:
LEX源程序的结构
LEX程序的组成部分:
- 声明
声明部分包括变量的声明,符号常量的声明和正则表达式定义。
正规定义中定义的名字可以出现在翻译规则的正规表达式中。
希望出现在lex,yy.c中的C语言声明语句用符号"%{"和“%}”括起来,如
%{#include<stdio.h>#include<stdlib.h>#include<string.h>#include<ctype.h>#include"y.tab.h"typedef char * YYSTYPEchar * yylval
%}
下面是关于名字delim,ws,letter, digit以及标识符 id的正规定义,这些名字都可以在翻译规则部分的正规表达式中出现。
dilim [\t\n]
ws {dilim}+
letter [A-Za-z]
digit [0-9]
id {letter}({letter}|{digit})*
- 翻译规则
翻译规则部分是由正规表达式和相应的动作组成的具有如下形式的语句序列:
p1 {action 1}
p2 {action 2}
p3 {action 3}
p4 {action 4}
其中pi是正规表达式,描述一种记号的模式;动作i是用C语言描述的程序段,表示当一个符号匹配模式pi时,词法分析程序应该做得动作
关于LEX源程序中的正规表达式的使用,参考python中的re模块不难理解
这里应该注意LEX解决冲突的两点策略:
- 根据规则定义的先后顺序进行匹配
解决了例子中关键字和标识符的冲突 - 最长匹配原则
解决了例子中诸如"<"和“<=”的冲突
也就是说,词法分析程序依此尝试每一条规则,尽可能地匹配最长的输入符号串,并且排在前面的规则的优先级高于排在后面的规则的优先级。如果有一些内容不匹配任何规则,LEX将其拷贝到标准输出。
- 辅助过程
对翻译规则的补充。翻译规则部分中某些动作需要调用的 过程或函数,如果不是C语言的库函数,则要在此给出具体的定义。这些过程或函数也可以在另一个程序文件中定义,然后和词法分析程序链接在一起即可。
各个部分由“%%”隔开