编译原理实验二 算符优先分析法

下面代码仅为实现实验作业所写。有很多不足之处,并且只能正确判断只包含下列字符的文法,并没有做任何的其他非法语言检测。

一、实验目的

设计、编制并调试一个词法分析程序,加深对算符优先分析法的理解。

  • 实验内容

编写程序,实现算符优先分析算法。

表达式文法G(E)如下:

  1. E->E+T|T
  1. T->T*F|F
  1. F->(E)|i

该方法的优先关系矩阵如下:

+

*

i

(

)

#

+

>

<

<

<

>

>

*

>

>

<

<

>

>

i

>

>

>

>

(

<

<

<

<

=

)

>

>

>

>

#

<

<

<

<

=

#include<iostream>
#include<cstdio>
#include<stack>
#include<unordered_map>
using namespace std;

//用一个hashmap储存字符转换为对应的数字 
unordered_map<string,int> charTransion={{"+",0},{"*",1},{"i",2},{"(",3},{")",4},{"#",5}};


//设置算符优先矩阵(用数字的储存方式) >,=,<优先级依次为2,1,0;没有的置为-1 
/*
	+	*	i	(	)	#
+	2	0	0	0	2	2

*	2	2	0	0	2	2

i	2	2	-1	-1	2	2

(	0	0	0	0	1	-1

)	2	2	-1	-1	2	2

#	0	0	0	0	-1	1
*/
int prior[6][6]={{2,0,0,0,2,2},
					{2,2,0,0,2,2},
					{2,2,-1,-1,2,2},
					{0,0,0,0,1,-1},
					{2,2,-1,-1,2,2},
					{0,0,0,0,-1,1}};

//把栈中的符号,转换成字符串的形式 
string showStack(stack<string> symbol)
{
	string tmp;
	string str;
	while(symbol.size())
	{
		tmp+=symbol.top();
		symbol.pop(); 
	}
	for(int i=tmp.size()-1;i>=0;i--)
		str+=tmp[i];
	return str;
	
}


//显示在控制台 
void show(int i,stack<string> symbol,string tmp)
{
	if(tmp.size()>1) //判断剩余输入串的长度如果不为1则,照常输出,如果为1那么就只剩下一个#号 
		cout<<i<<'\t'<<showStack(symbol)<<'\t'<<tmp[0]<<'\t'<<'\t'<<tmp.substr(1)<<endl;
	else
		cout<<i<<'\t'<<showStack(symbol)<<'\t'<<tmp[0]<<endl;
}

string findVT(stack<string> symbol)//找栈中第一个非终结符 
{
	string str;
	while(symbol.size())
	{
		string s=symbol.top();
		if(s[0]=='+' || s[0]=='*' || s[0]=='i' || s[0]=='(' || s[0]==')' || s[0]=='#')
		{
			str+=s[0];
			return str;
		}
		symbol.pop();
	}
}

//判断用哪个规约式子 
string judge(string str)
{
	string tmp;
	if(str.size()==1)
	{
		if(str[0]=='T')
			tmp="E";//匹配E -> T 
		else if(str[0]=='F')
			tmp="T";//匹配T -> F
		else
			tmp="F";//匹配F -> i 
	}
	else if(str.size()==3) 
	{
		if(str[0]=='(')
			tmp="F";//匹配F -> (E)
		else if(str[1]=='*')
			tmp="T";//匹配T -> T*F
		else
			tmp="E";//匹配E -> E+T 
	}
	return tmp;
}

