编译原理(3)语法_3(自顶向下语法分析:递归下降)

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

展开后:S → Sabc | abc | bc | c
在消除S的直接左递归后同样得到文法(3.4)。
3.3

自顶向下的语法分析
4、消除回溯
– 回溯发生的原因在于候选式存在公共的左因子,如产生式A如
下: A → αβ1 | αβ2 此时,如果输入串待分析的字符串前缀为α,则选用哪个候 选式以寻求与输入串匹配就难以确定。
重点掌握

消除左递归 消除回溯

构建递归下降子程序
3.3

自顶向下的语法分析
算法思想:

从文法的开始符号出发,向下推导,如果推导出的句子恰好
为输入符号串,则输入符号串为符合该文法的句子; 或者:开始符号作为根节点,向下生长出一棵语法树,其叶 子节点组成的句子恰好为输入符号串。这里的每一步“生长” 对应一次直接推导。
A → βA‘
A’ → α A‘ | ε 其中, A’是新引入的非终结符。ε 不可缺少,否则推导过程无 法结束。
3.3
自顶向下的语法分析
例如,含有直接左递归的表达式文法G[E]为 G[E]:E → E+T | T T → T*F | F F → (E) | i 经过消去直接左递归后得到文法G'[E]为 G'[E]: E → TE' E' → +TE' | ε T → FT' T' → *FT' | ε F → (E) | i
S' → abcS ' | ε
关于消除间接的特别说明
注意1:消除左递归之前的文法不允许有ε产生式,否则无法
得到等效的无左递归文法。因此,如果原文法中有ε的产生式,
则需将文法改写为无ε的产生式的文法。 (消除ε产生式的算法请查看参考书P27算法2.5:消除空规则) 注意2:此外,此算法并未对非终结符的排列顺序加以规定, 如果非终结符排列的顺序不同,最后得到的文法形式不同,但 是这些文法都是等价的。但是必须确保S不被消除。
(2)关于S的产生式只有一个,则生长语法树,
匹配语法树的第一个终结符x; (3) A → ab | a 有两个候选式,选择第一个, 并且匹配语法树的第二个叶子节点a;
(4)输入串xay期待匹配y,而语法树中的b与之匹配失败;
3.3

自顶向下的语法分析
1、不确定的自顶向下分析方法

假定文法G[S]为
–2、每个非终结符的所有候选终结首字符集两两不相交(候
选式不含公共左因子)
递归下降分析器的设计示例
G[E]:E → E+T | T T → T*F | F F → (E) | i G[E]:E → TE' E' → +TE' | ε T → FT' T' → *FT' | ε F → (E) | i
(3.2)
3.3

自顶向下的语法分析
3、消除左递归
一般情况下,设文法中关于A的产生式为
A → Aα1 | Aα2 | … | Aαm | β1 | β2 | … | βn R = (β1 | β2 | … | βn)(α1 | α2 | … | αm)* 其中,每个α都不等于ε且每个β都不以A开头,则消除A的 直接左递归性就是将其改为:
– 倘若候选式不含公共左因子,则推导出的首字符能与输入串
匹配的那个候选式便是惟一的匹配。

S → xAy
– 如何匹配
A → a | b
xay ?
3.3

自顶向下的语法分析
4、消除回溯的方法
– 一般情况下,设文法中关于A的产生式为
A → δβ1 | δβ2 | … | δβi | βi+1 | … | βj (3.5) 那么,可以把这些产生式改写为
是,对文法中的每个非终结符编写一个函数(或子程序), 每个函数的功能是识别由该非终结符所表示的语法成分。
– 由于描述语言的文法经常是递归定义的,因此相应的这组函
数也必然以互相递归的方式进行调用,所以这种分析方法称 为递归子程序法或递归下降分析法
– 递归下降分析程序也称为递归下降分析器,对文法的要求是: –1、文法不含左递归
3.3

