编译原理(二)词法分析:2.模式的形式化描述-正规式
文章目录第二章 词法分析语言识别?正规式(正则表达式)regular expression产生式第二章 词法分析三个术语:模式(pattern):即词法规则(产生和识别单词的规则)记号(token):按照某个模式识别出的元素单词(lexeme):被识别出的元素自身的值类比程序中的变量:模式:变量的类型记号:变量单词:变量的值。术语:有限字母表 ∑:如Σ...
文章目录
一、术语
术语:
- 有限字母表 ∑:如
Σ = {a, b}
- 语言L:语言 L 是有限字母表 ∑ 上有限长度字符串的集合。如
L(ε)= {ε}
- 正规式:用来表示模式,如
r = (a|b)*(a|bb)
- 正规集:用正规式描述的语言,即正规式描述的字符串集合。如
L(r)
1.语言L
定义2.1 语言L是有限字母表∑上有限长度字符串的集合
表示、术语 | 举例 |
---|---|
|S| | |abc|= 3 |
ε | |ε|= 0 |
S1S2 | “abc”“def”=“abcdef” |
Sn | “abc”3 =“abcabcabc” |
S的前缀X | “abc”的前缀可以是:ε,a,ab, abc |
S的后缀X | “abc”的前缀可以是:ε,c,bc, abc |
S的子串X | “abc”的子串可以是: ε,a,b, c, … |
S的真前缀、 | “abc”的真前缀可以是:a,ab |
真后缀 | 同理 |
真子串 | 同理 |
S的子序列X | “abdf”是“abcdef”的一个子序列(S中去掉0或若干个不一定连续的字符后形成的字符串 ) |
表示、术语 | 意义 |
---|---|
Φ | 空集合,即元素个数为0的集合 |
{ε} | 空串作为唯一元素的集合 |
X=L∪M | 并: X={s| s∈L or s∈M } |
X=L∩M | 交: X={s|s∈L and s∈M} |
X=LM | 连接: X={st|s∈L and t∈M } |
X=L* | (星)闭包: X = L ∗ = ∪ n = 0 ∞ L n = L 0 ∪ L 1 ∪ L 2 ∪ . . . X= L^*=\cup^{\infty}_{n=0}L^n=L0∪L1∪L2∪... X=L∗=∪n=0∞Ln=L0∪L1∪L2∪... |
X=L+ | 正闭包: X = L + = ∪ n = 1 ∞ L n = L 1 ∪ L 2 ∪ L 3 ∪ . . . X=L^+=\cup^{\infty}_{n=1}L^n=L1∪L2∪L3∪... X=L+=∪n=1∞Ln=L1∪L2∪L3∪... |
理解:
L
∗
=
∪
n
=
0
∞
L
n
=
L
0
∪
L
1
∪
L
2
∪
…
L^* = \cup^{\infty}_{n=0}L^n = L^0\cup L^1 \cup L^2 \cup \ldots
L∗=∪n=0∞Ln=L0∪L1∪L2∪…,L*
是集合,所以
- ε ∈ L ∗ ε∈L^* ε∈L∗(即 L 0 L^0 L0)
- a 、 b ∈ L ∗ a、b∈L^* a、b∈L∗(即 L 1 L^1 L1)
- a a 、 b b 、 … ∈ L ∗ aa、bb、\ldots∈L^* aa、bb、…∈L∗(即 L 2 L^2 L2), L 2 L^2 L2是 L 1 ∪ L 1 L^1\cup L^1 L1∪L1,每一个 L 1 L^1 L1可能是a,也可能是b
【注】 L 0 = ε , L 1 = L , L n = L L n − 1 = L n − 1 L L^0 = { ε }, L^1 = L, L^n = LL^{n-1} = L^{n-1}L L0=ε,L1=L,Ln=LLn−1=Ln−1L
2.正规式和正规集的定义
(1)正规式
定义2.2
令Σ是一个有限字母表,则Σ上的正规式及其表示的集合递归定义如下:
1. ε是正规式,它表示集合L(ε)={ε}
2. 若a是Σ上的字符,则a是正规式,它表示集合L(a)={a}
3. 若正规式r和s分别表示集合L(r)
和L(s)
,则
(a)或: r|s
是正规式,表示集合L(r)∪L(s)
,
(b)连接:rs
是正规式,表示集合L(r)L(s)
,
(c)(星)闭包:r*
是正规式,表示集合(L(r))*
(d)(r)
是正规式,表示的集合仍然是L(r)
。(加括弧改变优先级、结合性)
PS:正规式的简化表示
-
正闭包:
r+
至少一次:若r
是表示L(r)
的正规式,则r+
是表示(L(r))+
的正规式,且下述等式成立r+ = rr* = r*r
,r* = r+|ε
例如:(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)*
可以化简为:(0|1|2|3|4|5|6|7|8|9)+
-
可缺省:
r?
零次或一次:若r
是正规式,则r?
是表示L(r)∪{ε}
的正规式,且下述等式成立r?=r|ε
注意:引入算符?
的主要目的是为了回避不可以直接通过键盘输入的字符ε。
例如:E(+|-|ε)
可以改写为:E(+|-)?
-
字符组:
[r]
若r
是仅由|
运算构成的正规式,则可改写为[r']
,其中r'
可以有如下两种形式:- 枚举:如
[abc]
,它等价于:a|b|c
- 分段(左边界小于右边界):如
[0-9a-z]
,它等价于:[0123456789abcdefghijklmnopqrstuvwxyz]
- 枚举:如
-
非字符组:
[^r]
若[r]
是一个字符组形式的正规式,则[^r]
是表示∑- L(r)
的正规式。
例如:若∑={a, b, c, d, e, f, g}
,则L([^abc]) = { d, e, f, g }
(2)正规集
正规集(正规语言):用正规式描述的语言,即正规式描述的字符串集合。如L(r)
二、正规式的读法
正规式可以严格地规定记号的模式,用正规式说明记号的公式为:记号 = 正规式
。
读作为
- “记号 定义为 正规式”
- 或者 “记号 是 正规式”。
例如 id=a(a|b)*
可以读作为 “id定义为a(a|b)*
” 。
三、正规式的运算
1.正规式运算的优先级与结合性
若正规式的优先级和结合性做下述约定:
- 均具有左结合性质;
- 优先级从高到低顺序排列为:
- 星闭包运算
*
、正闭包+
、可缺省?
(这三个同一水平) - 连接运算
rs
- 或运算
r|s
- 星闭包运算
则正规式中不必要的括号可以被省略。例如,(a)|(((b)*)(c))
可以简化成a|b*c
。
2.代数性质
正规式的代数性质
等价性质 | 释义 |
---|---|
r | s = s | r | “或”运算满足交换律 |
r | ( s | t ) = ( r | s ) | t | “或”运算满足结合律 |
r ( s t ) = ( r s ) t | “连接”运算满足结合律 |
r (s | t ) = rs | rt (s | t)r = sr | tr | “连接”运算满足分配律 |
r** = r* | 星闭包具有“幂等性” |
r++ = r+ | 正闭包具有“幂等性” |
ε r = r ε = r | 字符串的前面或后面连接上空串,仍然是它 |
r* = (r | ε)* = r+ | ε | 星闭包中一定包含 ε |
r+ = r r* = r* r | “+” means “one or more” "*" means “zero or one or more” |
【ps】(A*|B*)*
等价于(A|B)*
3.正规式的等价
(1)定义
定义2.3 若正规式P和Q表示了同一个正规集,则称P和Q是等价的,记为P=Q。
例2.4:
令 L(x)={a,b},L(y)={c,d},则 L(x|y)={a,b,c,d} ,L(y|x)={a,b,c,d}
(2)正规式等价的判定(证明)
- 根据定义,证明不同的正规式表示同一集合(例2.4)
例:证明 L ( ( a b ) ∗ a ) = L ( a ( b a ) ∗ ) L((ab)*a)= L(a(ba)*) L((ab)∗a)=L(a(ba)∗)
考虑
L
(
(
a
b
)
∗
a
)
L((ab)*a)
L((ab)∗a)中的任意一个串ababab…aba,
由串连接的结合性可得:a(ba)(ba)(b…a)(ba),它恰好是
L
(
a
(
b
a
)
∗
)
L(a(ba)*)
L(a(ba)∗),即
L
(
(
a
b
)
∗
a
)
=
L
(
a
(
b
a
)
∗
)
L((ab)*a)= L(a(ba)*)
L((ab)∗a)=L(a(ba)∗)。
也可以用归纳法证明(提示:以ab重复0次、1次作为归纳基础,假设ab重复n次成立,证明ab重复n+1次也成立)。
- 根据正规式的代数性质进行运算
四、引入辅助定义
辅助定义: 内部名 = 正规式
例2.6 引入正规式的缩写形式和辅助定义式后,id和num的正规定义式(id=[a-zA-Z]([a-zA-Z0-9])*
,num=[0-9]+(.[0-9]+)?(E(+|-)?[0-9]+)?
)可重写如下。
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
【归纳】
-
正规式
r=(a|bb)
,则正规集L(r)={a,bb}
-
表示任意的 ab 串
正规式r = (a|b)*
正规集L( r )={ ε, a, b, aa, bb, ab, ba, aaa... }
理解:还要有空串 -
表示至少包含1个子串abb的ab串
正规式r=(a|b)*abb(a|b)
理解:要注意包含子串,那么串的首尾都可以有或没有ab串。 -
表示首尾均为 a 的 ab 串
正规式r=a(a|b)*a
理解:确定首尾,中间随便搞 -
表示偶数个(至少为0)b构成的串
正规式r=(bb)*
理解:bb
是一整个元素, L 1 = b b L^1=bb L1=bb -
表示偶数个(至少为2)b构成的串
正规式r=(bb)+
-
表示奇数个(至少为1)b构成的串
正规式r=b(bb)*=(bb)*b
-
字符组
[0-9a-z]
,非字符组[^abc]
【例题】
例1:给定 Σ = {a, b}, 以及 Σ 上的正规式
r = (a|b)*(a|bb)
,请问该正规式表示的正规集 L( r ) 是什么?
答:
写法(1):
L( r ) 就是所有“以 a 或 bb 结尾的 ab 串”【这句话既是自然语言描述的模式,也是用自然语言描述的正规集】。
写法(2):
若令正规式 s = (a|b)*
, 令正规式 t=a|bb,则
L( s ) = { ε, a, b, aa, bb, ab, ba, aaa, aab, aba, abb, … }
L( t ) = { a, bb }
所以 L( r ) = L(s)L(t) = { a, bb, aa, abb, ba, bbb, aaa, aabb, bba, bbbb, … }。
例2:试给出可描述集合“偶数个a开始,后面紧跟奇数个b的ab串”的正规式。(偶数至少为0,奇数至少为1)
答:偶数个(至少为0)a开始的正规式A=(aa)*
,奇数个b(至少为1)的正规式B=(bb)*b=b(bb)*
AB = (aa)*(bb)*b = (aa)*b(bb)*
例3:若某字符串集合中的每个字符串均是“偶数个a后面紧跟奇数个b”反复出现构成的ab串(偶数至少为0,奇数至少为1)。试给出可描述该集合的正规式。
((aa)*b(bb)*)+
或 ((aa)*(bb)*b)+
例4:设计一个正规式,它可描述 所有不含有子串 011 的01串 。
先写出若干最简单的串: 0, 1, 11, 00, 10, 01, 010, …
上述第1、4、6、7个串反复出现的情况,可用正规式表示:(0 | 00 | 01 | 010)* = (01 | 0)*
再考虑:仅由1组成的串(实例中的第2、3),或 若干1打头的串(实例中的第5个串)。
最终的正规式:1*|1*(01|0)* = 1*(01|0)*
例5:大家已知 C/C++ 语言的块注释的形式为 /* … */,且要求块注释内部若出现星号的话,该型号后不能紧跟斜杠,因为一旦出现 */ ,则意味着块注释结束了。请你设计一个正规式可描述这种形式的块注释。
(1)最简单的注释:空注释 /**/
。可用正规式 "/*"ε"*/"
描述。
(2)若注释非空,且没有星号,则可用正规式 "/*" [^*]* "*/"
描述。该正规式描述的情况也包含了空注释。
(3)若注释中出现星号,则要求星号紧后面不能是斜杠。可用正规式 "/*" ("*"[^/])* "*/"
描述。
(4)综合以上情况:即注释中,星号开始的情况 和 非星号开始的情况,可以以任意次序连续出现任意次。可得正规式 "/*" ([^*]* | ("*"[^/])* )* "*/"
似乎考虑完整了,但请注意:由于正规式 [^/]
可产生字符 "*"
,而 [^*]
可产生字符 "/"
,从而该正规式会产生错误的串 "/*... */ ...*/"
,这显然不符合块注释的约束呀。所以可将其中的 [^/]
修改为[^*/]
,从而上述正规式变成:"/*" ([^*]* | ("*"[^*/])* )* "*/"
由于 (A* | B*)*
等价于 (A|B)*
,所以上述正规式也等价于 "/*" ([^*] | "*"[^*/])* "*/"
(5)上步改写后的正规式,使得注释内部的星号不能连续出现。但实际上是允许这种情况出现的。所以再将上述正规式改写如下:"/*" ([^*] | "*"*[^*/])* "*"* "*/"
例题:针对以下三个正规集,各写出一个可描述其结构的正规式。
(1)仅仅包含两个 1 的 0、1 序列(即 01 串);【较容易】
0*10*10*
(2)不包含连续的 1 的 0、1 串; 【有点难】
(0|10)*1? , 1?(0|01)* , 0* (10+)* (1)? , 1?(0+1)*0*
(3)包含偶数个 1 的 0、1 串。 【更难】
(0*10*10*)* , (0*(10*1)*)* , 0*(10*1)*0* , (0|10*1)*
例题:如果一个集合中的元素都是长度不小于 1 且均不以 ab 开始的 a、b 串,请给出描述该集合的正规式。
a|(aa|b)(a|b)*
【注意连接运算的优先级比或运算的优先级高】
更多推荐
所有评论(0)