stack<string> reduction(stack<string> symbol,int indexY)//规约操作 
{
	//
	stack<string> red;
	string str;
	string tmp;//需要规约的字符 
	tmp+=symbol.top();
	symbol.pop();
	//下面进行规约操作 
	while(symbol.size()>=1)//因为最后一个是'#'号所以长度需要大于1 
	{
		//取出栈顶元素 
		string s=symbol.top();
		if(!isupper(s[0]))//不是大写字母
		{
			string ss;
			ss+=s[0]; 
			int indexX=charTransion[ss];//把栈顶元素转换成数字 
			int index=prior[indexX][indexY];//查找相对应的优先级 
			if(index==0)//优先级为<则进行规约 
			{
				for(int i=tmp.size()-1;i>=0;i--)str+=tmp[i];//颠倒字符串 
				str=judge(str);//寻找使用哪个规约式子 
				if(str=="")//没有找的匹配的规约式子 ,退出程序 
				{
					cout<<"程序有错"<<endl;
					exit(0);
				}
					
				break;
			}
			else//继续往栈下面查找 
			{
				indexY=indexX;
				tmp+=ss;
			}
		}
		else//是大写字母 
		{
			tmp+=s;	
		} 
		symbol.pop();
	}
	
	red=symbol;
	red.push(str);
	return red;
}

//(i+i)*i#
int main()
{
	string tt;//用来输入句子 
	string str;
	stack<string> symbol;//状态栈

	cout<<"请输入待规约句子,并以#号结尾"<<endl;
	while(cin>>tt,str+=tt,tt[tt.size()-1]!='#');//只有以'#'号结尾才能退出输入 
	int i=1;
	while(symbol.size())
	{
		cout<<symbol.top()<<endl;
		symbol.pop();
	}
	printf("步骤\t栈\t当前符号\t剩余输入串\n\n");
	string tmp=str;
	symbol.push("#");
	while(1)
	{
		show(i,symbol,tmp);//输出
		//tmp储存输入串
		//tmp[0]是代表当前符号
		//tmp.substr(1)//代表剩余输入串; 
		string stackTopVT=findVT(symbol);//栈的第一个终结符
		string nowChar;
		nowChar+=tmp[0];
		//判断是否满足成功退出条件
		if(stackTopVT=="#" && nowChar=="#")
		{
			cout<<"分析成功"<<endl;
			break; 
		}
		int indexX=charTransion[stackTopVT],indexY=charTransion[nowChar];
		int charIndex=prior[indexX][indexY];
		//按照查找出来的优先级来进行下一步的操作
		if(charIndex==-1)
		{
			cout<<"程序有错"<<endl;
			break;
		} 
		else if(charIndex==2)//进行规约操作 
		{
			symbol=reduction(symbol,indexX);
		}
		else if((charIndex==1 || charIndex==0) && tmp.size()>=2)//移进操作
		{
			string s;
			s+=tmp[0];
			symbol.push(s);
			tmp=tmp.substr(1);	
		}
		i++;
	}
	return 0;
}

运行截图:

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
算符优先分析法C是一种用于语法分析的方法,它基于算符优先关系来进行分析和判断。算符优先分析法C的主要目的是确定输入的表达式字符串是否符合给定的文法规则。 在算符优先分析法C中,首先需要定义一个算符优先关系表,该表用于存储各种操作符之间的优先级关系。然后,需要对给定的输入表达式进行预处理,将其转化为一个带有标识符和操作符的串。 接下来,通过扫描输入串,根据算符优先关系表来决定移进、规约或接受的操作。具体过程如下: 1. 初始化两个栈:一个用于存储操作符(operStack),一个用于存储标识符(identStack)。 2. 将输入表达式的结束标志符号(#)放入operStack。 3. 将输入表达式的第一个字符读入并放入identStack。 4. 重复以下步骤直到识别到结束标志符号: a. 如果当前操作符为“<”,则将其压入operStack。 b. 如果当前操作符为“>”,则根据相应规则不断进行规约,直到无法继续规约为止。 c. 如果当前操作符为“=”,则移除operStack的栈顶操作符和identStack的栈顶标识符。 5. 如果在规约过程中出现错误或者无法识别输入串,则分析过程失败。 6. 如果分析过程顺利完成,并且identStack中只剩下一个标识符且operStack中只剩下结束标志符号,则分析过程成功。 通过算符优先分析法C,我们可以判断一个给定的表达式是否符合文法规则,并且可以在分析过程中检测到错误。它是一种高效而可靠的语法分析方法,在编译器的设计实现中得到了广泛应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值