背景:
- 自定向下的语法分析方法,LL(1)是一种非常直观的方法,它的分析过程是按照句子的定义来进行的,也就是说从开始符出发对要分析的串进行推导,如果推导成功就证明这个被分析的串是一个合法的句子,否则的话就有语法错误,但是在推导过程中,对文法进行了一些限定,保证推导过程是唯一的 。
- 总体上说,LL(1)就是在选择规则的时候加入了约束条件,考虑到输入流中的第一个符号,以及推导过程中的非终极符的规则选择,只有当头符属于当前Vn为左部的某条规则的Predict 集的时候,才使用该规则进行推导,否则即错。对规则的限定就是说规则要唯一,所以P集交集为空。
- 构造语法分析器的方法也很简单,分成输入流、分析栈、LL(1)分析表、驱动程序四个部分,构造表的目的是提高分析器的效率,驱动程序中的动作无非4个——替换、查找、成功、失败。这样就把结构用程序描述出来了,得到语法分析器。
递归下降法是另一种自顶向下的语法分析方法
先不考虑左递归的问题,在定义语法分析程序的时候,每一个非终极符都定义成一个过程或者函数:
实际上这里就是一个条件:交集为空,因为含有直接左递归的文法一定不满足第二个条件,间接左递归也不行。
程序中有一个全局变量token,用来存储输入流的第一个语法符号,分析的时候需要一个一个往里读,token保存当前字符串的第一个字符;遇到非终极符的时候有一个匹配的动作即Match(a),如果满足Match后面的函数的内容可以读取下一个语法符号了。
E(){
if token ∈ {i,(}
then{
T();
E'();
}
}
E'(){
if token ∈ {+}
then{
match(+);
T();
E'();
}
if token ∈ {#,)}
then skip;
}
T(){
if token ∈ {i,(}
then {
F();
T'();
}
}
T'(){
if token ∈ {*}
then {
match(*);
F();
T'();
}
if token ∈ {+,#,)}
then skip;
}
F(){
if token ∈ {(}
then{
match('(');
E();
match(')');
}
if token ∈ {i}
then match(i);
}
main(){
ReadToken();
E();
if(token=='#')
return true;
else
return false;
}
相应语法分析部分:
Predict(Z->aBa) :{a}
Predict(B->bB) :{b}
Predict(B->c) :{c}
B没有交集
Z(){
if token ∈ {a}
then{
match(a);
B();
match(a);
}
B(){
if token ∈ {b}
then{
match(b);
B();
}
if token ∈ {c}
then{
match(c);
}
}
main(){
ReadToken();
Z();
if token == '#'
then return true;
else return false;
}