词法分析(Lexical Analysis)
词法分析器在英文中一般叫做 Tokenizer。
有一个计算模型,叫做有限自动机(Finite-state Automaton,FSA),或者叫做有限状态自动机(Finite-state Machine,FSM)。
状态机能够区分标识符和数字字面量
正则表达式也可以用来描述词法规则。这种描述方法,我们叫做正则文法(Regular Grammar)。
IntLiteral : [0-9]+; //至少有一个数字
Id : [A-Za-z][A-Za-z0-9]*; //以字母开头,后面可以是字符或数字
词法分析器要用到很多个词法规则,每个词法规则都采用“Token 类型: 正则表达式”这样一种格式,用于匹配一种 Token
词法规则里面要有优先级,比如排在前面的词法规则优先级更高
手写词法分析器的步骤太繁琐了,我们能否只写出词法规则,就自动生成相对应的有限自动机呢?当然是可以的,实际上,正则表达式工具就是这么做的。此外,词法分析器生成工具 lex(及 GNU 版本的 flex)也能够基于规则自动生成词法分析器。具体实现思路是这样的:把一个正则表达式翻译成 NFA,然后把 NFA 转换成 DFA。
DFA,它是“Deterministic Finite Automaton”的缩写,即确定的有限自动机。它的特点是:该状态机在任何一个状态,基于输入的字符,都能做一个确定的状态转换。
NFA,它是“Nondeterministic Finite Automaton”的缩写,即不确定的有限自动机。它的特点是:该状态机中存在某些状态,针对某些输入,不能做一个确定的转换。
NFA,这又细分成两种情况:对于一个输入,它有两个状态可以转换。存在ε转换的情况,也就是没有任何字符输入的情况下,NFA 也可以从一个状态迁移到另一个状态。
所有的正则表达式都能转换成 NFA 或 DFA;而所有的 NFA 或 DFA,也都能转换成正则表达式。
识别 s* 的 NFA
基于 NFA,仍然可以实现一个词法分析器,只不过算法会跟基于 DFA 的不同:当某个状态存在一条以上的转换路径的时候,要先尝试其中的一条;如果匹配不上,再退回来,尝试其他路径。这种试探不成功再退回来的过程,叫做回溯(Backtracking)。
解析 int 关键字、标识符和数字字面量的过程:
NFA 的运行可能导致大量的回溯,那么能否将 NFA 转换成 DFA,这个算法就是子集构造法。
只要有了准确的正则表达式,是可以根据算法自动生成对字符串进行匹配的程序的,这就是正则表达式工具的基本原理,也是有些工具(比如 ANTLR 和 flex)能够自动给你生成一个词法分析器的原理。