1、上下文无关 文法与语言,2005.3,引 言,从语法角度对程序设计语言的代码进行处理。对于程序设计语言的语法描述,将使用上下文无关文法的表示法,这种表示法又称为巴科斯范式,即BNF描述。这种表示法作为语言的语法描述有明显的优点:对程序可给出精确易懂的语法描述;从描述语言的文法可以自动构造出可用的分析程序;在语言的语法描述中,可以方便地插入相关的语义描述,进行语法制导的语义翻译。,主要内容,上下文无关文法的基本概念 分析和推导 文法的设计 乔姆斯基层次及上下文无关文法的局限,上下文无关文法的基本概念,定义 :上下文无关文法G是一个四元组G = (N,T,P,S),其中 N是非终结符的有限集合;
2、T是终结符或单词的有限集合,它与N不相交; P是形如A 的产生式的有限集合,其中AN,V,V=TN S是N中的区分符号,称为开始符号或句子符号。V中的符号称为文法符号,包括终结符和非终结符。,上下文无关文法的基本概念,特殊情况:A 空产生式例如, if语句结构的文法产生式表示:stmt if expr then stmt else stmt Backus - Naur范式(Backus-Naur form)或BNF文法,上下文无关文法的基本概念,符号的使用约定 : 符号是终结符: 字母表中比较靠前的小写字母,如a,b,c等。 操作符,如 +、-等。 标点符号,如括号、逗号等。 数字0,1,9。
3、 黑体串,如 id、if等。,上下文无关文法的基本概念,符号的使用约定 : 下列符号是非终结符: 字母表中比较靠前的大写字母,如A、B、C等。 字母S,它常常代表开始符号。 小写斜体名字,如expr、stmt等。 字母表中比较靠后的大写字母,如X、Y、Z等,表示文法符号,也就是说,可以是非终结符也可以是终结符。,上下文无关文法的基本概念,符号的使用约定 : 字母表中比较靠后的小写字母,如 u,v,z等,表示终结符号的串。 小写希腊字母,如、等,表示文法符号的串。因此,一个通用产生式可以写作A ,箭头左边(产生式左部)是一个非终结符A,箭头右边是文法符号串(产生式右部)。,上下文无关文法的基本概
4、念,符号的使用约定 : 如果A 1、A 2、A k 是所有以A为左部的产生式(称为A产生式),则可以把它们写成A 1|2|k,我们将1、2、k称为A的候选式。除非另有说明,否则第一个产生式左部的符号是开始符号。,上下文无关文法的基本概念,例1 考虑下面的关于简单算术表达式的文法,非终结符为和,终结符有ID,+,-,*,/,(,)。产生式有 () - ID + - * / ,E E O E | (E)| -E | ID O + | - | * | / | ,上下文无关文法的基本概念,正规表达式和上下文无关文法的关系:正规表达式所描述的每一种语言结构都可以用上下文无关文法来描述。,上下文无关文法的
5、基本概念,NFA转换成一个等价CFG(上下文无关文法) 对NFA的每个状态i,创建一个非终结符Ai。 如果在状态i输入符号a转换到状态j,则引入产生式 Ai a Aj 。 如果在状态i输入符号转换到状态j, 则引入产生式 Ai Aj。 如果状态i是接受状态,则引入产生式Ai 。 如果状态i是开始状态,则Ai 是文法的开始符号。,分析和推导,文法是用来定义一个语言的,那么,它是如何定义的? 分析树的建立过程 推导,其核心思想是把产生式看成重写规则,即用产生式右部的串来代替左部的非终结符,实际上也可以看成是从上而下推导分析树的精确描述,分析和推导,表达式(52-6) * 32的推导过程: E E
6、op E E E op E ( E )op E E (E ) ( E ) op number E number ( E ) * number op * (E op E) * number E E op E (E op number) * number E number (E number) * number op - (number number) * number E number,分析和推导,如果1 2 3 4 5 6 n ,则说1推导出n。一般,符号表示“一步推导”,通常我们用*表示“零步或多步推导”,用+表示“一步或多步推导”由推导从E 符号中得到的所有记号符号的串集是被表达式的文法定
7、义的语言。这个语言包括了所有合乎语法的表达式。由上下文无关文法产生的语言称为上下文无关语言,如果两个文法产生同样的语言,则称这两个文法等价。可将它用符号表示为:L (G) = s | E * s 其中G代表表达式文法,s 代表记号符号的任意数组串。,分析和推导,文法生成的语言示例: 例 考虑带有单个文法规则的文法G E (E )|a 例 考虑带有单个文法规则文法G: E (E) 例 考虑带有单个文法规则E E + a | a的文法G 例 考虑下面语句的极为简化的文法:statement if-stmt|otherif-stmt if (exp) statement| if (exp) stat
8、ement else statementexp 0|1,分析和推导,other if ( 0 ) other if ( 1 ) other if ( 0 ) other else other if ( 1 ) other else other if ( 0 ) if ( 0 ) other if ( 0 ) if ( 1 ) other else other if ( 1 ) other else if ( 0 ) other else other .,分析和推导,两种推导的主要方法 : 最左推导 :每一步都替代最左非终结符的推导 。最右推导 :每一步推导都替代最右非终结符的推导,分析和推导,
9、分析树 分析树是抽去了代换顺序的推导图表示。分析树中每棵子树的根,也就是树的内部节点,都是文法的非终结符,子树本身是被代换的符号的产生式的右部。文法开始符号总是整棵分析树的根。分析树的叶节点,即树中无子树的节点,或为非终结符,或为终结符,从左至右读,就构成了一个句型。句子的分析树的叶节点就得到了该句子的串。,分析和推导,分析和推导,分析和推导,二义文法 给定一个文法G,如果L(G)中存在一个具有两棵或两棵以上分析树的句子,则称G是二义性的。针对句子3+5*7,该文法就有两棵不同的语法树。,文法的设计,对输入进行语法分析的过程基本上是为其建立分析树或建立最左(最右)推导的过程。一般,每种分析方法
10、只能处理某种形式的文法。因此,虽然语言的设计者给出了定义程序设计语言的文法,但是,为了适应所选择的分析方法,还需常常改写初始文法。如适合于表达式的文法常常用结合律和优先级的信息来构造。 如何设计好文法,使其能够更好适应分析方法,包括消除二义性、消去左递归等等。,文法的设计,验证由文法产生的语言 从给定的文法定义,推导出它所生成的语言。验证给定的文法或产生式集合是否产生指定的语言是非常重要的。可以从两方面进行, 为语言设计精确的抽象的文法; 推导文法所生成的语言。对“文法G产生语言L”的证明包括两部分: 证明由G产生的每个字符串都在L中。 证明L中的每个字符串都能有G产生。,文法的设计,消除二义
11、性 必要性 有两个解决二义性的基本方法 : 设置一个规则,该规则可在每个二义性情况下指出哪一个分析树(或语法树)是正确的。这样的规则称作消除二义性规则 。 将文法改变成一个强制正确分析树的构造的格式,这样就可以解决二义性了。 优缺点比较:,文法的设计,消除二义性 重写规则后使得所有的运算都是左结合:E E addop term | termaddop + | -term term mulop factor | factormulop *factor ( E ) | number,文法的设计,消除二义性 “悬挂else”的问题 stmt if expr then stmt | if expr t
12、hen stmt else stmt | other,文法的设计,消除二义性 “悬挂else”的问题 每个else都同其前面最近的未匹配的then相匹配 改写后的文法如下: stmt matched_stmt | unmatched_stmt matched_stmt if expr then matched_stmt else matched_stmt | other unmatched_stmt if expr then stmt | if expr then matched_stmt else unmatched_stmt,文法的设计,消除左递归 递归定义 自顶向下语法分析法不能处理左递
13、归文法 左递归的情况分三种 : 简单直接左递归 普遍直接左递归 间接左递归,文法的设计,消除左递归 简单直接左递归 左递归只出现在如下文法规则中A A | 其中和是终结符和非终结符的串,而且不以A 开头。 重写为两个规则 :A AA A | ,文法的设计,消除左递归 普遍直接左递归 如下格式的产生式:A A 1 | A 2 | . . . | A n | 1 | 2 | . . . | m 其中1, . . . , m 均不以A 开头。 重写为两个规则 :A 1 A| 2 A| . . . | m AA 1A| 2A| . . . |n A|,文法的设计,消除左递归 间接左递归 至少有一步是以
14、相同的非终结符:A * A 开始和结束的推导 该算法的方法是:为语言的所有非终结符选择任意 顺序,如A1 , . . . , Am,接着它消除所有AiAj , 其中ji 形式的文法规则的左递归。如果按这样操 作从1到m的每一个i,则由于这样的循环的每个步 骤只增加索引,且不能再次到达原始索引,因此就 不会留下任何递归循环了。,文法的设计,以某种顺序排列非终结符A1,A2,An; for i := 1 to n do begin for j :=1 to i-1 do begin 用产生式Ai1|2|k代替每个形如AiAj 的产生式, 其中,Aj1|2|k是所有的当前Aj产生式;end 消除Aj
15、产生式中的直接左递归end,文法的设计,例 考虑下面的算术表达式文法:EE + T |TTT * F |FF( E ) | id消除E和T的直接左递归,可以得到E T EE + T E|T F TT * F T|F( E )|id,文法的设计,例 考虑下面的文法: A B a | A a | c B B b | A b | d 令A1 = A,且A2 = B,当i = 1时,得到的文法是:A B a A | c AA a A |B B b | A b| d 当i = 2得到了文法:A B a A | c AA a A |B B b | B a Ab | c Ab | d,文法的设计,最后消除B
16、 的直接左递归后得到 A B a A | c A A a A | B c Ab B | d B B b B | a Ab B |,文法的设计,提取左因子 当两个或更多文法规则选择共享一个通用前缀串时,需要提取左因子。 Why?,文法的设计,提取左因子 提取方法:A | 将左边的分解出来,把用哪个产生式展开的决定推迟到可以看到足够的输入信息才作。并将该规则重写为两个规则A AA |,文法的设计,提取左因子 一般提取方法:A 1 | 2 | n 将左边的分解出来,把用哪个产生式展开的决定推迟到可以看到足够的输入信息才作。并将该规则重写为两个规则A AA 1 | 2 | n,文法的设计,提取左因子
17、例: S i E t S | i E t S e S | aE b提取左因子后,该文法变为:S i E t S S | aS e S | E b,乔姆斯基层次及 上下文无关文法的局限,4种文法非限制的、上下文有关的、上下文无关的和正则的,分别被称为0型、1型、2型和3型文法。它们构成的语言类称为以乔姆斯基命名的乔姆斯基层次(Chomsky hierarchy)。,乔姆斯基层次及 上下文无关文法的局限,语言 文法 模型正则语言 右线性文法 有穷自动机上下文无关语言 上下文无关文法 下推自动机上下文有关语言 上下文有关文法 线性有界自动机 递归可枚举语言 非限制文法 图灵机,课后习题,Page 80: 3, 9,