自顶向下的语法分析
4、递归下降分析器 E' → +TE' | ε void E'() { if (lookahead == ‘+’) //原则2:遇到终结符’+’, 调用match() { match(‘+’); T(); E'(); } // 原则3:候选式是ε,E'认为自动获得匹配,不返回error }
,下述算法将消除文法的左递归: (1) 将文法G[S]的所有非终结符按一给定的顺序排列: A1、A2、…、An;
3.3
自顶向下的语法分析
(2) 执行下述循环语句将消除所有左递归 for(i=1;i<=n;i++) { for(j=1;j<=i−1;j++) { 把一个形如: A i A j γ | β1 | β 2 | | β n A j δ1 | δ 2 | | δ k 的产生式改写为 Ai→δ1γ | δ2γ | … | δkγ | β1 | β2 | … | βn; 按消除直接左递归的方法消除Ai的直接左递归; } } (3) 化简所得到的文法,去掉无用的产生式:去掉那些从开始 符号S出发,推导中无法出现的非终结符产生式。
A βA' β A βA' βαA' βα A βA' βαA' βααA' βαα A βA' βαA' βααA' βαααA' βααα …
可见,两种产生式所推导的结果相同:都能描述正规表达式βα*
3.3

自顶向下的语法分析
3、消除左递归 规则:将产生式 A → Aα | β 改写为:
A→δA'∣βi+1∣…∣βj (3.6) A'→β1∣…∣βi
例如,对文法G[A]: A → aAB | a | b提取公共左因子后的文法
G‘[A]为 G’[A]: A → aA ' | b A' → AB | ε
3.3

自顶向下的语法分析
4、递归下降分析器
– 递归下降分析法:是确定的自上而下分析法。它的基本思想
(2) 无回溯,对文法的任一非终结符号,当其产生式右部 有多个候选式可供选择时,各候选式所推出的终结符号串
的首字符集合要两两不相交
原因:会导致先前做的一大堆语义工作(指中间代码产 生工作和各种表格的簿记工作)推倒重来
3.3

自顶向下的语法分析
3、消除左递归

方法:
引入一个新的非终结符,把含有左递归的产生式改写为右递归。 设关于非终结符A的直接左递归的产生式形如 A → Aα | β
A→β1A'∣β2A'∣…∣βnA' A'→α1A'∣α2A'∣…∣αmA'∣ε
例如,对产生式 E→E+T | E-T | T,消除直接左递归后为
E → TE'
E' → +TE' | -TE' | ε
3.3

自顶向下的语法分析
3、消除间接左递归
注意:也有些文法是含有间接左递归的,如下述文法G[S]:
小结:关于不确定的自顶向下分析方法
这种自顶向下的分析是一个不断试探的过程;也即,在分
析过程中,如果出现多个产生式(即候选式)可供选择,则逐一 试探每一候选式进行匹配,每当一次试探失败,就选取下一候 选式再进行试探; 此时,必须回溯到这一次试探的初始现场,包括注销已生 长的子树及将匹配指针调回到失败前的状态。 这种带回溯的自顶向下分析方法实际上是一种穷举的试探 方法,其分析效率极低,在实用的编译程序中很少使用。
Gwk.baidu.comS]: S → Q c | c Q → R b | b R → S a | a (3.3)
中的S、Q、R都具有间接左递归
S Qc Rbc Sabc
3.3

自顶向下的语法分析
3、消除间接左递归
如何消除一个文法的一切左递归呢?如果一个文法不含回路(
+ 的推导),且产生式的右部也不含ε的候选式,那么 形如A=>A
3.3

自顶向下的语法分析
2、确定的自顶向下分析方法

确定的自顶向下分析要求文法满足两个条件:
(1) 文法不含左递归:即不存在这样的非终结符号A:有
+ Aα A
A→A…存在或者有 E→E+T

原因:左递归的文法使自顶向下分析工作陷入无限循环
E E T E T T E T T T
(3.1) 可以通过文法(3.2)构造递归下 降分析器: (1)文法(3.2)无左递归 (2) E ' 、 T ' 、F的候选式首字 (3.2) 符无交集
3.3

