词法分析
编译器中唯一与源程序打交道的部分;规定所有合法输入+识别合法输入
任务:
- 滤掉源程序中的无用成分,如注释、空格、回车等
- 处理与具体平台有关的输入,如文件结束符的不同表示等
- 根据模式识别记号,并交给语法分析器【主要任务】
- 调用符号表管理器或出错处理器,进行相关处理
工作方式:
- 单独一遍扫描,输出记号流
- 作为语法分析器的子程序,通过词法分析器的调用,然后返回记号
- 与语法分析器并行工作的模式,以生产/消费的形式并行工作,通过队列存放已生产的“记号”
词法
词法的双重含义:
- 规定单词形成的规则,也被称为构词规则或词法规则
- 作用相当于立法,规定什么样的输入序列是语言所允许的合法单词
- 根据构词规则识别输入序列,也被称为词法序列
- 作用相当于执法,根据规则识别出合法的单词和指出非法的输入序列
模式pattern:
- 产生和识别元素的规则
记号token:
- 按照某个模式(或规则)识别出的元素(一组),包含记号的类别和记号的值
单词lexeme:
- 被识别出的元素自身的值(一个),也称为词值
字典:
- 预先定义且内容不变的记号表
基本分类
- 关键字/保留字kw(key word/reserved word)
- 标识符id(identifier)
- 字面量literal
- 常数字面量
- 整型、实型、枚举
- 字符串字面量
- 常数字面量
- 特殊符号ks(key symbol/special symbol)
- 运算符
- 分隔符,例如
"
,'
模式的形式化描述
语言L是有限字母表∑上有限长度字符串的集合
字符串
基本概念:
表示/术语 | 意义 |
---|---|
$\ | S\ |
ε ε ε | $\ |
S1S2 | 字符串的连接 |
S n S^n Sn | 连续n个S的连接 |
S的前缀X | “abc”的前缀可以是: ε , a , a b , a b c ε, a, ab, abc ε,a,ab,abc |
S的后缀X | “abc”的后缀可以是: ε , c , b c , a b c ε, c, bc, abc ε,c,bc,abc |
S的子串X | “abc”的子串可以是: ε , a , b , c , … ε, a, b, c, … ε,a,b,c,… |
S的真前缀 | X是S的前缀,并且具有性质:$X!=S\ and\ \ |
S的真后缀 | X是S的后缀,并且具有性质:$X!=S\ and\ \ |
S的真子串 | X是S的真子串,并且具有性质:$X!=S\ and\ \ |
S的子序列X | S中去掉0或若干个不一定连续的字符后形成的字符串 |
集合操作:
表示、术语 | 意义 |
---|---|
ϕ \phi ϕ | 空集合,即元素个数为0的集合 |
{ ε } \{ε\} {ε} | 空串作为唯一元素的集合 |
X = L ∪ M X=L∪M X=L∪M | X是集合L和M的并: $X={s\ |
X = L ∩ M X=L∩M X=L∩M | X是集合L和M的交: $X={s\ |
X = L M X=LM X=LM | X是集合L和M的连接: $X={st\ |
X = L − M X=L-M X=L−M | X是集合L和M的差: $X={s\ |
X = L ∗ X=L^* X=L∗ | X是集合L和M的(星)闭包: X = L 0 ∪ L 1 ∪ L 2 ∪ … X=L^0∪L^1∪L^2∪… X=L0∪L1∪L2∪…,其中 L 0 = { ε } L^0=\{ε\} L0={ε} |
X = L + X=L^+ X=L+ | X是集合L和M的正闭包: X = L 1 ∪ L 2 ∪ L 3 ∪ … X=L^1∪L^2∪L^3∪… X=L1∪L2∪L3∪… |
正规式
记 号 = 正 规 式 记号=正规式 记号=正规式,读作:记号定义为正规式或者记号是正规式
令Σ是一个有限字母表,则Σ上的正规式及其表示的集合递归定义如下:
- ε是正规式,它表示集合 L ( ε ) = ε L(ε)={ε} L(ε)=ε
- 若a是Σ上的字符,则a是正规式,它表示集合L(a)= a {a} a
- 若正规式r和s分别表示集合L®和L(s),则
(a) r ∣ s r|s r∣s是正规式,表示集合 L ( r ) ∪ L ( s ) L(r)∪L(s) L(r)∪L(s)
(b) r s rs rs是正规式,表示集合 L ( r ) L ( s ) L(r)L(s) L(r)L(s)
(c) r ∗ r^* r∗是正规式,表示集合 ( L ( r ) ) ∗ (L(r))^* (L(r))∗,
(d) ( r ) (r) (r)是正规式,表示的集合仍然是 L ( r ) L(r) L(r)【加括弧改变优先级、结合性】
可用正规式描述的语言称为正规语言或正规集
优先级
- (从高到低顺序排列为)闭包运算、连接运算、或运算
结合性
- 三种运算均具有左结合性质
正规集是一个集合,而正规式是表示正规集的一种方法
-
不同正规式也可以表示同一个正规集,即正规式与正规集之间是多对一的关系
-
若正规式P和Q表示了同一个正规集,则称P和Q是等价的,记为P=Q
代数性质:
r ∥ s = s ∥ r r \| s=s \| r r∥s=s∥r | ( r s ) t = r ( s t ) (rs)t=r(st) (rs)t=r(st) |
---|---|
r ∥ ( s ∥ t ) = ( r ∥ s ) ∥ t r \| (s \| t)=(r \| s) \| t r∥(s∥t)=(r∥s)∥t | ε r = r ε = r εr=rε=r εr=rε=r |
r ( s ∥ t ) = r s ∥ r t r(s \| t)=rs \| rt r(s∥t)=rs∥rt | r ∗ = ( r + ∥ ε ) r^*=(r^+ \| ε) r∗=(r+∥ε) |
( s ∥ t ) r = s r ∥ t r (s \| t)r=sr \| tr (s∥t)r=sr∥tr | r ∗ ∗ = r ∗ r^{**}=r^* r∗∗=r∗ |
其它:
- 可缺省, r ? = r ∣ ε r?=r|ε r?=r∣ε,因为ε不可以用键盘直接键入,?与*具有相同的运算优先级
- 字符组[r],有两种形式
- 枚举,如 [ a b c ] = a ∣ b ∣ c [abc]=a|b|c [abc]=a∣b∣c
- 分段,如 [ 0 − 9 a − z ] [0-9a-z] [0−9a−z],注意左边界小于右边界
- 非字符组 [ [ [^ r ] = ∑ − L ( r ) r]=\sum-L(r) r]=∑−L(r)
- 串,”r”,用来避免与正规式中运算符的冲突
- 辅助定义式:名字=正规式,是为复杂的或重复出现的正规式命名,并在以后的使用中用名字代替正规式
char = [a-zA-Z]
digit =[0-9]
digits =$digit^+$
optional_fraction =(.digits)?
optional_exponent =(E(+|-)?digits)?
id =char(char|digit)*
num =digits optional_fraction optional_exponent
有限自动机
所谓有限,是指自动机的状态数是有限的
NFA
- NFA: Nondeterministic Finite Automaton不确定的有限自动机
NFA是一个五元组(5-tuple):M =(S,∑,move, s 0 s_0 s0,F),其中
- (1) S是有限个状态(state)的集合;
- (2) ∑是有限个输入字符(包括ε)的集合;
- (3) move是一个状态转移函数,move( s i s_i si,ch)= s j s_j sj表示,当前状态 s i s_i si下若遇到输入字符ch,则转移到状态 s j s_j sj;
- (4) s 0 s_0 s0是唯一的初态(也称开始状态);
- (5) F是终态集(也称接受状态集),它是S的子集,包含了所有的终态
表示方式
状态转换图
用一个有向图来直观表示NFA
- NFA中的每个状态,对应转换图中的一个节点
- NFA中的每个
move(si, a)=sj
,对应转换图中的一条有向边 - 需满足最长匹配原则
初态:除去环后没有前驱的节点
状态转换矩阵
用一个矩阵来直观表示NFA
-
矩阵中,状态对应行,字符对应列
-
一般矩阵第一行所对应的状态为初态,而终态需要特别指出
识别记号的特点
具有不确定性,即在当前状态下对同一字符有多于一个的下一状态转移
具体体现:
- (定义)move函数是1对多的
- (状态转移图)同一状态有多于一条边标记相同字符转移到不同的状态
- (状态转移矩阵)M[si, a]是一个状态的集合
方法与问题
方法:反复试探所有路径,直到到达终态,或者到达不了终态
问题:
- 只有尝试了全部可能的路径,才能确定一个输入序列不被接受,而这些路径的条数随着路径长度的增长成指数增长
- 识别过程中需要大量回溯,时间复杂度升高且算法趋于复杂
DFA
- DFA: Deterministic Finite Automaton确定的有限自动机
DFA是NFA的一个特例,其中:
-
(1)没有状态具有ε状态转移(ε_transition),即状态转换图中没有标记ε的边;
-
(2)对每个状态s和每个字符a,最多有一个下一状态。
识别记号的特点
具有确定性
- 即在当前状态下对同一字符最多只有一个的下一状态转移
具体体现:
- (定义)move函数是1对1的
- (状态转移图)从一个节点出发的边上标记均不相同
- (状态转移矩阵)M[si, a]是一个状态
- 且字母表不包括 ε \varepsilon ε
将在DFA上识别输入序列的过程形式化为算法,该算法被称为模拟器(模拟DFA的行为)或驱动器(用DFA的数据驱动分析动作);
算法与DFA一起,即构成识别记号的词法分析器的核心。它的最大特点是算法与模式无关,仅DFA与模式相关。
有限自动机的等价
若有限自动机M和M’识别同一正规集,则称M和M’是等价的,记为M=M’。
模拟DFA
s:=s0; ch:=nextchar; -- 初值
while ch≠eof -- 循环
loop s:=move(s,ch);
ch:=nextchar;
end loop;
if s is in F then return “yes”; -- 返回
else return “no”;
end if;
NFA与DFA
NFA:与正规式有对应关系,易于构造,状态数少
DFA:确定性便于记号识别,不易构造,状态数可能多
对于任何一个NFA,均可以找到一个与它等价的DFA