版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
自定向下预测分析法(LL(1)非递归)
通过之前得学习,可以知道,使用自顶向下得预测分析法,选择产生式时没必要进行回溯,每一步推导仅有一个产生式符合要求,否则就出错。
怎么知道选哪个产生式呢?在进行推导之前,要有一个预测分析表,根据当前扫描到得终结符号和当前正在推导的非终结符,得到选用哪一条产生式。(是一个二维的表格)关于怎么生成预测分析表,前面的博客有提到过。
伪代码
版本一:
//将结束符入栈
push('#');
//将开始符号入栈
push('E');
i = 0;//指向输入缓冲区的指针,初始情况下,指向第一个字符
//获取栈顶的元素
top = getTop();
while(top != '#'){
得到产生式M[top,s[i]]//M表示预测分析表
if(top是非终结符){
if(找到产生式){
pop();//将当前分析的非终结符出栈、
push(将产生式反着入栈);
top = getTop();
}
else{
error!!!
}
}
else if(top是终结符){
if(top与s[i]匹配){
pop();
i++;
top = getTop();
}
else{
error!!!!
}
}
}
版本二:
//将结束符入栈
push('#');
//将开始符号入栈
push('E');
i = 0;//指向输入缓冲区的指针,初始情况下,指向第一个字符
//获取栈顶的元素
top = getTop();
while(top != '#'){
if(top与i指向得输入符号相同){
pop();
i++;
}
else if(top是一个终结符){
error!!!
}
else if(M[top,s[i]]是一个报错条目(无产生式)){
error!!!
}
else if(M[top,s[i]]是一个产生式){
pop();
将产生式右部反着入栈
}
top = getTop();
}
举例
产生式
初始状态如下图,将#和开始符号入栈
第一次循环开始
当前栈顶是一个非终结符E
,所以需要找确定使用哪个产生式,当前的待匹配输入符号是id
,查表M[E,id]
,得到产生式E→TE'
。将栈顶字符出栈,将刚才得到的产生式右部反着入栈
经过这一步推导,语法树“生长”一次
扫描二维码关注公众号,回复:
7629001 查看本文章
第一次循环结束
第二次循环开始
当前栈顶是一个非终结符号T
,查找产生式M[T,id]
,栈顶出栈,将产生式反着入栈
语法树“生长”
第二次循环结束
第三次循环开始
当前栈顶是一个非终结符号F
,查找产生式M[F,id]
,栈顶出栈,将产生式反着入栈
语法树“生长”
第三次循环结束
第四次循环开始
当前栈顶是一个终结符号id
,与当前待匹配的串进行匹配,匹配成功,扫描指针后移,栈顶出栈
第四次循环结束
当前栈顶是一个非终结符号T'
,查找产生式M[T',+]=T'→ε
,空串产生式什么都不做,栈顶出栈
语法树“生长”
以此类推,直到栈中只剩“#”
如果最终栈中只剩界符“#”,则说明可以从开始符号推导到输入串,也就是说输入串是文法的一个句子。
预测分析表中的空白条目
如果在推导过程中,在找M[X,a]的过程中,找到了空白条目,则说明输入串有语法错误