参考《龙书》
需要识别的程序语言单词的分类:
关键字 (保留字或基本字):if, else…标识符字面常数运算符分界符:,, :, ;…词法分析器的接口设计
词法分析可作为单独一遍来实现 (多遍编译程序) 简化设计;改进编译效率 (词法分析只需要分析3型文法,而语法分析分析的是上下文无关文法);增加编译系统的可移植性 词法分析程序作为语法分析程序的子程序 (单遍编译程序) 每当语法分析需要一个新的单词符号时,就调用词法分析子程序,词法分析子程序从字符串源程序中识别出一个具有独立意义的单词,将其单词符号返给语法分析区分关键字和标识符
关键字通常也满足标识符的组成规则,因此可以将关键字作为保留字。只有当一个字符串不是关键字时它才能组成一个标识符具体实现方法:用符号表保存字符串 (关键字和已经识别出的标识符)
单一表示。一个字符串表可以将编译器的其余部分和表中字符串的具体表示隔离开,编译器后面的步骤可以只使用指向表中字符串的指针或引用保留字。要实现保留字,可以在初始化时在字符串表中加入保留的字符串以及它们对应的词法单元。当词法分析器读到一个可以组成标识符的字符串或词素时,它首先检查这个字符串表中是否有这个词素。如是,它就返回表中的词法单元,否则返回带有终结符号 i d id id 的词法单元;如果不存在对应的条目,那么由 i d id id 和属性值 s s s (词素) 组成的词法单元将被加入到字符串表中,并被返回下面是正规式和它所表示的正规集的递归定义:
设字母表为 ∑ \sum ∑,辅助字母表 ∑ ′ = { ∅ , ε , ∣ , • , ∗ , ( , ) } \sum'=\{\varnothing, ε,|,•,*,(,)\} ∑′={∅,ε,∣,•,∗,(,)} ε ε ε 和 ∅ \varnothing ∅ 都是 ∑ \sum ∑ 上的正规式,它们所表示的正规集分别为 { ε } \{ε\} {ε} 和 { } \{\ \} { }任何 a ∈ ∑ a\in \sum a∈∑, a a a 是 ∑ \sum ∑ 上的一个正规式,它所表示的正规集为 { a } \{a\} {a}假定 e 1 e_1 e1 和 e 2 e_2 e2 都是 ∑ \sum ∑ 上的正规式,它们所表示的正规集分别为 L ( e 1 ) L(e_1) L(e1) 和 L ( e 2 ) L(e_2) L(e2),那么, ( e 1 ) , e 1 ∣ e 2 , e 1 • e 2 , e 1 ∗ (e_1), e_1|e_2,e_1•e_2, e_1^* (e1),e1∣e2,e1•e2,e1∗ 也都是正规式,它们所表示的正规集分别为 L ( e 1 ) , L ( e 1 ) ∪ L ( e 2 ) , L ( e 1 ) L ( e 2 ) , ( L ( e 1 ) ) ∗ L(e_1), L(e_1)\cup L(e_2), L(e_1)L(e_2),(L(e_1))^* L(e1),L(e1)∪L(e2),L(e1)L(e2),(L(e1))∗仅由有限次使用上述三步骤而定义的表达式才是 ∑ \sum ∑ 上的正规式,仅由这些正规式所表示的集合才是 ∑ \sum ∑ 上的正规集其中: ∣ | ∣ 读为“或”(也有使用 + + + 代替 ∣ | ∣ 的) • • • 读为“连接”,一般可省略不写 ∗ * ∗ 读为“闭包”(即,任意有限次的自重复连接) 优先顺序: ∗ * ∗、 • • •、 ∣ | ∣
例
设 ∑ = { a , b } \sum=\{a, b\} ∑={a,b}, ∑ \sum ∑ 上的正规式和相应的正规集的例子有: 正规式正规集 a a a { a } \{a\} {a} a a a | b b b { a , b } \{a,b\} {a,b} a b ab ab { a b } \{ ab\} {ab} a ∗ a^* a∗ { ε , a , a a , . . . } \{ε,a,aa,... \} {ε,a,aa,...} ( a (a (a| b ) ( a b)(a b)(a| b ) b) b) { a a , a b , b a , b b } \{ aa,ab,ba,bb\} {aa,ab,ba,bb} ( a (a (a| b ) ∗ b)^* b)∗ { a , b } \{ a,b\} {a,b}上的任意串 ( a (a (a| b ) ∗ b)^* b)∗ ( a a (aa (aa| b b b ) ( a bbb)(a bbb)(a| b ) ∗ b)^* b)∗ ∑ ∗ \sum^* ∑∗上所有含有两个相继的 a a a 或三个连续的 b b b 的 a 、 b a、b a、b 串 ( a (a (a| b ) ∗ a b b b)^*abb b)∗abb以 a b b abb abb 结尾的 a 、 b a、b a、b 串例
∑ = { l , d } \sum=\{l,d\} ∑={l,d}, l l l 代表字母, d d d 代表数字。正规式 r = l ( l ∣ d ) ∗ r=l(l |d)^* r=l(l∣d)∗ 表示标识符例
∑ = { d , . , e , + , − } \sum=\{d,.,e,+,-\} ∑={d,.,e,+,−}, d d d 表示 0 0 0 ~ 9 9 9 的数字。正规式 d ∗ ( . d d ∗ ∣ ε ) ( e ( + ∣ − ∣ ε ) d d ∗ ∣ ε ) d^*(.dd^*|ε)(e(+|-|ε)dd^*|ε) d∗(.dd∗∣ε)(e(+∣−∣ε)dd∗∣ε) 表示无符号整数 例如: 3.6 e 2 , 471.88 e − 1 3.6e2,\ \ \ 471.88e-1 3.6e2, 471.88e−1设 r , s , t r,s,t r,s,t 为正规式,正规式服从的代数规律有:
r ∣ s = s ∣ r r|s=s|r r∣s=s∣r 交换律 r ∣ ( s ∣ t ) = ( r ∣ s ) ∣ t r|(s|t)=(r|s)|t r∣(s∣t)=(r∣s)∣t 结合律 ( r s ) t = r ( s t ) (rs)t=r(st) (rs)t=r(st) 结合律 r ( s ∣ t ) = r s ∣ r t r(s|t)=rs|rt r(s∣t)=rs∣rt 分配律 ( 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 ∣ r = r r|r=r r∣r=r ”或“的抽取律 r ∗ = ε ∣ r ∣ r r ∣ … r^*=ε|r|rr|… r∗=ε∣r∣rr∣…正规文法 即 3型文法 / 右线性文法
正则式(正规式)与正则文法的等价性,即 正则语言可以由正则式定义,也可以由正则文法定义
对任一正则文法,存在一个定义同一个语言的正则式对每个正则式,存在一个生成同一语言的正则文法例
求下列正则文法对应的正则式 G [ S ] : S → a S ∣ a B ① B → b C ② C → a C ∣ a ③ \begin{aligned} G[S]:S →aS | aB \ \ \ \ \ ① \\B→bC \ \ \ \ \ ② \\C→aC | a \ \ \ \ \ ③\end{aligned} G[S]:S→aS∣aB ①B→bC ②C→aC∣a ③解
从活符号 C C C 开始 由 ③ 得 C = a ∗ a 代 入 ② 得 B = b a ∗ a 代 入 ① 得 S → a S ∣ a b a ∗ a ∴ S = a ∗ a b a ∗ a \begin{aligned} 由③得\ \ \ \ \ C&=a^*a\\ 代入②得\ \ \ \ \ B&=ba^*a\\ 代入①得\ \ \ \ \ S&→aS|aba^*a\\ \therefore\ \ \ \ \ S&=a^*aba^*a\end{aligned} 由③得 C代入②得 B代入①得 S∴ S=a∗a=ba∗a→aS∣aba∗a=a∗aba∗a例
求下列正则文法对应的正则式 G [ S ] : S → b S ∣ a A ① A → a A ∣ b B ② B → a A ∣ b C ③ C → b S ∣ a A ∣ ε ④ \begin{aligned}G[S]: S&→bS|aA①\\ A&→aA|bB②\\ B&→aA|bC③\\ C&→bS|aA |ε④\end{aligned} G[S]:SABC→bS∣aA①→aA∣bB②→aA∣bC③→bS∣aA∣ε④解
由 ① 、 ④ ①、 ④ ①、④, C → S ∣ ε C →S | ε C→S∣ε 所以 B → a A ∣ b S ∣ b , B = S ∣ b B→aA|bS|b,B=S|b B→aA∣bS∣b,B=S∣b 所以 A = a A ∣ b ( S ∣ b ) = a A ∣ b S ∣ b b , A = S ∣ b b A=aA|b(S|b)=aA|bS|bb, A=S|bb A=aA∣b(S∣b)=aA∣bS∣bb,A=S∣bb 所以 S = b S ∣ a ( S ∣ b b ) = ( a ∣ b ) S ∣ a b b S=bS|a(S|bb)=(a|b)S|abb S=bS∣a(S∣bb)=(a∣b)S∣abb 因此 S = ( a ∣ b ) ∗ a b b S=(a|b)^*abb S=(a∣b)∗abb 即:以 a b b abb abb 结尾的 a 、 b a、b a、b 串例
将 R = a ( a ∣ b ) ∗ R=a(a|b)^* R=a(a∣b)∗ 转换为正规文法解 G [ S ] : S → a A A → a A ∣ b A ∣ ε \begin{aligned} G[S]:S&→aA\\ A&→aA|bA| ε\end{aligned} G[S]:SA→aA→aA∣bA∣ε
例
将 R = ( a ∣ c ∣ b a ∣ b c ) ∗ ( b ∣ ε ) R=(a|c|ba|bc)^*(b|ε) R=(a∣c∣ba∣bc)∗(b∣ε) 转换为正规文法解
令 α = a ∣ c ∣ b a ∣ b c α=a|c|ba|bc α=a∣c∣ba∣bc G [ S ] : S → α S ∣ b ∣ ε 即 : S → a S ∣ c S ∣ b a S ∣ b c S ∣ b ∣ ε G[S]:S→αS|b| ε\\ 即: S→aS|cS|baS|bcS|b|ε G[S]:S→αS∣b∣ε即:S→aS∣cS∣baS∣bcS∣b∣ε进一步转化为严格意义的正则文法: S → a S ∣ c S ∣ b A ∣ b B ∣ b ∣ ε A → a S B → c S S→aS|cS|bA|bB|b|ε\\ A→aS\\ B→cS S→aS∣cS∣bA∣bB∣b∣εA→aSB→cS若 F A FA FA 处于状态 q i q_i qi,正在读字符 a a a,而状态应转换为 q j q_j qj ,则
状态转换函数 f : f ( q i , a ) = q j f:f (q_i, a) = q_j f:f(qi,a)=qj状态装换图,节点代表状态,弧代表转换,弧上符号代表输入字符 状态转换矩阵 M : M [ q i , a ] = q j M:M [q_i, a] = q_j M:M[qi,a]=qj例
给出识别语言 { 以 i 为 首 的 i , d 串 } \{以i为首的i,d串\} {以i为首的i,d串} 的 F A FA FA 的三种形式解
状态转换矩阵中,列 F F F 代表终止状态标记,对应行标记 1 表示该状态为终止状态
例 例
构造一个 D F A DFA DFA,它识别的语言为 { x ∣ x ∈ { 0 , 1 } ∗ , 且 当 把 x 看 成 二 进 制 数 时 , x M O D 3 = 0 } \{x | x \in\{0,1\}^*,且当把 x 看成二进制数时,x\ MOD\ 3=0\} {x∣x∈{0,1}∗,且当把x看成二进制数时,x MOD 3=0}( x x x 模3与0同余)解
定义下列状态: q 0 , q 1 , q 2 q_0,q_1,q_2 q0,q1,q2:分别对应除以 3 余数为 0,1,2 的 x x x 组成的等价类 q s q_s qs: F A FA FA 的开始状态 q s q_s qs 状态下读入0时,有 x = 0 x=0 x=0,应进入状态 q 0 q_0 q0;读入1时,有 x = 1 x=1 x=1,应进入状态 q 1 q_1 q1; q 1 q_1 q1状态下有 x = 3 n + 1 x=3n+1 x=3n+1。读入0时, x ′ = 2 × ( 3 n + 1 ) = 6 n + 2 x'=2\times(3n+1)=6n+2 x′=2×(3n+1)=6n+2。所以, δ ( q 1 , 0 ) = q 2 δ(q_1,0)=q_2 δ(q1,0)=q2;读入1时, x ′ = 2 × ( 3 n + 1 ) + 1 = 6 n + 3 x'=2\times(3n+1)+1=6n+3 x′=2×(3n+1)+1=6n+3。所以, δ ( q 1 , 1 ) = q 0 δ(q_1,1)=q_0 δ(q1,1)=q0…依次分析可以画出下面的 D F A DFA DFA:确定的有穷自动机 D F A DFA DFA (deterministic finite automata)
D F A DFA DFA 是一个五元组: M = ( K , Σ , f , S , Z ) M=(K,Σ,f,S,Z) M=(K,Σ,f,S,Z)
K K K:状态的有穷非空集 (对应文法中的 V N V_N VN) Σ Σ Σ:有穷输入字母表 (对应文法中的 V T V_T VT) f f f: K × Σ K× Σ K×Σ 到 K K K 的一个映射(是单值函数) (对应文法中的 P P P) S ∈ K S∈K S∈K 是开始状态 (对应文法中的 S S S) Z ⊆ K Z\subseteq K Z⊆K 是终止状态集不确定的有穷自动机 N F A NFA NFA (nondeterministic finite automata)
N F A NFA NFA 是一个五元组: M = ( K , Σ , f , S , Z ) M=(K,Σ,f,S,Z) M=(K,Σ,f,S,Z)
K K K:状态的有穷非空集 (对应文法中的 V N V_N VN) Σ Σ Σ:有穷输入字母表 (对应文法中的 V T V_T VT) f f f: K × Σ K× Σ K×Σ 到 K K K 的子集 (在离散数学中表示为 2 K 2^K 2K) 的一个映射 (对应文法中的 P P P) S ⊆ K S\subseteq K S⊆K 是开始状态集 (对应文法中的 S S S) Z ⊆ K Z\subseteq K Z⊆K 是终止状态集特别地,对于带空转换的 N F A NFA NFA:
f f f: K × ( Σ ∪ { ε } ) K×( Σ\ \cup\ \{ε\}) K×(Σ ∪ {ε}) 到 K K K 的子集的一个映射注意: f , S f,S f,S 与 D F A DFA DFA 不同
D F A DFA DFA 与 N F A NFA NFA 的两点区别
N F A NFA NFA 可以有多个开始状态 N F A NFA NFA 的映射函数值可是多个状态或空集 ( 1 → 多 或 1 → 空 1→多\ 或\ 1→空 1→多 或 1→空) ( N F A NFA NFA 在任意时刻可以处于有穷多个状态)例
构造一个 D F A DFA DFA,识别语言 { x 000 y ∣ x , y ∈ { 0 , 1 } ∗ } \{x000y | x,y \in\{0,1\}^*\} {x000y∣x,y∈{0,1}∗}解
该语言定义的句子都会有三个连续的 0该语言的正则表达式为 ( 0 ∣ 1 ) ∗ 000 ( 0 ∣ 1 ) ∗ (0|1)^*000(0|1)^* (0∣1)∗000(0∣1)∗。可以看出, N F A NFA NFA 与正则表达式天然同构
例
识别实常数解
以 d d d 代表数字, D F A DFA DFA 如图:例
构造一个 D F A DFA DFA,识别语言 { 0 n 1 m ∣ n , m ≥ 0 } \{0^n1^m | n,m\geq0\} {0n1m∣n,m≥0}解 例
构造 N F A NFA NFA,识别语言 { x ∣ x 为 非 负 偶 整 数 , 不 允 许 0 开 头 } \{x | x为非负偶整数,不允许0开头\} {x∣x为非负偶整数,不允许0开头}解
N F A M NFA\ M NFA M 构造如下: 对应正规文法: S → D 1 A ∣ 2 ∣ 4 ∣ 6 ∣ 8 D 1 → 1 ∣ 2 ∣ 3 ∣ 4 ∣ 5 ∣ 6 ∣ 7 ∣ 8 ∣ 9 A → D 1 A ∣ 0 A ∣ 0 ∣ 2 ∣ 4 ∣ 6 ∣ 8 S→D_1 A | 2 | 4 | 6 | 8\\ D_1 →1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9\\ A→D_1A | 0A| 0 | 2 | 4 | 6 | 8 S→D1A∣2∣4∣6∣8D1→1∣2∣3∣4∣5∣6∣7∣8∣9A→D1A∣0A∣0∣2∣4∣6∣8定理
对于任意两个有穷自动机 M M M 和 M ′ M' M′,如果 L ( M ) = L ( M ′ ) L(M) = L(M') L(M)=L(M′),则称 M M M 与 M ′ M' M′ 是等价的对任意的有穷自动机 A A A,都存在一个确定的有穷自动机 A ′ A' A′,使得 L ( A ′ ) = L ( A ) L(A')= L(A) L(A′)=L(A)。即: N F A NFA NFA 与 D F A DFA DFA 都识别同一语言类, D F A DFA DFA 是 N F A NFA NFA 的特例N F A NFA NFA 并不比 D F A DFA DFA 识别能力强,但有时描述起来更容易、更自然。但在化为程序时,必须使用 D F A DFA DFA
格局运动(表示 F A FA FA 识别正则句子的过程) 设 M = { K , ∑ , f , S , Z } M = \{K,\sum,f,S,Z\} M={K,∑,f,S,Z} 是 ∑ \sum ∑ 上的一个 D F A DFA DFA
K × ∑ ∗ K\times \sum^* K×∑∗上的元素 ( q , w ) (q,w) (q,w) 称为 K K K 的一个格局 ( w w w 表示待分析的串)如果 f ( q , a ) = q ’ f(q, a) = q’ f(q,a)=q’,则称 D F A DFA DFA 从格局 ( q , a x ) (q, ax) (q,ax) 进入 ( q ’ , x ) (q’,x) (q’,x) 为一次运动。记为 ( q , a x ) ⊢ ( q ’ , x ) (q,ax)\vdash (q’,x) (q,ax)⊢(q’,x),其中: a ∈ ∑ , x ∈ ∑ ∗ a\in\sum,x\in\sum^* a∈∑,x∈∑∗运动 ⊢ \vdash ⊢ 是格局上的一个二元关系
例 串 b d b d d bdbdd bdbdd 的识别过程 解 ( q 1 , b d b d d ) ⊢ ( q 2 , d b d d ) ⊢ ( q 2 , b d d ) ⊢ ( q 2 , d d ) ⊢ ( q 2 , d ) ⊢ ( q 2 , ε ) (q_1,bdbdd)\vdash(q_2,dbdd)\vdash(q_2,bdd)\vdash(q_2,dd)\vdash(q_2,d)\vdash(q_2,ε) (q1,bdbdd)⊢(q2,dbdd)⊢(q2,bdd)⊢(q2,dd)⊢(q2,d)⊢(q2,ε) 或 ( q 1 , b d b d d ) ⊢ ∗ ( q 2 , ε ) (q_1,bdbdd)\vdash^*(q_2,ε) (q1,bdbdd)⊢∗(q2,ε) q 2 ∈ F q_2 \in F q2∈F,所以 b d b d d bdbdd bdbdd 被识别。
( q 2 , ε ) (q_2,ε) (q2,ε) 也被称为 终止格局
F A FA FA 识别的语言
设 M = ( K , Σ , f , S , Z ) M=(K,Σ,f,S,Z) M=(K,Σ,f,S,Z)是一个 F A FA FA,如果有 ( S , w ) ⊢ ∗ ( A , ε ) , 且 A ∈ Z , w ∈ Σ ∗ (S, w) \vdash^* (A, ε),且A\in Z,w\inΣ^* (S,w)⊢∗(A,ε),且A∈Z,w∈Σ∗则称串 w w w 可被 M M M 识别 M M M 所识别的 Σ ∗ Σ^* Σ∗ 上的所有串,称为 M M M 所识别的语言 F A FA FA 识别空串 如果开始状态也是终止状态,或是存在一条从初态到某个终止状态的 ε ε ε 道路,则空串可被 F A FA FA 识别例 构造 F A FA FA 识别由偶数个 0 0 0 和偶数个 1 1 1 组成的串 解 构造 F A FA FA 的状态转换图
于是 F A FA FA 记为: A = ( { S , A , B , C } , { 0 , 1 } , f , S , { S } ) A=(\{S,A,B,C\},\{0,1\},f,S,\{S\}) A=({S,A,B,C},{0,1},f,S,{S}) f ( S , 0 ) = A , f ( A , 0 ) = S , f ( B , 0 ) = C , f ( C , 0 ) = B , f ( S , 1 ) = B , f ( A , 1 ) = C , f ( B , 1 ) = S , f ( C , 1 ) = A f(S,0)=A , f(A,0)=S , f(B,0)=C , f(C,0)=B ,\\ f(S,1)=B, f(A,1)=C ,f(B,1)=S, f(C,1)=A f(S,0)=A,f(A,0)=S,f(B,0)=C,f(C,0)=B,f(S,1)=B,f(A,1)=C,f(B,1)=S,f(C,1)=A
101 101 101 能否被识别? ( S , 101 ) ⊢ ( B , 01 ) ⊢ ( C , 1 ) ⊢ ( A , ε ) , A ∉ Z (S,101) \vdash(B,01)\vdash(C,1)\vdash(A,ε), A\notin Z (S,101)⊢(B,01)⊢(C,1)⊢(A,ε),A∈/Z因此不能被识别
该语言直接写出文法有些困难,但是写出 F A FA FA 之后就可以很方便的构造文法: G [ S ] : S → 0 A ∣ 1 B ∣ ε A → 0 S ∣ 1 C B → 0 C ∣ 1 S C → 1 A ∣ 0 B \begin{aligned}G[S]:S&→0A|1B| ε\\ A&→0S|1C \\ B&→0C|1S \\ C&→1A|0B\end{aligned} G[S]:SABC→0A∣1B∣ε→0S∣1C→0C∣1S→1A∣0B
例 构造 D F A DFA DFA 识别含有奇数个1的0、1串
由 F A FA FA 的状态转换图,可得正则式 r = 0 ∗ 1 ( 0 ∣ 1 0 ∗ 1 ) ∗ r=0^*1(0|10^*1)^* r=0∗1(0∣10∗1)∗ 或者 r = ( 0 ∣ 1 0 ∗ 1 ) ∗ 1 0 ∗ r= (0|10^*1)^*10^* r=(0∣10∗1)∗10∗读入以 E O F EOF EOF 结束的符号串 x x x,按 D F A DFA DFA 的转换函数进行状态转换。如果 D F A DFA DFA 接受 x x x,返回 Y E S YES YES,否则返回 N O NO NO
int smlt_DFA() { int S; char C; S = S0; //开始状态 C = nextchar(); while (C != EOF) { S = move(S, C); // 状态转移函数 move C = nextchar(); } if (S is in Z) return YES; else return NO; }已知: N F A M 1 = ( K , Σ , f , S , F ) NFA\ M_1=(K,Σ,f,S,F) NFA M1=(K,Σ,f,S,F),且 ε ∉ Σ ε\notin Σ ε∈/Σ。求: D F A M 2 = ( K ′ , Σ , f ′ , S ′ , F ′ ) DFA\ M_2= (K' ,Σ,f',S',F') DFA M2=(K′,Σ,f′,S′,F′)
步骤:
S ′ = { S 1 , S 2 , . . . , S n } S'= \{S_1,S_2,...,S_n\} S′={S1,S2,...,Sn} ,其中 S i ∈ S ( i = 1 S_i \in S(i=1 Si∈S(i=1 ~ n ) n) n) 为 M 1 M_1 M1 开始状态 K ′ = { S ′ } K'=\{ S'\} K′={S′}对 K ′ K' K′ 中的新状态 P P P,针对每个 a ∈ Σ a\inΣ a∈Σ,求 f ′ ( P , a ) : f'(P, a): f′(P,a): Q = f ′ ( P , a ) = { f ( t , a ) ∣ t ∈ P } Q= f'(P , a)=\{ f (t, a) | t\in P \} Q=f′(P,a)={f(t,a)∣t∈P}若 Q Q Q 不在 K ′ K' K′ 中,则 K ′ = K ′ ∪ { Q } K'=K'\cup\{ Q\} K′=K′∪{Q}重复第二步,直至 K ′ K' K′ 中所有新状态的映射都计算完标记终止状态 若 K ′ K' K′ 中的状态 P P P 包含 F F F 中的状态,则令 P ∈ F ′ P\in F' P∈F′例 构造有穷自动机,它识别的语言为以 a b b abb abb 结尾的 a 、 b a、b a、b 串,并将其确定化 ( 1 ) (1) (1) 构造 N F A NFA NFA,识别以 a b b abb abb 结尾的 a 、 b a、b a、b 串 ( 2 ) (2) (2) N F A NFA NFA 转化为 D F A DFA DFA
G [ S ] : S → b S ∣ a X X → a X ∣ b Y Y → a X ∣ b Z Z → a X ∣ b S ∣ ε \begin{aligned}G[S]: S &→bS|aX\\ X &→aX|bY\\ Y &→aX|bZ\\ Z &→aX|bS|ε\end{aligned} G[S]:SXYZ→bS∣aX→aX∣bY→aX∣bZ→aX∣bS∣ε
例 已知 N F A M NFA\ M NFA M,求 D F A M DFA\ M DFA M 解
例 识别语言 { a n b m c k ∣ n , m , k ≥ 0 } \{a^nb^mc^k|n,m,k\geq0\} {anbmck∣n,m,k≥0} 解
带有空转换的 N F A NFA NFA 的确定化算法:
由 ε ε ε- N F A NFA NFA 构造等价的 D F A DFA DFA 的算法与不带有空转换的 N F A NFA NFA 确定化的算法类似,只是需要引进状态集的 ε ε ε-闭包( ε ε ε-CLOSURE)的概念,并在算法中,凡是涉及到状态集时就用与它相对应的 ε ε ε-闭包代替定义状态集 I I I 的空闭包: 设 I I I 是一状态集, C ( I ) C(I) C(I) 是其空闭包( ε ε ε-closure( I I I)),
若 P ∈ I P\in I P∈I,则 P ∈ C ( I ) P\in C(I) P∈C(I)对于 P ∈ I P\in I P∈I,若 f ( P , ε ) = Q f(P,ε)=Q f(P,ε)=Q,则 Q ∈ C ( I ) Q\in C(I) Q∈C(I) 即从 P P P 出发,经过任意条 ε ε ε 弧所能到达的任何状态 Q Q Q,都属于 C ( I ) C(I) C(I)在确定化算法中,状态集由它的 ε ε ε闭包代替,即可消除 ε ε ε 转换
定理
对任何一个具有 ε ε ε 转移的不确定的有穷自动机 N F A N NFA\ N NFA N,一定存在一个不具有 ε ε ε 转移的不确定的有穷自动机 N F A M NFA\ M NFA M ,使得 L ( M ) = L ( N ) L(M)=L(N) L(M)=L(N)例
C ( S ) = { S , A } C ( A ) = { A } \begin{aligned}C(S)&=\{S,A\}\\C(A)&=\{A\}\end{aligned} C(S)C(A)={S,A}={A}
将状态集都用其空闭包表示,其余步骤与不带 ε ε ε 转换的确定算法相同
D F A DFA DFA 如下:
例 解 该 N F A M NFA\ M NFA M 识别的语言是 L ( M ) = ( a ∣ b ) ∗ a b b L(M)=(a|b)^*abb L(M)=(a∣b)∗abb 转换后的 D S A M DSA\ M DSA M 的状态图
定理
对任意的正则文法 G = ( V N , V T , P , S ) G=( V_N, V_T, P, S) G=(VN,VT,P,S),都存在一个有穷自动机 A A A,使得 L ( A ) = L ( G ) L(A)=L(G) L(A)=L(G)对任一 D F A DFA DFA (或 N F A NFA NFA ),都存在一个正则文法 G G G,使 L ( G ) = L ( A ) L(G)=L(A) L(G)=L(A)文法 G G G 是正则的,当且仅当存在一个 F A FA FA,使 L ( G ) = L ( M ) L(G)=L(M) L(G)=L(M)已知: G = ( V N , V T , P , S ) G = (V_N,V_T,P,S ) G=(VN,VT,P,S) 是正则文法。用文法的非终极符作为状态,开始符号作为开始状态。再增加一个新的符号 R R R,作为终止状态
注意,这里的正则文法指严格意义上的正则文法,即 a ∈ V T a\in V_T a∈VT 而非一个终结符号串 (因为 F A FA FA 是一个符号一个符号地读入)
右线性文法 F A FA FA q i → a q j q_i\rightarrow aq_j qi→aqj f ( q i , a ) = q j f(q_i,a)=q_j f(qi,a)=qj q i → a q_i\rightarrow a qi→a f ( q i , a ) = R f(q_i,a)=R f(qi,a)=R A → ε A\rightarrow ε A→ε A A A 也作为终止状态例 G [ S ] : S → 0 S ∣ 1 A A → 0 A ∣ 1 S ∣ ε \begin{aligned}G[S]: S &→0S | 1A \\ A &→0A|1S | ε\end{aligned} G[S]:SA→0S∣1A→0A∣1S∣ε
解
设 F A M = ( Q , ∑ , δ , q 0 , F ) FA\ M=(Q,∑,δ,q_0,F) FA M=(Q,∑,δ,q0,F)
对于转换函数 δ ( A , t ) = B δ(A, t) =B δ(A,t)=B,可写一产生式 A → t B A→tB A→tB对于可接受状态 z z z,增加一产生式 z → ε z→ε z→ε S = q 0 S=q_0 S=q0 V T = ∑ V_T =∑ VT=∑例 已知 L ( G ) = { x ∣ x ∈ { 0 , 1 } ∗ , 且 不 含 两 个 相 邻 的 1 } L(G)=\{x | x\in\{0,1\}^* ,且不含两个相邻的1\} L(G)={x∣x∈{0,1}∗,且不含两个相邻的1}, 求文法 G G G 解
该语言属于正则语言,容易给出 F A M FA\ M FA M,如下图所示 根据 F A M FA\ M FA M,可以构造出如下的正则文法: G [ S ] : S → 0 S ∣ 1 A ∣ ε A → 0 S ∣ ε \begin{aligned}G[S]: S &→0S | 1A | ε\\ A &→0S | ε\end{aligned} G[S]:SA→0S∣1A∣ε→0S∣ε例
**左线性正则文法 G G G 构造 F A M FA\ M FA M
对于 A → a A\rightarrow a A→a 的产生式,按归约理解(自底向上),句子中的第1个字符,都是用 A → a A\rightarrow a A→a 的产生式进行归约的。对应到 F A FA FA 中, F A FA FA 从开始状态出发,读到句子的第一个字符 a a a, 将它归约为 A A A。此时引入初态 q q q, 定义为: f ( q , a ) = A f(q,a)=A f(q,a)=A对于 A → B a A\rightarrow Ba A→Ba 的产生式, F A FA FA 应该在状态 B B B 读入 a a a, 其状态转为 A A A, 即 f ( B , a ) = A f(B,a)=A f(B,a)=A按归约来说,如果一个输入串是文法 G G G 产生语言的合法句子,它最终应该被归约成开始符号。所以 G G G 的开始符号就是 F A M FA\ M FA M 的终止状态例 构造下述文法 G [ S ] G[S] G[S] 的自动机: S → A 0 A → A 0 ∣ S 1 ∣ 0 \begin{aligned}S&→A0 \\ A&→A0 | S1 | 0 \end{aligned} SA→A0→A0∣S1∣0该自动机是确定的吗?若不确定,则对它确定化。该自动机相应的语言是什么? 解
确定化:
正规式: 00 ( 0 ∣ 10 ) ∗ 00(0|10)^* 00(0∣10)∗
例 考虑 字 母 表 = { a } 字母表 =\{a\} 字母表={a} 上的语言,该语言包含的所有串的长度要么是 2 的倍数,要么是 3 的倍数,其中包括了空串 (1)试写出该语言的正则表达式 (2)画出识别该语言的不确定有限自动机(NFA);你可直接画NFA,不必运用机械 算法从正则表达式得到 (3)画出识别该语言的确定有限自动机(DFA);你可直接画DFA,不必运用机械算法从上一小题的NFA确定化得到
提示:串长只能是 2、3 的倍数,如: a a a a a aaaaa aaaaa 不满足要求
(1) ( a a ) ∗ ∣ ( a a a ) ∗ (aa)^*|(aaa)^* (aa)∗∣(aaa)∗ (2)
(3)
或
例 写出下列语言的正规式描述:所有不含子串011的01串
先画出含有子串 011 的 DFA 对上面的自动机求补得到 DFA,即,将它的非终结状态改为终结状态,终结状态改为非终结状态,同时删去不可终止的状态 依据该 DFA 可写出正则文法: 由正则文法改造可得正则式 1 ∗ ( 0 ∣ 01 ) ∗ 1^*(0|01)^* 1∗(0∣01)∗ (如果直接用 DFA 写正则式的话,得到的不是最简的正则式)定理
对于 Σ Σ Σ 上的 N F A M NFA\ M NFA M,可构造一个 Σ Σ Σ 上的正则式 r r r,使 L ( r ) = L ( M ) L(r)=L(M) L(r)=L(M)对于 Σ Σ Σ 上的每个正则式 r r r,可构造 Σ Σ Σ 上的 N F A M NFA\ M NFA M,使 L ( M ) = L ( r ) L(M)=L(r) L(M)=L(r)正则表达式(RE)可看做是一种“程序设计语言”,用来表示某些重要的应用,比如文本搜索应用或编译器部件
例如:
搜索命令 (Linux 的 grep…) 搜索系统把正则表达式转换成 D F A DFA DFA 或 N F A NFA NFA,并在所搜索的文件上模拟这个自动机词法分析器生成器。词法分析器是编译器部件,接受本质上是正则表达式的记号形式的描述,产生一个 D F A DFA DFA,识别在输入中下一个出现的记号是哪一个N F A → R E NFA\rightarrow RE NFA→RE 的步骤(纸上作业法):
新增两个状态 x , y x,y x,y x x x 为新的初态结点,用 ε ε ε 弧连向原来所有的初态结点。 y y y 为新的终态结点,将原来所有的终态结点用 ε ε ε 弧连向 y y y。形成与 M M M 等价的 M ′ M' M′对 N F A M ′ NFA\ M' NFA M′ 中的结点按下图所示规则合并弧和去状态 反复使用这些规则,直到 N F A M NFA\ M NFA M 中只剩下结点 x , y x,y x,y。其弧上的标记即为所求的正则式 R R R(结果不唯一)例: 已知 F A FA FA,求正则式 解 所求正则式 r = ( a ∣ b ∣ c ( a ∣ b ) ∗ d ) ∗ r=(a | b | c (a | b)^*d )^* r=(a∣b∣c(a∣b)∗d)∗
例: 已知 F A FA FA,求正则式
解 利用规则删去一个状态时,必须注意到一切与之有关的支路
所求正则式 r = ( 0 0 ∗ 1 ) ∗ 0 0 ∗ 0 r= ( 00^*1)^*00^*0 r=(00∗1)∗00∗0 (或 : r = 0 ( 0 ∣ 10 ) ∗ 0 r= 0(0|10)^*0 r=0(0∣10)∗0)
例 已知 L ( G ) = { x ∣ x ∈ { 0 , 1 } ∗ , 且 不 含 11 子 串 } L(G)=\{x | x\in\{0,1\}^* ,且不含11子串\} L(G)={x∣x∈{0,1}∗,且不含11子串} (1) 试构造识别该语言的 N F A NFA NFA (2) 求出 N F A NFA NFA 对应的正则式 (3) 给出该语言的正则文法 G G G 解 (1) (3)根据 F A M FA\ M FA M,给出对应的正则文法(右线性): G [ S ] : S → 0 S ∣ 1 A ∣ ε A → 0 S ∣ ε \begin{aligned}G[S]: S &→0S | 1A | ε\\ A &→0S | ε\end{aligned} G[S]:SA→0S∣1A∣ε→0S∣ε
(2)根据 N F A → R E NFA \rightarrow RE NFA→RE 的纸上作业法,可得 R = ( 0 ∣ 10 ) ∗ ( 1 ∣ ε ) R=(0|10)^*(1|ε) R=(0∣10)∗(1∣ε)
例 求下列 F A M FA\ M FA M 所描述的语言
解 (1) { w ∣ w ∈ { 0 , 1 } ∗ , 且 包 含 至 少 一 个 0 } \{w|w \in\{0,1\}^* ,且包含至少一个0\} {w∣w∈{0,1}∗,且包含至少一个0} (2) { 0 } \{0\} {0} (3) { ε } \{ε\} {ε}
正则式 R R R 构造等价的 N F A M NFA\ M NFA M
我们希望能够给出一种比较“机械”的方法,使得计算机系统能够按照规则自动进行 N F A NFA NFA 与正则表达式之间的转换相应的等价转换方法如下:
与 r = r 1 ∣ r 2 r=r_1|r_2 r=r1∣r2 等价的 ε ε ε- N F A NFA NFA其中, M 1 M_1 M1 识别 r 1 r_1 r1, M 2 M_2 M2 识别 r 2 r_2 r2
与 r = r 1 r 2 r=r_1r_2 r=r1r2 等价的 ε ε ε- N F A NFA NFA 与 r = r 1 ∗ r=r_1^* r=r1∗ 等价的 ε ε ε- N F A NFA NFA 例 构造与 r = ( 0 ∣ 1 ) ∗ 0 ∣ ( 00 ) ∗ r=(0|1)^* 0|(00)^* r=(0∣1)∗0∣(00)∗ 等价的 ε ε ε- N F A NFA NFA 解正则式 R → N F A M R \rightarrow NFA\ M R→NFA M(适合手工推导)
引进两个状态 x x x 和 y y y, x x x 是 N F A M NFA\ M NFA M 的开始状态, y y y 是终止状态, x x x 引向 y y y 的弧上标记为正则式 R R R,即把正则式表示成拓广转换图运用如下的三条转换规则不断加入新结点进行分解,直到每个弧的标记只是 V T V_T VT 中的一个字符或 ε ε ε 为止,所得的 N F A M NFA\ M NFA M 即为所求例 已知正则式 r = b ∗ ( d ∣ a d ) ( b ∣ a d ) ∗ r=b^*(d|ad)(b|ad)^* r=b∗(d∣ad)(b∣ad)∗,构造等价的 N F A M NFA\ M NFA M 解
例 已知正则式 r = 1 ( 01 ) ∗ ( 0 ∗ ∣ 1 ∗ ) 0 r= 1 (01)^*(0^* | 1^* ) 0 r=1(01)∗(0∗∣1∗)0 ,构造等价的 N F A M NFA\ M NFA M 解
根据正则式定义语言的特征,可以使 N F A M NFA\ M NFA M 的状态图更简化注意,上面的状态转换图在 ( 01 ) ∗ (01)^* (01)∗ 的部分进行了简化
例 语言 < 无 符 号 数 > <无符号数> <无符号数> ( a ) (a) (a) 正则式表示 d d ∗ ( . d d ∗ ∣ ε ) ( e ( + ∣ − ∣ ε ) d d ∗ ∣ ε ) dd^*(.dd^*|ε)(e(+|-|ε)dd^*|ε) dd∗(.dd∗∣ε)(e(+∣−∣ε)dd∗∣ε)
( c ) (c) (c) F A FA FA ( d ) (d) (d) 正则文法定义 N → d N 1 N 1 → d N 1 ∣ . N 2 ∣ e N 4 ∣ ε N 2 → d N 3 N 3 → d N 3 ∣ e N 4 ∣ ε N 4 → d N 5 ∣ + N 6 ∣ − N 6 N 5 → d N 5 ∣ ε N 6 → d N 5 \begin{aligned}N&→dN_1\\ N_1&→dN_1|.N_2|eN_4| ε \\ N_2&→dN_3 \\ N_3&→dN_3|eN_4| ε \\ N_4&→dN_5|+N_6|-N_6\\ N_5&→dN_5| ε \\ N_6&→dN_5\end{aligned} NN1N2N3N4N5N6→dN1→dN1∣.N2∣eN4∣ε→dN3→dN3∣eN4∣ε→dN5∣+N6∣−N6→dN5∣ε→dN5
在编译程序中,词法分析器(扫描器)的效率是很重要的。如果可能的话,应该使构造的 D F A DFA DFA 最小(即状态数最少)。实际上,对于任何给定的 D F A DFA DFA ,都有与之等价且唯一的具有最小状态数的 D F A DFA DFA 存在
D F A M DFA\ M DFA M 的每个可达状态存储一个输入字符子串的等价类,记为 s e t ( q ) set(q) set(q)对于同一正则语言 L L L,不同结构的自动机模型对 ∑ ∗ ∑^* ∑∗ 进行的等价划分不同,所得到字符子串的等价类也可能不同使 ∑ ∗ ∑^* ∑∗ 划分形成的等价类个数最少,即:用来存储字符子串的状态数最少的自动机,便可实现自动机的最小化定义
化简的 F A FA FA:是指没有多余状态且状态中没有两个是互相等价的多余状态:从 D F A DFA DFA 的开始状态出发,任何输入串也不能到达的那个状态在 D F A DFA DFA 中,状态 s s s 和 t t t 状态等价的条件是: (1) 一致性条件: s s s 和 t t t 必须同时为可接受态或不可接受态 (即 f ( s , a ) , f ( t , a ) f(s,a),f(t,a) f(s,a),f(t,a) 均有定义或无定义) (2) 蔓延性条件:对于所有输入符号, s s s 和 t t t 必须转换到等价的状态集里 ( f ( s , a ) , f ( t , a ) f(s,a),f(t,a) f(s,a),f(t,a)属于相同的状态集)如果 D F A DFA DFA 的状态 s s s 和 t t t 不等价,则称 s s s 和 t t t 是可区分的分割法将 D F A DFA DFA 最小化:将 D F A DFA DFA 的状态集分割成一些不相交的子集,使得任何不同子集的状态都是可区分的,而同一子集中的任何状态都是等价的
把 D F A DFA DFA 的终态和非终态分开,形成具有两个子集的基本划分对当前已划分出的子集 I ( 1 ) , I ( 2 ) , … , I ( n ) I^{(1)} ,I^{(2)},…,I^{(n)} I(1),I(2),…,I(n),看每一个 I ( i ) I^{(i)} I(i) 是否能进一步分割 如果 s , t ∈ I ( i ) s,t\in I^{(i)} s,t∈I(i) ,若 f ( s , a ) f(s,a) f(s,a) 和 f ( t , a ) f(t,a) f(t,a) 属于不同子集,则 I ( i ) I^{(i)} I(i) 应进一步细分,使 s s s 和 t t t 属于 I ( i ) I^{(i)} I(i) 的不同子集 (蔓延性); 若 s s s 有定义,而 t t t 无定义,则 s s s 和 t t t 也是可区分的,应划分在 I ( i ) I^{(i)} I(i) 的不同子集中 (一致性)重复进行上一步中的划分,直到每个子集无法再分割对每个子集,选一个状态为代表,删去其余等价状态 例如,若 I ( i ) = { S 1 , S 2 , S 3 } I^{(i)}=\{S_1,S_2,S_3\} I(i)={S1,S2,S3},删去 S 2 , S 3 S_2,S_3 S2,S3。原 D F A M DFA\ M DFA M 中有指向 S 2 , S 3 S_2,S_3 S2,S3 的有向边,均改为指向 S 1 S_1 S1;所有 S 2 , S 3 S_2,S_3 S2,S3 引出的弧,均已由 S 1 S_1 S1 引出 (由蔓延性保证)若子集中有初态,则该状态为新的初态;若子集中有终态,则该状态为新的终态例 将下图所示的 D F A M DFA\ M DFA M 最小化。 解 先画出状态转换矩阵,便于之后的观察
将 M M M 的状态按照终态和非终态分成两个子集 P 0 = ( { 1 , 2 , 3 , 4 } , { 5 , 6 , 7 } ) P_0=(\{1,2,3,4\}, \{5,6,7\}) P0=({1,2,3,4},{5,6,7})在任一含两个或以上元素的子集中寻找可区分元素。例如可以在 P 0 P_0 P0 中寻找一个子集和一个输入符号,使该子集中的状态可区分。考察: { 1 , 2 , 3 , 4 } \{1,2,3,4\} {1,2,3,4}。因为 { 1 , 2 } a = { 6 , 7 } ⊂ { 5 , 6 , 7 } , { 3 , 4 } a = { 1 , 4 } ⊂ { 1 , 2 , 3 , 4 } \{1,2\}_a=\{6,7\}\subset\{5,6,7\},\{3,4\}_a=\{1,4\} \subset\{1,2,3,4\} {1,2}a={6,7}⊂{5,6,7},{3,4}a={1,4}⊂{1,2,3,4},所以 P 1 = ( { 1 , 2 } , { 3 , 4 } , { 5 , 6 , 7 } ) P_1=(\{1,2\},\{3,4\},\{5,6,7\}) P1=({1,2},{3,4},{5,6,7})继续在任一含两个或以上元素的子集中寻找可区分元素。例如可以在 P 1 P_1 P1 中考察子集 { 3 , 4 } \{3,4\} {3,4}:由于 { 3 } a = { 1 } , { 4 } a = { 4 } \{3\}_a=\{1\},\{4\}_a =\{4\} {3}a={1},{4}a={4} 所以 P 2 = ( { 1 , 2 } , { 3 } , { 4 } , { 5 , 6 , 7 } ) P_2=(\{1,2\},\{3\},\{4\},\{5,6,7\}) P2=({1,2},{3},{4},{5,6,7})在 P 2 P_2 P2 中考察 { 5 , 6 , 7 } \{5,6,7\} {5,6,7} : 由于 { 5 } a = { 7 } , { 6 , 7 } a = { 4 } \{5\}_a=\{7\}, \{6,7\}_a=\{4\} {5}a={7},{6,7}a={4} 所以 P 3 = ( { 1 , 2 } , { 3 } , { 4 } , { 5 } , { 6 , 7 } ) P_3=(\{1,2\},\{3\},\{4\},\{5\},\{6,7\}) P3=({1,2},{3},{4},{5},{6,7})经观察,不能再划分了令 1 1 1 代表 { 1 , 2 } \{1,2\} {1,2}, 6 6 6 代表 { 6 , 7 } \{6,7\} {6,7},消去 2 2 2 和 7 7 7 。把原来指向 2 2 2 和 7 7 7 的弧,指向 1 1 1 和 6 6 6 。最小化的 D F A DFA DFA 如右图:定理
对于有同一接受集的 F A FA FA,与之等价且具有最小状态数的 D F A DFA DFA 在同构意义下是唯一的(不考虑状态命名)可通过构造最小 D F A DFA DFA,证明正则式的等价性例 通过构造下列正则式的最小 D F A DFA DFA,证明它们是等价的 ( a ∣ b ) ∗ , ( a ∗ ∣ b ∗ ) ∗ , ( ( ε ∣ a ) b ∗ ) ∗ (a | b)^*,(a^* | b^*)^*,(( ε| a)b^*)^* (a∣b)∗,(a∗∣b∗)∗,((ε∣a)b∗)∗
解 它们对应的 N F A NFA NFA 分别为
经确定化以及化简后对应的最小 D F A DFA DFA 均为: