赞
踩
版权声明:本文为原创文章,未经博主允许不得用于商业用途。
可以看出,词法单元、模式和词素是"一对一对多"的关系,下图给出了c语言词法一个示例:
词法分析在编译器中位于以下位置:
从图片上可知,词法分析将字符串形式的源程序解析为词法单元,并且生成符号表。具体来说,词法分析器具有如下作用:
读入字符流,组成词素,输出词法单元序列
过滤空白、换行、制表符、注释等
将词素添加到符号表中
将编译器生成的错误信息和在源程序中的位置联系起来(后续)
从作用可以看出,其工作流程分为扫描阶段(去除注释、多余的空白符)和词法分析(生成词法单元)阶段。
这里所说的正则表达式为最基本的正则表达式,只包含如下四种运算:并(a|b)、连接(ab)、Kleene闭包(a*)、正闭包(a+)。其中运算优先级为{‘*’,‘+’}>‘连接’>‘|’。
正则表达式可以通过递归定义,设正则表达式集合为R,则
为了书写方便,主流语言常常使用了正则定义预定义了常用正则串。正则定义规则如下:
按照如下形式定义串:
d
1
→
r
1
,
d
2
→
r
2
,
d
3
→
r
3
,
.
.
.
d_1\rightarrow r_1,\ d_2\rightarrow r_2,\ d_3\rightarrow r_3,...
d1→r1, d2→r2, d3→r3,...
其中满足:
比正则表达式更加优秀的语言表示方法是有穷自动机。所有的正则表达式都可以用有穷自动机来表示。
一个有穷自动机包含:
有穷自动机分为两类:
算法如下:
其中, ϵ − c l o s u r e ( s ) \epsilon-closure(s) ϵ−closure(s)表示NFA中通过空串符可以从s状态到达的状态集合, m o v e ( T , a ) move(T,a) move(T,a)表示T状态接收到a字符后可达的状态集合, D t r a n [ T , a ] Dtran[T,a] Dtran[T,a]表示转换表中T行a列的表项,即T状态接收到a字符后的下一个状态。
算法的流程即将0步可达的状态合并为同一个状态,之后不断遍历字符集移动到下一个状态集合,如果之前没出现过此状态集合则定义为DFA中的新的状态。
初始状态 A : ϵ − c l o s u r e ( 0 ) = { 0 , 1 , 2 , 4 , 7 } A:\epsilon-closure(0)=\{0,1,2,4,7\} A:ϵ−closure(0)={0,1,2,4,7},接受a后可达 m o v e ( A , a ) = { 3 , 8 } move(A,a)=\{3,8\} move(A,a)={3,8},因此下一个状态为 ϵ − c l o s u r e ( { 3 , 8 } ) = { 1 , 2 , 3 , 4 , 6 , 7 , 8 } \epsilon-closure(\{3,8\})=\{1,2,3,4,6,7,8\} ϵ−closure({3,8})={1,2,3,4,6,7,8},之前没有出现过,因此作为DFA中的新状态B。
按顺序计算即可得转换表:
其中A为初始状态,E为接受状态。
正则表达式到NFA的转化可以通过对四种运算的递归获得。
基本规则:
归纳部分
如图,
首先区分接受状态 { A , B , C , D } \{A,B,C,D\} {A,B,C,D}和非接受状态 { E } \{E\} {E}
之后细分第一个集合,根据字符b可以划分为 { A , B , C } \{A,B,C\} {A,B,C}和 { D } \{D\} {D}(D收到b后移动到可区分状态E)
之后细分第一个集合,根据字符b可以划分为 { A , C } \{A,C\} {A,C}和 { B } \{B\} {B}(B收到b后到达可区分状态状态D)
{ A , C } \{A,C\} {A,C}对于任何字符都不可区分,因此可以合并为一个状态。简化完成。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。