#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];
}
}
浙公网安备 33010602011771号