#include<bits/stdc++.h>
using namespace std;
string s,x;
vector<string> d;
int main(){
	int id = 100,T = 1, F = 100;
	getline(cin,s);
	s+=" #";
	stringstream b(s);
	while(b>>x){
		if(x=="or"||x=="#"){
			if(x=="or") F+=2;
			else F=0;
			int n = d.size();
			for(int i=0;i<n-3;i+=3){
				cout<<id<<"(j"<<d[i+1].c_str()<<","<<d[i].c_str()<<","<<d[i+2].c_str()<<","<<id+2<<")"<<endl;
				id++;
				cout<<id<<"(j,_,_,"<<F<<")"<<endl;
				F = id++; 
			}
			cout<<id<<"(j"<<d[n-2].c_str()<<","<<d[n-3].c_str()<<","<<d[n-1].c_str()<<","<<T<<")"<<endl;
			T = id++;
			cout<<id<<"(j,_,_,"<<F<<")"<<endl;
			id++;
			d.clear();
			if(x=="#") break; 
		}
		else if(x=="and") F+=2;
		else d.push_back(x);
	}
	return 0;
} 

O - DAG优化

#include<bits/stdc++.h>
using namespace std;
struct nd {
	char ch;
	vector<char>val;//附加标记,就是图中节点右侧的变量
	int left = -1, right = -1;//指针,使用链式前向星思想
}point[200];
int num = 0;//point数组中已使用的下标,每使用一个num++,即num就是DAG图中的行数
string ans[200];//存放重构语句
bool flag[200];//标记重构的语句
bool find_val(int id, char ch);//查找id节点中val是否存在ch
int add(char ch);//添加叶子节点
void add_op(char op, char ch, int left, int right);//添加运算符节点
char chose_var(int id);//遍历id节点的val中是否有AB
void save(char ch);//依据要保留的字符ch进行删除无用变量
void dfs(int id);//以id为起点进行dfs遍历
int main()
{
	int t;
	string sentence;
	cin >> t;
	for (int i = 0; i < t; i++) {
		cin >> sentence;//输入形如a=b+c的语句
		int left = add(sentence[2]), right = add(sentence[4]);//建立叶子节点
		add_op(sentence[3], sentence[0], left, right);//建立运算符节点
	}
	for (int i = 0; i < num; i++) {//重构代码
		if (point[i].left != -1 && point[i].right != -1) {//如果不是叶子节点,重构一条语句,分析中有解释为什么要在写一个exist函数
			ans[i].push_back(chose_var(i));//对于每一个选取的变量都要判断,下面两个变量也一样
			ans[i].push_back('=');
			ans[i].push_back(chose_var(point[i].left));
			ans[i].push_back(point[i].ch);
			ans[i].push_back(chose_var(point[i].right));
		}
	}
	save('A'), save('B');//因为最后要保留AB所以分别依据A和B进行删除无用变量
	for (int i = 0; i < num; i++)//结果输出
		if (flag[i])
			cout << ans[i] << endl;
	return 0;
}
bool find_val(int id, char ch) {//查找id节点中val是否存在ch
	for (char t : point[id].val)//迭代遍历
		if (t == ch) return true;
	return false;
}
int add(char ch) {//添加叶子节点
	for (int i = 0; i < num; i++)//如果节点存在,有叶子节点或者附加标记中有返回节点号
		if (ch == point[i].ch || find_val(i, ch)) return i;
	point[num].ch = ch;
	return num++;
}
void add_op(char op, char ch, int left, int right) {//添加运算符节点
	for (int i = 0; i < num; i++)//如果有类似运算符节点则在该节点的附加标记中添加变量,如何是类似的分析中解释
		if (point[i].ch == op && point[i].left == left && point[i].right == right) {
			point[i].val.push_back(ch); return;
		}
	point[num].ch = op;//建立新的运算符节点
	point[num].val.push_back(ch);
	point[num].left = left;
	point[num].right = right;
	num++;
}
char chose_var(int id) {
	/*该函数是综合了两种功能,在重构代码是等号两边的变量都能用,不需要在左右子树中写一长串判断了*/
	if (!point[id].val.size()) return point[id].ch;
	for (char tt : point[id].val)
		if (tt == 'A' || tt == 'B') return tt;
	return point[id].val[0];
}
void save(char ch) {
	for (int i = num - 1; i >= 0; i--) {//删除无用语句,在分析中有详细解释
		if (ans[i][0] == ch) {
			dfs(i);  return;
		}
	}
}
void dfs(int id) {//以id为起点进行dfs遍历
	if (point[id].left != -1 && point[id].right != -1)
	{
		flag[id] = true;
		dfs(point[id].left);
		dfs(point[id].right);
	}
}

P - 简单的代码生成程序

#include<bits/stdc++.h>
using namespace std;
char s[110][1100],p[10]={0};//s数组用来存放输入的每一行表达式,p来代表寄存器
int n,m,top=0;//top用于判断寄存器是否占满 
int get(char ch){//get表示获得字符在第几个寄存器中,即表示获得寄存器的下标 
	for(int i=0;i<m;i++)
		if(p[i]==ch)return i;
	return -1;
}
int use(int x,char ch){//在第x行开始寻找,一直到最后一行,看是否出现过对应的字符,返回对应的行号 
	for(int i=x;i<n;i++)
		if(ch==s[i][3]||ch==s[i][5])return i;
	return n;
} 
int find(int x){
	if(top<m)return top++;//如果有空余寄存器,返回top++ 
	int t=-1,max=-1;
	for(int i=0;i<m;i++){//每个寄存器遍历一遍 
		int k=use(x,p[i]);//k等于从第x开始遍历寻找p[i]字符,找到则k等于行号 
		if(k>max){//逐渐更新max的值 
			max=k;//max相当于最后使用p[i]的行号,因为要 将最晚使用的寄存器先给其他字符使用 
			t=i;//t等于寄存器下标编号 
		}
	}
	return t;//返回寄存器编号 
} 
void print1(char ch){//输出 
	if(ch=='+')cout<<"ADD ";
	else if(ch=='-')cout<<"SUB ";
	else if(ch=='*')cout<<"MUL ";
	else if(ch=='\\')cout<<"DIV ";
}
void print2(char ch){//输出 
	int x=get(ch);
	if(x!=-1)
		cout<<"R"<<x<<endl;
	else
		cout<<ch<<endl;
}
int main(){
	cin>>n>>m;
	for(int i=0;i<n;i++)
		cin>>s[i];
	for(int i=0;i<n;i++){//从0到n-1行逐步遍历 
		int x=get(s[i][3]);//首先先调用get函数,得知字符在第几个寄存器中 
		if(x==-1){//如果寄存器中没有当前字符的操作 
			x=find(i);//返回top值或者最晚使用的寄存器编号 
			if(p[x]!='\0'&&use(i,p[x])<n){//如果寄存器不为空并且字符在以后会使用 
				cout<<"ST R"<<x<<", "<<p[x]<<endl;//将存在p[x]中的字符写入内存 
				p[x]=NULL;//将寄存器置空 
			}
			cout<<"LD R"<<x<<", "<<s[i][3]<<endl;//不符合上面情况就将内存中的内容读入寄存器中 
		}
		print1(s[i][4]);//输出 
		cout<<"R"<<x<<", ";
		print2(s[i][5]);
		p[x]=s[i][0];
	}
}

 

posted on 2025-11-14 10:06  fafrkvit  阅读(0)  评论(0)    收藏  举报