自顶向下的语法分析
4、递归下降分析器
void match(token t) // 匹配终结符 { if (lookahead == t) // 判断当前终结符是否匹配 lookahead = nexttoken; // 读入下一个终结符 else error(); } E → TE ' void E() // 每个非终结符对应一个子程序 { // 按照产生式顺序调用 T(); //原则1:遇到非终结符T,调用T() E'(); }
例:消除间接左递归
实际上,也可以用数学中的分配律来消除文法中的左递归。对
文法(3.3),首先将R的产生式代入到Q的产生式中并按分配律展 开(注:“(”和“)”为元语言符号)得 Q → (Sa | a)b | b 展开后:Q → Sab | ab | b
再将改变后Q的产生式代入到S的产生式中并按分配律展开得 S → (Sab | ab | b)c | c


自顶向下分析方法:

1、不确定的自顶向下分析 2、确定的自顶向下分析


递归下降分析法
LL(1)分析法
3.3

自顶向下的语法分析
1、不确定的自顶向下分析方法
– 假定文法G[S]为
S → xAy A → ab | a 若输入串为xay,则其分析过程如下: (1)建立根节点S;
S
x a A y b
S → xAy A → ab | a 若输入串为xay,则其分析过程如下:
(5)撤销匹配a,
S
x a A a y b
注销A所生成的子树,回溯;
(6)选择产生式A → a,重新匹配a; (7) 匹配输入串的字符y;而语法树的最后
一个叶子节点也是y,因此语法树和输入串xay匹配成功。
3.3

自顶向下的语法分析
A→δA'∣βi+1∣…∣βj A'→β1∣…∣βi
(3.6)
– 经过反复提取左因子,就能把每个非终结符(包括新引进者)
的所有候选首字符集变为两两不相交(即不含公共左因子)。
3.3

自顶向下的语法分析
4、消除回溯的方法
– 也可以用数学中提取公共因子的办法来提取公共左因子。如
对式(3.5)提取公共(左)因子后得 A → δβ1 | δβ2 | … | δβi | βi+1 | … | βj A → δ(β1 | β2 | … | βi ) | βi+1 | … | βj 将产生式中由“(”和“)”括起的部分以非终结符A '命名则 得到式(3.6)
例:消除间接左递归 消除文法(3.3)的左递归: G[S]: S → Q c | c Q → R b | b R → S a |a (3.3)
[解答] 1、令3个非终结符的排列顺序为R、Q、S, 2、由于R不存在直接左递归,不需要进行操作; 当i=2,j=1时,将 Q → R b | b 替换成 Q → Sab | ab | b (不需要消除直接左递归)
当i=3,j=2时,将S → Q c | c 替换成 S → Sabc | abc | bc | c (含有直接左递归)
例:消除间接左递归 消除直接左递归,得到:
S → abcS' |bcS' |cS'
S' → abcS ' | ε Q → Sab|ab|b R → Sa|a 3、显然:后两条产生式为多余的产生式,从S出发的推导无 法到达。因此,经化简后得到的文法是: S → abcS' |bcS' |cS'
其中,α、β是任意的符号串且β不以A开头。该产生式所能
推导的句子如下:
Aβ A Aα βα A Aα Aαα βαα A Aα Aαα Aααα βααα

3.3
自顶向下的语法分析
再看下面不含A的直接左递归的产生式:
A → βA'
A' → α A' | ε 这两个产生式所能推导的句子如下:
西北农林科技大学本科教程
第 6 讲
主讲教师:赵建邦
第三章 语法分析
3.1 3.2
文法和语言 推导与语法树
3.3
3.4
自顶向下的语法分析
自底向上的语法分析
3.5
规范规约的自底向上语法分析方法
本讲目标

第三章《语法分析》

3.3
自顶向下的语法分析
递归下降分析法 LL(1)分析法(下一讲内容)
相关文档
最新文档