Chapter 2 文法和语言的基础知识
2.1 概述
语法:对语言结构的定义,即这条语句是由什么构成的
语义:描述语言的含义,即这条语句是干什么的
语用:从使用的角度去描述语言,即这个语句对应的一类语句有什么用
2.2 字母表和符号串的基本概念
文法:描述语言的语法结构的形式规则
字母表:元素的非空有穷集合,记为Σ
符号(字符):字母表中每个元素称为字符
字符串(字):由Σ中的字符构成的一个有穷序列
空字:不包含任何字符的序列,记为ε
所有字的全体:包含空字,记为Σ∗,实际上就是Σ的闭包。
如Σ={a,b},那么Σ∗={ε,a,b,ab,ba,aa,ab,aaa,...}
连接:x和y两个字符串的连接xy。Σ∗的子集的连接(乘积)定义为:AB={xy∣x∈A&y∈B}
符号串的幂运算:设x为符号串,则其幂运算定义为:x0=ε,x1=x,x2=xx,...。集合的幂运算与之类似。
正闭包A+和闭包A∗:A的正闭包和闭包定义为:A+=A1∪A2∪...∪An...,A∗={ε}∪A+
2.3 文法和语言的形式定义
2.3.1 形式语言
序列的集合称为形式语言。形式语言有两种表示方式。
一种方式是将语言所有可能以枚举的形式写到一个集合中去。
另一种方式针对无法枚举的情况,称为产生式。
2.3.2 文法的形式定义
规则
规则又称产生式,是一个符号与一个符号串的有序对(A,β),通常写作A→β,其中A为规则左部,是一个符号,β为规则右部,是一个符号串。→表示“生成”、“定义为”。规则的作用是告诉我们如何使用规则中的符号生成语言中的序列,即一组规则定义了一个语言的语法结构。
文法
文法是规则的有穷集合,通常用四元组G=(VN,VT,P,S)表示,其中:
- VN是规则中非终结符号的集合
- VT是规则中终结符号的集合,VN∩VT=∅。通常使用V表示VN∪VT,称为文法中的词汇表
- P是文法规则的集合
- S是一个非终结符号,称为文法的开始符号或文法的识别符号,至少要在一条规则中出现,由它开始识别定义的语言
文法是对语言结构的定义和描述。文法四大要素中,关键是规则的集合。
为书写方便,对于若干左部相同的规则可以缩写为A→α1∣α2∣...,其中每一个αi称为A的一个候选式。约定第一条规则的左部符号为识别符号,对文法G不使用四元式显式表示,而是只写出规则。
2.3.3 语言的形式定义
直接推导
令G为一文法,从xAy直接推出xαy,即xAy⇒xαy,仅A→α是G的一个规则且x,y∈(VN∪VT)∗。即这一次直接推导只使用了一次规则。注意推导是⇒而规则是→,二者千万不要搞混。
推导
如果存在一个推导序列α0⇒α1⇒...⇒αn,则称这个序列是一个从α0到αn的长度为n的推导,记为α0⇒+αn,其表示从α0出发可以经过1步或若干步或使用若干次规则推导出αn。
广义推导
α0⇒∗αn表示从α0出发可以经过0步或若干步或使用若干次规则推导出αn。0步指的是α0=αn的情况。
句型和句子
设有文法G[S],如果S⇒∗x,x∈(VN∪VT)∗,则称符号串x为文法G[S]的句型,S⇒∗x,x∈(VT)∗,称x为文法G[S]的句子。即句子只含有终结符,是一个确定的字符串序列,而矩形可能含有非终结符,可能是一个字符串范式,表示一类字符串的格式。
语言
文法G[S]产生的所有句子的集合称为该文法G所定义的语言,记作L(G[S])。L(G[S])={x∣S⇒+x&x∈VT∗}。当文法确定时,语言也就确定。注意L(G)是VT∗的一个子集,属于VT∗的符号串x不一定属于L(G),因为VT∗中不是所有的符号串都满足文法规定的句型格式。
2.3.4 规范推导和规范规约
最左(最右)推导:对于一个推导序列中的每一步直接推导α⇒β,都是对α中的最左(最右)非终结符进行替换。最右推导又称规范推导,由规范推导推导出的句型称为规范句型。
规范规约:规范推导的逆过程,即从左向右进行规约,也称为最左规约。
2.4 短语、直接短语和句柄
2.4.1 短语和直接短语
令G为一个文法,S为文法开始符号,假定αβδ是文法G的一个句型,如果有S⇒∗αAδ且A⇒+β,则称β是相对于非终结符A的句型αβδ的短语。特别地如果有S⇒∗αAδ且A⇒β,则称β为直接短语。一个句型的最左直接短语称为该句型的句柄。
2.5 语法树与文法的二义性
2.5.1 推导和语法树
语法树:使用一张图表示一个句型的推导,称为语法树。一棵语法树是不同推导过程的共性抽象。
语法树的子树:由某一个非末端结点连同所有分支组成的部分。
简单子树:只有单层分支的子树。
可以根据语法树快速确定一个句子的短语、直接短语和句柄。方法如下:
短语——子树的末端结点形成的符号串是相对于子树根的短语。
直接短语——简单子树的末端结点形成的符号串是相对于简单子树根的短语。
句柄——最左简单子树的末端结点形成的符号串是句柄。
2.5.2 文法的二义性
当一个句型有多个最左(最右)推导时,表示该文法存在某个句子对应两棵不同的语法树,该文法具有二义性。一个语言是二义的,如果对其不存在没有二义性的文法。
消除二义性文法可以通过添加限制性规定、调整运算符的优先顺序和结合规则等方式实现。
2.6 文法和语言的分类
文法和语言分为4大类:0型~3型。
- 0型:无限制文法。即每条规则的左式和右式都为(VN∪VT)∗,且左式中至少含有1个非终结符。
- 1型:上下文有关文法。每一条规则形式为αAβ→αuβ,其中A∈VN,α,β∈(VN∪VT)∗,u∈(VN∪VT)+,即在替换非终结符A时需要考虑上下文。
- 2型:上下文无关文法。每一条规则的形式为A→β,其中A∈VN,β∈(VN∪VT)∗。即使用该规则时无需考虑A的上下文结构而可以直接将其转换。
- 3型:正规文法。每一条规则的形式为A→αB或A→α,其中A,B∈VN,α∈VT∗。右线性文法和左线性文法都为3型文法。
上面4种文法可以表示的句型范围从大到小,规范性从弱到强。一些句型可能无法使用高规范文法进行表示但可以用低规范性文法表示。对于现今程序设计语言,在编译程序中,仍然采用上下文无关文法来表述其语言结构。
2.7 有关文法的实用限制和变换
对文法的实用限制有两点:
- 文法中不能包含如A→A的规则,这被称为有害规则。
- 文法中不能包含多余规则。即文法中出现以下两种规则:
- 某条规则左部符号不在所属文法的任何规则右部出现,这样这个规则就永远不可能用得上。
- 对文法中某个非终结符不能从其推导出任何终结符号串,这意味着如果使用了这个规则,那么它将一直推导下去永远无法到达终点,这显然是不允许的。
题型总结
1. 基本概念的理解
例-1:给出文法G[S]如下:
S→Bd
B→Ae
A→Ad∣d
求句子dded的句柄、所有短语和直接短语。
方法1:画出语法树。这是最为保险,也最不容易错的一种方法。此处语法树略。
方法2:进行推导。
S⇒Bd⇒Aed⇒Aded⇒dded。其中有B⇒+ded,因此ded是一个短语。同理第一个d,dd,dded也是短语。
直接短语是直接推导而来,因此只有第一个d是直接短语。
句柄是最左直接短语,即第一个d。
一定要搞清楚短语、直接短语和句柄的定义,不要混淆。
2. 根据字符串描述写出文法
例-2:使用文法表示下面描述的语言。该语言由0、1、左右括号组成,且由01开头,10结尾。中间的值可以为0、1、括号扩充的整体。由左右括号扩充的整体中,以00开头,11结尾,中间的值可以为0、1、括号扩充的整体。如01(00111)(0011011)011(0011)10是该语言的一个句子。
分析:求解写文法题时需要将问题分解,采用分治的思想逐个击破。如本题中可明显地将“括号扩充的整体”进行首先处理,然后再去处理其他的内容。将这部分定义为由非终结符T生成,则有
T→(00A11),其中A应该表示的是0或1构成的序列:
A→A0∣A1∣0∣1
外层的内容:
S→01B10,其中B应该是T和A构成的字符串
B→BT∣BA∣T∣A
所求文法:
S→01B10
B→BT∣BA∣T∣A
T→(00A11)
A→A0∣A1∣0∣1
技巧:对于一些常见的序列组合,有固定的模式可以套用——
- 由终结符{a1,a2,...,an}构成的所有字符串可以使用下面的文法规则(如不包含空串则删去最后的ε即可):
- S→Sa1∣Sa2∣...∣San∣a1∣a2∣...∣an∣ε
- 运算符优先级控制,对于运算符{∗1,∗2,...,∗n},下标越大优先级越高,则可以使用下面的文法规则表示(这只是一种表示,还有其他表示方式):
- A1→A1∗1A2∣A2
- A2→A2∗2A3∣A3
- ...
- An→An∗nAn+1∣An+1
- 若存在优先级相同的运算符,则作为一个规则的不同候选式。
实际上有了上面这两条规则模板,已经可以解决很多的问题了,但有时还可以通过一些更加巧妙的组合来简化文法的书写:
- 长度相等子串对:在句子中包含有类似于αnβn(n≥0)的形式,如果采用上面的方式需要两个规则,但实际上可以简化为一条规则:
- S→αSβ∣αβ∣ε
- 长度相关子串对:两个重复子串的长度不再相等,而是具有一定的关系:
- 大小关系:αnβm(n>morn<m,m,n≥0),以n>m为例,可以写为一条规则:
- S→αSβ∣αS∣α∣β(此时可以不加ε,因为此时m和n必有一个不为0,因此串不可能为空串)
- 倍数关系:αanβn,可以将αa看做一个整体:
- S→αaSβ∣αaβ∣ε
- 差数关系:两串长度的差值固定,将差的那一部分分离出来看做前后缀即可。
- 注意:形如anbncn的句子无法使用2型文法规则定义,因为b子串长度取决于其左右a子串和c子串的长度。换句话说,我们无法对这个句子用分治法进行规则解释。但a2nb2nc2n可以解释,其文法为:
- S→ASB∣AB∣ε
- A→a2Ab∣a2b
- B→bBc2∣bc2
- 这是将这个句子拆分成了a2nbn和bnc2n两份求解的,这两份的n的关系由第一条规则可以定义。但anbncn不能这样分解是因为n无法确定是否是偶数。当n为偶数或奇数时相应的2型文法都可以写出来,但二者合并是无法实现的。(思考:当n为奇数时,文法应该如何书写?)
- 长度相关子串对,之间夹有其他字符
- 将S的第二个候选式αβ变换为αTβ,其他内容由T规则负责解释。
3. 根据文法写出语言描述
也即第2种题型的逆推。
例-3:根据下列文法说出其定义的语言
S→0S∣SD∣D
D→aS∣b
分析:其定义的语言可以通过画树状图的方式来寻找规律。每一次对候选式进行分支,可以据此获取所有该语言的句子。如上述文法定义的语言的最短的几个句子应该是:b、0b、ab、0ab,可以发现所有这些句子的最后一个字符都是b。有推导:S⇒SD⇒0∗SD、S⇒SD∗D⇒Dn⇒anSn⇒anDn⇒anbn。再往下分析,就比较难了,因为没有对这个文法进行化简。
对该文法尝试进行化简:
S→0S∣SaS∣Sb∣aS∣b
注意到其中有S→0S∣aS,因此前缀应是0和a组成的任意长度字符串,而后缀只能是b组成的字符串。中间有一个规则是S→SaS,表示两个S中间有一个a分隔。去掉这条规则后,就只剩下对前缀后缀的规则定义了,因此这个文法描述的语言是:
一个类型的字符串A以一种方式连接起来形成的总字符串。字符串A由两个部分组成,前面是以0或a构成的任意长度字符串(含空串),后面是以b构成的任意长度字符串(不含空串)。总字符串中有1个或多个这样的字符串,这些字符串中间以a连接。
4. 二义性检查与反例
检查文法的二义性主要有判断性问题和举反例问题,多出现在运算符优先级设置不合理的文法中。二义性的直接影响是在文法分析过程中会产生移进-规约冲突和规约-规约冲突,前者出现于一个右部串是另一个右部串的子串时,后者出现在一个右部串对应多个左部串。有时对于移进-规约冲突的情形,需要进行推导才能发现右部符号串有包含情况。