编译原理 --- 词法分析中的一些重要概念:串和语言,及语言的运算法则

首先,字母表,即Alphabet,是一个有限的符号集合。

然后,串(string) 是该字母表 的一个有穷序列。

举个简单的例子,集合{0,1}是一个二进制字母表(Binary Alphabet),可以取这个字母表里面的元素组成串,即01序列。

我们通常将串的长度记做 |s|,空串是长度为0的串,记做 ϵ
语言(Language) 是某个给定的字母表上任意一个可数的串的集合。

也即,字母表 里的符号组成 ,各个 的集合叫做 语言

对于串来说,我们有如下的一些术语:

1)串的前缀(prefix) 是 从串s的头部取0个或多个符号形成的新串
如串a、串ap是串apple的前缀。
2)串的后缀(suffix) 是 从串s的尾部取0个或多个符号形成的新串
如串e、串le是串apple的前缀。
3)串的子串(substring)是删除串s的某个前缀和某个后缀形成的新串。
4)串的真前缀真后缀真子串是既不包含空串ϵ,也不包含s本身的前缀、后缀、子串。
5)串的子序列是从串s任意按顺序地取出符号形成地串。如子序列apple可以是al、pe、appe、apple。

我们定义串x与串y的连接运算是将串y附加到串s后面,记做xy,也可以看作是x与y的乘法运算。
如x=dog,y=house,那么xy=doghouse
对于连接运算有如下性质:对于任意的串s,都有:ϵs=sϵ=s

串的 “指数运算” 如下:
定义s0=ϵ,si=si-1s,那么有s1=s,s2=ss,s3=s2s=sss,…,sn=ssss…ssss(n个s)

语言的运算规则

设L、M是两种语言,有:
L和M的并:L∪M = { s | s ∈ L 或 s∈M }
L和M的连接:LM = { xy | x ∈ L 且 y∈M}
两种语言的连接就是,从语言L任取一个串,与从语言M任取的串连接起来的所有可能的串的集合。举个例子,假设L={ab,cd},M={12,34},那么LM={ab12,ab34,cd12,cd34}。
L的正闭包:L+=Ui=1Li
L+=Ui=1Li=L1∪L2∪…∪L

为了解读正闭包的定义,我们先来看Li怎么计算。

由于LM = { xy | x ∈ L 且 y∈M},如果我们令M=L,我们可以得到L2={ xx | x ∈ L },L3=LL2={ xxx | x ∈ L },L4=LL3={ xxxx | x ∈ L }
由上面归纳得到:Li={ xxx…xxx | x ∈ L } (i个x) ={ xi | x ∈ L }。也就是说,L的i次方Li实际上就是L里面随意取i个串连接起来,其连接后所有可能得到的串的集合。举个简单的例子,令L={‘0’,‘1’,‘2’,‘3’,‘4’,‘5’,‘6’,‘7’,‘8’,‘9’},这个语言由9个串组成,每个串含有一个符号。那么L3表示的是所有可能的三位数集合,如{‘012’,‘252’,…}。

搞懂了Li的含义之后,看正闭包的定义就简单了。正闭包的定义如下:
L+=Ui=1Li=L1∪L2∪…∪L
可以观察到,L的正闭包其实就是,从L里面随意取出串,拼接成所有可能长度(长度至少为1)的串的集合。应用上面的例子L={‘0’,‘1’,‘2’,‘3’,‘4’,‘5’,‘6’,‘7’,‘8’,‘9’},那么L的正闭包L+表示的就是所有能够表示出来的数字的集合,如{‘1’,‘8’,‘12’,‘01’,‘789’,‘948357’,…}请注意,正闭包的定义里不包含L0={s0}=ϵ,也就是说,正闭包不包含空串ϵ。

L的Kleene闭包:L*=Ui=0
L=Ui=0Li=L0∪L1∪L2∪…∪L
可以看到,L的Kleene闭包和正闭包的区别仅仅在于多了个L0,也就是说,Kleene闭包仅仅是在正闭包的基础上加入了空串。
再次应用上面的例子L={‘0’,‘1’,‘2’,‘3’,‘4’,‘5’,‘6’,‘7’,‘8’,‘9’},那么L*={ϵ,‘1’,‘8’,‘12’,‘01’,‘789’,‘948357’,…}

posted @ 2020-02-17 11:44  NathanLi97  阅读(667)  评论(0)    收藏  举报