词法分析
lexical analysis,是计算机科学中将字符序列转换为单词(Token)序列的过程。
进行词法分析的程序或者函数叫作词法分析器(Lexical analyzer,简称Lexer),也叫扫描器(Scanner)。
词法分析器供语法分析器调用。
词法分析阶段是编译过程的第一个阶段,是编译的基础。
这个阶段的任务是从左到右一个字符一个字符地读入源程序,即对构成源程序的字符流进行扫描然后根据构词规则识别单词(也称单词符号或符号)。
词法分析程序可以使用Lex等工具自动生成。
编译程序把一个源程序翻译成目标程序的工作过程分为五个阶段:词法分析;语法分析;语义检查和中间代码生成;代码优化;目标代码生成。
从输入字符流中生成单词的过程叫作单词化(Tokenization),在这个过程中,词法分析器还会对单词进行分类。
词法分析器通常不会关心单词之间的关系(属于语法分析的范畴),例如,词法分析器能够将括号识别为单词,但并不保证括号是否匹配。
单词经常使用正则表达式进行定义,像lex一类的词法分析器生成器就支持使用正则表达式。
词法分析的第一阶段即扫描器,通常基于有限状态自动机。
开发一个词法分析器是在词法定义的基础上的,词法定义需要使用正则表达式
正则表达式可以转换为NFA(Non-determinate finite automata 不确定的有穷自动机)
NFA可以转换为DFA(determinate finite automata确定的有穷自动机)
DFA可以极小化,进而使用为开发词法分析器的工具
DFA的正式定义
一个DFA定义了一个字符串集合
每个字符串是一个字符的序列,字符属于∑
起始状态给出生成字符串的起始点
终端状态给出了终点
转换函数制定了生成字符串的规则
Lex 基本
Lex编译器将输入的模式转换成一个状态转换图,并生成相应的实现代码,并存放到文件lex.yy.c中。
Lex 的常规表达式
常规表达式是一种使用元语言的模式描述。表达式由符号组成。符号一般是字符和数字,但是 Lex 中还有一些具有特殊含义的其他标记。 下面两个表格定义了 Lex 中使用的一些标记并给出了几个典型的例子。
用 Lex 定义常规表达式
字符 含义
A-Z, 0-9, a-z 构成了部分模式的字符和数字。
. 匹配任意字符,除了 \n。
- 用来指定范围。例如:A-Z 指从 A 到 Z 之间的所有字符。
[ ] 一个字符集合。匹配括号内的 任意 字符。如果第一个字符是 ^ 那么它表示否定模式。例如: [abC] 匹配 a, b, 和 C中的任何一个。
* 匹配 0个或者多个上述的模式。
+ 匹配 1个或者多个上述模式。
? 匹配 0个或1个上述模式。
$ 作为模式的最后一个字符匹配一行的结尾。
{ } 指出一个模式可能出现的次数。 例如: A{1,3} 表示 A 可能出现1次或3次。
\ 用来转义元字符。同样用来覆盖字符在此表中定义的特殊意义,只取字符的本意。
^ 否定。
| 表达式间的逻辑或。
"<一些符号>" 字符的字面含义。元字符具有。
/ 向前匹配。如果在匹配的模版中的“/”后跟有后续表达式,只匹配模版中“/”前 面的部分。如:如果输入 A01,那么在模版 A0/1 中的 A0 是匹配的。
( ) 将一系列常规表达式分组。
常规表达式举例
常规表达式 含义
joke[rs] 匹配 jokes 或 joker。
A{1,2}shis+ 匹配 AAshis, Ashis, AAshi, Ashi。
(A[b-e])+ 匹配在 A 出现位置后跟随的从 b 到 e 的所有字符中的 0 个或 1个。