自定向下预测分析法(LL(1)非递归)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq2071114140/article/details/102730421

自定向下预测分析法(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'将栈顶字符出栈,将刚才得到的产生式右部反着入栈

在这里插入图片描述

经过这一步推导,语法树“生长”一次

在这里插入图片描述

第一次循环结束

第二次循环开始

当前栈顶是一个非终结符号T,查找产生式M[T,id],栈顶出栈,将产生式反着入栈

在这里插入图片描述

语法树“生长”

在这里插入图片描述

第二次循环结束

第三次循环开始

当前栈顶是一个非终结符号F,查找产生式M[F,id],栈顶出栈,将产生式反着入栈

在这里插入图片描述

语法树“生长”

在这里插入图片描述

第三次循环结束

第四次循环开始

当前栈顶是一个终结符号id与当前待匹配的串进行匹配,匹配成功,扫描指针后移,栈顶出栈

在这里插入图片描述

第四次循环结束

当前栈顶是一个非终结符号T',查找产生式M[T',+]=T'→ε空串产生式什么都不做,栈顶出栈

在这里插入图片描述

语法树“生长”

在这里插入图片描述

以此类推,直到栈中只剩“#”

如果最终栈中只剩界符“#”,则说明可以从开始符号推导到输入串,也就是说输入串是文法的一个句子。

预测分析表中的空白条目

如果在推导过程中,在找M[X,a]的过程中,找到了空白条目,则说明输入串有语法错误

猜你喜欢

转载自blog.csdn.net/qq2071114140/article/details/102730421