算术运算表达式的中间代码生成

一、算术表达式转为后缀式

主要思路:从左到右扫描算术表达式,遇到的操作数直接存放到后缀表达式中,遇到的运算符以及左括号都暂时保存到运算符栈且先执行的运算符先出栈。
前提说明:exp:中缀表达式;postexp:后缀表达式;
方法描述:在扫描exp遇到一个运算符op时,
1、若栈为空,直接进栈
2、若不为空,当op的优先级高于栈顶运算符的优先级时才直接将op进栈,否则依次出栈并存入postexp,直到栈顶运算符的优先级小于op的优先级为止,然后再将op进栈。
3、若op为 ‘(’ ,直接进栈。
4、若op为 ‘)’ ,出栈运算符并存入postexp,直到栈顶为 ‘(’ ,再将 ‘(’ 出栈。
5、若op为其他运算符,而栈顶为 ‘(’ ,直接进栈。

//中缀表达式假如只考虑+、-、*、/、(、) 
string trans(string exp)
{
	string postexp="";
	stack<char> stack;
	int i=0; 
	while(i<exp.size())
	{
		switch(exp[i])
		{
			case '(':
				stack.push('(');
				i++;
				break;
			case ')':
				while(stack.top()!='(')
				{
					postexp+=stack.top();
					stack.pop();
				}
				stack.pop();
				i++;
				break;
			case '+':
			case '-':
				while(!stack.empty())
				{
					if(stack.top()=='(')
					{
						stack.push(exp[i]);
						break;
					}
					else
					{
						//对于当前情况,栈中没有运算符小于+、-;因此只有在栈中遇到 '(' 才停止出栈。 
						postexp+=stack.top();
						stack.pop();
					}
				}
				if(stack.empty())
					stack.push(exp[i]);
				i++;
				break;
			case '*':
			case '/':
				while(!stack.empty())
				{
					if(stack.top()=='(')
					{
						stack.push(exp[i]);
						break;
					}
					//遇到*、/出栈,碰到 '(' 停止; 
					else if(stack.top()=='*'||stack.top()=='/')
					{
						postexp+=stack.top();
						stack.pop();
					}
					else
						break;
				}	
				if(stack.top()!=exp[i])
					stack.push(exp[i]);
				i++;
				break;
			default:
				while(exp[i]>='0'&&exp[i]<='9'||exp[i]>='a'&&exp[i]<='z'||exp[i]>='A'&&exp[i]<='Z'||exp[i]=='_')
				{
					postexp+=exp[i++];
				}
				postexp+='#';
		}
	} 
	while(!stack.empty())
	{
		postexp+=stack.top();
		stack.pop();
	}
	cout<<postexp<<endl;
	return postexp;
}

二、后缀运算表达式转中间代码

方法描述:从左到右扫描后缀式postexp,
1、若读取的是一个操作数,将它进操作数栈opnd。
2、若读取的是一个运算符op,从操作数栈中连续出栈两个操作数,假如说是a,b,定义一个变量T(存储计算结果的变量),将它变成四元式(op,a,b,T)并将T进操作数栈

vector<string> arithMiddle(string postexp,int &n)
{
	vector<char> op={'+','-','*','/'};
	vector<string> middle;
	stack<string> opnd;
	string s="";
	for(int i=0;i<postexp.size();i++)
	{
		if(find(op.begin(),op.end(),postexp[i])==op.end())
		{
			if(postexp[i]=='#')
			{
				opnd.push(s);
				s="";
			}
			else
				s+=postexp[i];
		}
		else
		{
			string a=opnd.top();
			opnd.pop();
			string b=opnd.top();
			opnd.pop();
			string T="";
			char ch=n+48;
			T=T+'T'+ch;
			string temp="";
			temp=temp+"("+postexp[i]+','+a+','+b+','+T+')';
			middle.push_back(temp);
			opnd.push(T);
			n++;
		}
	}
	for(int i=0;i<middle.size();i++)
		cout<<middle[i]<<endl;
	return middle;
} 
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是一个非常复杂的任务,需要涉及到编译原理、数据结构、计算机组成原理等多个领域的知识。下面是一个大致的流程: 1. 词法分析器:将输入的代码转换成 Token 流,Token 是一个数据结构,包含 Token 类型和 Token 值。比如,"if (a > b) { c = 10; }" 可以被转换成如下 Token 流: ``` if, (, a, >, b, ), {, c, =, 10, ;, } ``` 2. 语法分析器:将 Token 流转换成语法树(AST),AST 是一个树形数据结构,每个节点表示一个语法结构。比如,上面的 Token 流可以被转换成如下 AST: ``` if ├── > │ ├── a │ └── b └── = ├── c └── 10 ``` 3. 中间代码生成器:将 AST 转换成中间代码。中间代码是一种类似汇编语言的低级代码,比如,上面的 AST 可以被转换成如下中间代码: ``` LABEL L1 LOAD a, R0 LOAD b, R1 CMP R0, R1 JLE L2 LOAD 10, R2 STORE R2, c JUMP L3 LABEL L2 NOP LABEL L3 NOP ``` 4. 代码优化器:对中间代码进行优化,以减少程序运行时间或者减少程序占用的内存。比如,可以将连续的 LOAD 和 STORE 操作合并成一条指令。 5. 目标代码生成器:将中间代码转换成目标代码。目标代码是机器语言的二进制代码,可以直接在计算机上执行。这一步需要考虑硬件架构和操作系统等因素。 以上是一个大致的流程,实际实现的时候还需要考虑很多细节和特殊情况。如果你想深入了解编译原理,可以参考《编译原理》这本经典的教材。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值