自上而下的语法分析
自上而下的语法分析
自上而下 指 从文法的开始符号开始,逐步向下构建出整棵语法树。这样的分析过程会遇到以下问题:
文法左递归:导致分析过程无限循环
回溯问题:在进入错误分支后,需要恢复进入分支前的现场,导致程序设计复杂
构造不会陷入死循环的、不需要回溯的语法分析算法
1. 消除左递归
文法可以消除左递归的条件
不含以
为右部的产生式 不含回路,即不存在
1.1 直接左递归
该产生式表示 以一个beta开头,以若干个alpha结尾的串 。即
需要设计出不含左递归的文法:左递归变右递归。
容易知道,这两种文法是等价的。
CAUTION 左递归的实质是语法树不断增长而输入串的匹配没有任何推进,左递归改为右递归后,虽然语法树还可能一直增长,但是输入串的匹配指针在一直前进。
推广 更复杂产生式的直接左递归消除
含有左递归的文法
如此改为右递归:
1.2 间接左递归
若从
为了消除这种依赖关系,进行如下操作:
这样出现了直接左递归,可用之前提到的方法进行消除,即:
由于文法的轮换对称性,对其他非终结符进行操作得到的文法是等价的。
1.3 消除左递归的通用算法
1 | sort(G) # 把文法G的所有非终结符按照一种顺序排列 P_1, P_2, ..., P_N |
由于在外层循环执行到
2. 消除回溯
为了消除回溯,必须保证选派的候选项可以
2.1 First集合
假设当前需要匹配的输入串的 token 为
特别地,若
在满足 文法的规则中只能有至多一个以
但是并非所有的文法都满足上述条件,即
2.2 Follow集合
上述的
若
特别地,若
2.3 LL(1)文法
文法不含左递归
文法中的每个非终结符的产生式的所有候选项的
集合两两不相交 对于文法中的每个非终结符,若它的某个候选项的
集合中存在 ,则所有候选项的 集合不能和该非终结符的 集合相交
上述第三条规则保证了不会出现
LL(1)文法分析过程
若
,则指派 完成匹配 若
不属于任何一个候选项的 集合,则: 若某个候选项的
集合中有 ,且 ,则用 匹配。 否则,
的出现为语法错误。
2.4 First集合的构造
对于每个
若
,则 若
,且有产生式 ,则将 加入 中。特别地,若 也是一条产生式,则也将 加入 中。 若
是一条产生式,且 ,则将 中所有非 元素加入 中。 若 $X\rightarrow Y1Y_2…Y{i-1}Yi…Y_k
Y_1, Y_2, …, Y{i-1}\in VN Y_1 Y{i-1} First \epsilon First(Y_i) \epsilon First(X) Y_1 Y_k First \epsilon \epsilon First(X)$ 。
虽然一个产生式