编译原理(二)词法分析:2.模式的形式化描述-正规式


【编译原理博客列表】》》》》》》


一、术语

术语:

  • 有限字母表 ∑:如Σ = {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=0Ln=L0L1L2...
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=1Ln=L1L2L3...

理解: 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=0Ln=L0L1L2L*是集合,所以

  • ε ∈ L ∗ ε∈L^* εL(即 L 0 L^0 L0
  • a 、 b ∈ L ∗ a、b∈L^* abL(即 L 1 L^1 L1
  • a a 、 b b 、 … ∈ L ∗ aa、bb、\ldots∈L^* aabbL(即 L 2 L^2 L2), L 2 L^2 L2 L 1 ∪ L 1 L^1\cup L^1 L1L1,每一个 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=LLn=LLn1=Ln1L

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*rr* = 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)*【注意连接运算的优先级比或运算的优先级高】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值