【编译原理】语法分析器的设计与实现---递归下降法(实验报告+C/C++源程序)

一、实验目的

        通过设计、开发一个高级语言的递归下降语法分析程序,加深对相关课堂教学内容(包括自顶向下语法分析、FIRST集、FOLLOW集、SELECT集、对某一输入串的分析过程)的理解,提高语法分析方法的实践能力。

二、实验要求

        编写一个递归下降语法分析器。

三、实验设备与环境

1.硬件:处理器:12th Gen Intel(R) Core(TM) i5-12500H(16 CPUs),~2.5GHZ

2.软件:dev c++

四、实验内容

五、实验步骤

        语法分析的设计与实验采用递归下降法的思想。

        为每个非终结符编制一个子程序,子程序的名字表示一个产生式左部的非终结符,程序体则是按该产生式右部的符号串顺序编写的。每匹配一个终结符,则再读入下一个符号,对于产生式右部的每个非终结符,则调用相应子程序。当一个非终结符对应多个候选式时,子程序体按可选集决定选用哪个候选式。

        实验步骤

        1.分析文法,消除左递归,避免自顶向下分析工作陷入无限循环;消除回溯,避免产生冗余操作。

        2.计算出FIRST集、FOLLOW集和SELECT集;

        3.根据递归下降语法分析的理论设计相应代码;

        4.上机调试,修复bug并完善实验设计;

        5.调试完成,完成实验。

产生式FIRST集FOLLOW集SELECT集
S->AaB{a,f,g}{#}{a,f,g}
S->Bb{d,e,b}{d,e,b}
A->aD{a}{a}{a}
A->D{f,g}{f,g}
B->d{d}{b,#}{d}
B->e{e}{e}
B->\varepsilon{\varepsilon}{b,#}
D->fD{f}{a}{f}
D->g{g}{g}

        void print()  //打印输出每一步骤的具体信息

        void error()  //如果识别错误时,进行报错

        void match(string x)  //匹配终结符

        void D()  //非终结符D的调用程序

        void B()  //非终结符B的调用程序

        void A()  //非终结符A的调用程序

        void S()  //非终结符S的调用程序

        int main()  //字符串的输入以及分析过程的入口

六、实验结果及分析

测试一:

测试二:

测试三:

        从开始符号S依次入栈,识别输入串的第一个字符,匹配所用的产生式,再将产生式右部依次入栈。如果符号栈的栈顶元素成功匹配输入串最左端,则将栈顶元素弹出,继续识别下一个字符。如果栈顶元素无法匹配输入串的最左端,则再进行判断、弹出栈顶元素、产生式右部入栈等操作;直到栈顶为终结符且与输入串能成功匹配。重复以上操作,直至符号栈为空且输入串全部识别完成。最终分析成功。

        对于以上三组测试样例,均包含了所有产生式以及各种情况,分析较为准确。

七、实验小结和思考

        本次实验我充分掌握了递归下降分析法在运行中的实际过程,掌握语法分析的基本方法和技巧。

        对于实验结果与预期结果也较为相符,输出符号串的分析过程,包括分析栈、输入串、所用产生式等,对于非法字符也会进行报错。

        实验中也会遇到一些问题:对于指向输入串下一个字符的指针总是会指向前一个或后一个,而导致分析错误。为了解决问题,通过查找资料并结合实际情况进行调试和修改,在匹配字符完成后将指针下移,就避免了重复分析或漏分析。测试时也会出现样例不充分,导致无法发现潜在错误,因此,要对程序进行全面测试。

八、源程序清单

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
//存放FIRST集
string s1="afg";
string s2="deb";
string d="fg";
string b="b#";
string b0="";
int i=0,st;  //st表示当前步骤,i指向当前字符串位置,j
string chuan;
string q="#";

void print(){
	cout<<st<<"\t"<<q<<"\t";
	for(int k=i;k<=chuan.length();k++){
		cout<<chuan[k];
	}
	cout<<"\t";
	st++;
}

void error(){
	cout<<"Error!!"<<endl;
}

void match(string x){
	print();
	cout<<x<<"匹配"<<endl;
	q.pop_back();
	i++;
}

void D(){
	char token=chuan[i];
	if(token=='f') 
	{
		print();
		cout<<"D->fD"<<endl;
		q.pop_back();
		q+="Df";
		match("f");
		D();
	}
	else if(token=='g')
	{
		print();
		cout<<"D->g"<<endl;
		q.pop_back();
		q+="g";
		match("g");
	}
	else error();
}

void B(){
	char token=chuan[i];
	if(token=='d') 
	{
		print();
		cout<<"B->d"<<endl;
		q.pop_back();
		q+="d";
		match("d");
	}
	else if(token=='e') 	
	{
		print();
		cout<<"B->e"<<endl;
		q.pop_back();
		q+="d";
		match("e");
	}
	else if(token=='#'||token=='b') 	
	{
		print();
		cout<<"B->epsilon"<<endl;
		q.pop_back();
		return;
	}
	else error();
}

void A(){
	char token=chuan[i];
	if(token=='a') 
	{
		print();
		cout<<"A->aD"<<endl;
		q.pop_back();
		q+="Da";
		match("a");
		D();
	}
	else if(d.find(token)!=string::npos) 
	{
		print();
		cout<<"A->D"<<endl;
		q.pop_back();
		q+="D";
		D();
	}
	else error();
}

void S(){
	char token=chuan[i];
	if(s1.find(token)!=string::npos)  //查找该字符是否在S的FIRST集中,如果在,则移进该字符。
	{
		q+="S";
		print();
		cout<<"S->AaB"<<endl;
		q.pop_back();  //弹出栈顶元素,移进产生式右部元素
		q+="BaA";
		A();
		match("a");
		B();
		if(i<chuan.length()-1) {  //如果退出S时,输入串还未移进完毕,则说明分析失败
			print();cout<<"分析失败!";
			return;
		}
		print();cout<<"分析成功";
	}
	else if(s2.find(token)!=string::npos) 
	{
		q+="S";
		print();
		cout<<"S->Bb"<<endl;
		q.pop_back();
		q+="bB";
		B();
		match("b");
		if(i<chuan.length()-1) {
			print();cout<<"分析失败!";
			return;
		}
		print();cout<<"分析成功";
	}
	else error();        
}        
                    
int main(){
	cout<<"请输入符号串:";
	cin>>chuan;
	chuan+="#";
	st=1;
	cout<<"步骤\t符号栈\t输入串\t所用产生式"<<endl;
	S();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值