语法分析的功能:
语法分析方法的分类:
(1)自上而下(自顶而下)分析法:从开始符号出发,进行最左推导,或从根开始,构造推导树。(回溯分析法属于不确定的自上而下的语法分析方法,而递归下降分析法和预测方法都属于确定的自上而下的语法分析法)
(2)自下而上(自底而上)分析法:从输入串开始,直至文法开始符号。
下面来介绍回溯分析法:
实例:
S→xAy
A→ab|a
输入串为xay,说明分析过程
分析:从开始符号开始,进行左推导。如图所示:
推导之后,如右图所示,该串为xaby,显然,与题目输入串xay是不一致的,因此需要回溯,回溯得到的结果为:
回溯分析法实际上是一种试探的方法,其效率是非常低的。特别是当匹配失败后再多次试探后,逐级回溯的开销是令人难以忍受的。上面,我们来分析出现回溯的原因。
回溯出现的原因:
1.回溯——公共左因子的存在(A→ab1/ab2)
2.含有左递归引起的回溯(直接左递归和间接左递归)
①从开始符开始,但是开始符S有两个产生式,但是串第一个字符是b,首先我们选第二个产生式,如一图所示,但是图一的结果和我们的结果不一致,所以需要回溯。回溯到前一步就是选产生式那一步。
②回溯之后,选第一个产生式,由于第一个产生式存在左递归,加上结果所需要的串第一个字符为b,所以选择第一个产生式之后,再选择第二个产生式,如图2所示,显然,结果也是错误的,需要回溯到上一步。
③回溯之后,选择第一个产生式之后,再选择第一个产生式,最后再选择第二个产生式。结果正确。
由此可知,一旦出现错误,一步一步去回溯,效率是非常低的。
3.由于ε产生式引起的回溯
①从开始符S开始,但是开始符S有两个产生式,但是串第一个字符是a,首先我们选第一个产生式。出现非终结符A,但是A有两个产生式,串第二个字符是b,我们选第一个产生式,如一图所示,显然结果是错误的,需要回溯到上一步。
②回溯到上一步,即回到选A产生式那一步,我们刚刚选择第一个产生式是错误的,所以我们选择第二个产生式,接着还有一个非终结符S,加上结果串最后一个字符为b,所以我们选择第二个产生式,如图二所示。结果正确。
由此可知,一旦出现错误,一步一步去回溯,效率是非常低的。
解决回溯的办法:
1.提取公共左因子
产生式A→ab1|ab2|...|abn
将公共左因子a提取出来,变成:
A→aB
B→b1|b2|...|bn
例如:
2.消除直接左递归(变成右递归)
一般地,A→Aa1|Aa2|...|Aan|b1|b2|...|bn
变成右递归:
A→b1F|b2F|...|bnF
F→a1F|a2F|...|anF|ε
例如:
3.消除间接左递归(先把间接左递归变成直接左递归,最后再消除直接左递归)
例如:
①→②间接左递归转换为直接左递归
②→③消除直接左递归
间接左递归算法:
1.将文法G的所有非终结符按任一顺序排列,设为A1....An
2.执行下面的算法,消除可能的左递归
for(int i=1;i<=n;i++){
for(int j=1;j<=i-i;j++){
把一个形如Ai→Ajα的产生式改写成为Ai→δ1α|δ2α|...|δnα|;
(其中,Aj→δ1|δ2|...|δn是Aj的所有产生式)
消除Aj产生式的直接左递归
}
}
3.化简:删除多余产生式,即在从文法开始符号的任何推导都不会出现的非终结符的产生式。
举个例子:
(1)首先,有三个非终结符 S Q R,可以按SQR排序,或者RQS排序。我们就以按RQS排序为例,RQS设为A1A2A3.
(2)接下来,进入算法
①当i=1时,无任何操作。R→Sa|a
②当i=2时(A2),j=1(A1),这时可以理解为A2和A1存在关系,将A1(R)带入A2(Q)得Q→Sab|ab|b,该式子不存在直接左递归。注:一直是Ai→Aj的形式
③当i=3时(A3),j=2(A2),这时可以理解为A3和A2存在关系,将A2(Q)带入A3(S)得
S→Rbc|bc|c,j因为要遍历循环,当i=3时(A3),j=1(A1),将A1(R)也带入,最后的结果为S→Sabc|abc|bc|c,该式子存在直接左递归,所以我们要消除直接左递归。得到最后结果为:
S→abcB|bcB|cB
B→abcB|ε
最后的结果,用蓝色标出,但是前面两个蓝色为多余的产生式,删掉。
最后得:
S→abcB|bcB|cB
B→abcB|ε
文法产生语言的语言为:(abc|bc|c)(abc)*。
练习:
首先,先提去公共左因子。 如下图所示:
其次,第三个产生式有直接左递归,因此我们需要消除直接左递归。 如下图如示:
接着,第一个产生式和第三个产生式存在间接左递归。SBAP设为A1A2A3A4 ①当i=1,无操作②当i=2,j=1时,无操作③当i=3,j=2,无操作,当i=3,j=1时,将S带入A得A→ABbcP|bcbcP|dP④当i=4,j=3,无操作,当i=4,j=3,无操作,当i=4,j=2,无操作,当i=4,j=1,无操作。结果如下图所示:
最后,第三个产生式存在直接左递归,所以我们需要消除左递归,如下图所示:
创作不易,点个关注吧!!!