LL(1)语法分析C++实现

目录

实验题目

流程图

实验步骤

1、给出LL(1)文法

2、FIRST集和FOLLOW集

3、构造分析表

代码步骤

1、分析器代码表示

2、运行函数

实验结果


实验题目

(1)E→E+T | E-T | T

(2)T→T*F | T/F | F

(3)F→P^F | P

(4)P→(E) | i

此文法实际上可以表示加、减、乘、除、乘方运算法则,即有理运算法则。我们采用LL(1)分析法对以上文法进行分析。

流程图

实验步骤

1、给出LL(1)文法

原来的文法中包含左递归和公共左因子,消除(1)(2)式中的左递归和(3)式中的公共左因子。

修改后的文法为:

  (1)E->TE'

  (2)E'->+TE'|-TE'|e

  (3)T->FT'

  (4)T'->*FT'|/FT'|e

  (5)F->PF'

  (6)F'->^F|e

  (7)p->(E)|i

e表示空。

2、FIRST集和FOLLOW集

写出每个非终结符的FIRST集和FOLLOW集

 

FIRST

FOLLOW

E

(,i

),#

E'

+,-,e

),#

T

(,i

+,-,),#

T'

*,/,e 

+,-,),#

F

(,i

*,/,+,-,),#

F'

^,e

*,/,+,-,),#

P

(,i

^,*,/,+,-,),#

3、构造分析表

 

(

i

+

-

*

/

^

)

#

E

TE'

TE'

 

 

 

 

 

 

 

E'

 

 

+TE'

-TE'

 

 

 

e

e

T

FT'

FT'

 

 

 

 

 

 

 

T'

 

 

e

e

*FT'

/FT'

 

e

e

F

PF'

PF'

 

 

 

 

 

 

 

F'

 

 

e

e

e

e

^F

e  

e

P

(E)

i

 

 

 

 

 

 

 

代码步骤

1、分析器代码表示

//使用X、Y、Z 代替 E'、T'、F'
//非终结符
char non_terminal[7] ={'E','X','T','Y','F','Z','P'};

//终结符
char terminal[9]={'(','i','+','-','*','/','^',')','#'};

//分析表
string analystate[7][19]={
  {"TX","TX","NULL","NULL","NULL","NULL","NULL","NULL","NULL"},
  {"NULL","NULL","+TX","-TX","NULL","NULL","NULL","e","e"},
  {"FY","FY","NULL","NULL","NULL","NULL","NULL","NULL","NULL","NULL"},
  {"NULL","NULL","e","e","*FY","/FY","NULL","e","e"},
  {"PZ","PZ","NULL","NULL","NULL","NULL","NULL","NULL","NULL"},
  {"NULL","NULL","e","e","e","e","^F","e","e"},
  {"(E)","i","NULL","NULL","NULL","NULL","NULL","NULL","NULL"}  
};

//输入串
string input;

//当前输入符号
int nowchar=0;

//分析栈
vector<char> analystack;

2、运行函数

//读取栈顶非终结符时,获取此非终结符的index以便查询分析表
int indexN(char N){
	int i=0;
	for(i;i<7;i++){
		if(non_terminal[i]==N)return i;
	}
}
//读取当前输入符号时,获取此终结符index以便查询分析表
int indexT(char T){
	int i=0;
	for(i;i<9;i++){
		if(terminal[i]==T)return i;
	}
}

//当栈顶是非终结符时进行的推导
//NULL报错、e只抛出不进栈、其他逆序进栈
void operstack(int i,int j){	
	string formula=analystate[i][j];	
	analystack.pop_back();//栈顶元素出栈 
	if(formula=="NULL"){
		cout<<"error at ";
		int  k=0;
		for(k;k<nowchar;k++){
			cout<<input[k];
		}
		cout<<"!"<<endl;
		exit(0);
	}
	
	if(formula!="e"){//产生式结果为e,只抛出不进栈 
	    int k=formula.length()-1;
		for(k;k>=0;k--){
			analystack.push_back(formula[k]);//产生式结果逆序进栈 
		}
    }
}
//打印分析过程
void print(){
	int i;
	for(i=0;i<analystack.size();i++)
    cout<<analystack[i];
    cout<<'\t'<<'\t';//输出符号栈 
    
    cout<<input[nowchar]<<'\t'<<'\t';//输出当前输入符号 
    
    for(i=nowchar+1;i<input.length() ;i++){//输出输入串 
    	cout<<input[i];
	}
    cout<<endl;
}
int main(){
	
	cin>>input;//输入字符串 以#结尾
	analystack.push_back('#');
	analystack.push_back('E');//初始化符号栈 
	
	cout<<"符号栈"<<'\t'<<'\t'<<"当前输入符号"<<'\t'<<"输入串"<<endl;
	print(); 
	while(!analystack.empty()) {//当栈不为空时 
	
		while(analystack.back()!=input[nowchar]){//当栈顶元素与输入不匹配时递推 	
			operstack(indexN(analystack.back()),indexT(input[nowchar]));
			print();
		} 
		analystack.pop_back();//匹配成功,弹出栈顶符号
		if(nowchar<input.length()-1)nowchar++;//输入符号后移 
        print();
	}
	cout<<"success";
	return 0; 
}

实验结果

①输入i*(i+i)^i#判断结果:

 可以试试根据分析结果画出语法树,可以看出分析结果与熟知的有理运算各符号的运算优先级是一样的,没有二义性。

②输入错误语句i--i#判断结果:

连输两个“-”号,提示出错。不足在于遇到错误直接停止程序报错,没有查找后面表达式的正确性。

 

  • 1
    点赞
  • 0
    评论
  • 13
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

kan木

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值