部分代码如下(仅供参考)
//部分函数和数据结构设计省略,可通过最下方链接下载
void firstvt_lastvt() //遍历一遍所有产生式,更新firstvt、lastvt集合
{
for(int s = 0; s < grammar.size(); s++)
{
string grammar_this = grammar[s]; //存储每一次遍历的产生式
int t = grammar_this.find("->"); //t为‘-’的位置
string grammar_left = grammar_this.substr(0, t); //左串 即非终结符
t+=2;
string grammar_right = grammar_this.substr(t); //右串
vector<string> Y;
Y = splitStringtoVector(grammar_right); //右串分割为终结符与非终结符组成的vector一元组
int k = Y.size();
//Y[0]为终结符 P -> a...
if(vt.count(Y[0]) != 0)
firstvt[vn[grammar_left]].insert(Y[0]);
//Y[1]为终结符 P -> Qa...
else if(k > 1 && vt.count(Y[1]) != 0)
firstvt[vn[grammar_left]].insert(Y[1]);
//Y[0]为非终结符 P -> Q...
if(vn.count(Y[0]) != 0)
{
firstvt[vn[grammar_left]] = merge_set(firstvt[vn[grammar_left]],firstvt[vn[Y[0]]]);
}
// P -> ...a
if(vt.count(Y[k-1]) != 0)
lastvt[vn[grammar_left]].insert(Y[k-1]);
// P -> ...aQ
else if(k > 2 && vt.count(Y[k-2]) != 0)
lastvt[vn[grammar_left]].insert(Y[k-2]);
// P -> ...Q
if(vn.count(Y[k-1]) != 0)
lastvt[vn[grammar_left]] = merge_set(lastvt[vn[grammar_left]],lastvt[vn[Y[k-1]]]);
}
}
void iteration() //迭代计算firstvt与lastvt集合
{
bool flag = false; //收敛标志
set <string> old_firstvt[50];
set <string> old_lastvt[50];
int times = 0; //直到收敛经历的迭代轮数
while(!flag)
{
flag = true;
times++;
firstvt_lastvt();
for(auto t = vn.begin(); t != vn.end(); t++)
{
if(firstvt[t->second].size() != old_firstvt[t->second].size() || lastvt[t->second].size() != old_lastvt[t->second].size()) //不收敛
flag = false;
old_firstvt[t->second] = firstvt[t->second];
old_lastvt[t->second] = lastvt[t->second];
}
}
cout << "times: " << times << endl;
}
float string_to_float(string s)
{
if(s[0] == '-')
return -string_to_float(s.substr(1));
float ans = 0;
if(s.find('.') != string::npos)
{
string l = s.substr(0,s.find('.'));
string r = s.substr(s.find('.')+1);
float base_l = 1;
float base_r = 0.1;
for(int i = l.size()-1; i >= 0; i--)
{
ans+=(l[i] - '0')*base_l;
// cout << ans << endl;
base_l*=10;
}
for(int i = 0; i < r.size(); i++)
{
ans+=(r[i] - '0')*base_r;
base_r/=10;
// cout << ans << endl;
}
}
else
{
float base = 1;
for(int i = s.size()-1; i >= 0; i--)
{
ans+=(s[i] - '0')*base;
base*=10;
// cout << ans << endl;
}
}
return ans;
}
int get_ind(string s) //获取中间结果下标
{
int ans = 0;
int base = 1;
for(int i = s.size()-1; i > 0; i--)
{
ans+=(s[i]-'0')*base;
base*=10;
}
return ans;
}
bool contain_alp(string s) //输入表达式是否包含字母
{
for(int i = 0; i < s.size(); i++)
{
if(s[i] >= 'a' && s[i] <= 'z')
return true;
}
return false;
}
void main_control(string inText)
{
vector <string>().swap(s);
vector <string>().swap(sm);
bool num_alp = contain_alp(inText); //true为含字母表达式
FILE *history = fopen("C:\\Users\\21911\\Desktop\\history.txt","a+");
if(history == nullptr)
{
cout << "历史文件获取失败!\n";
return;
}
FILE *f = fopen("C:\\Users\\21911\\Desktop\\curAnalysis.txt","w+"); //以重写方式打开文件
if(f == nullptr)
{
cout << "open file error!\n";
return;
}
ind = 1;
int timess = 0; //规约次数
string in = inText;
in_before = splitStringtoVector(in);
for(int i = 0; i < in_before.size(); i++)
cout << in_before[i] << " ";
cout << endl;
in = trans(in); //转换
in_after = splitStringtoVector(in);
in_after.insert(in_after.end(),1,"#");
in_before.insert(in_before.end(),1,"#");
int index = 0; //指示in_after
s.push_back("#");
sm.push_back("#"); //结束符入栈
int k = 0; //指示符号栈栈顶
int j; //指示最靠顶部的终结符
string a; //指示下一输入符号
string Q; //存储可规约串中间的终结符
string pp = "T0";
float result[MAXN]; //存放中间结果 Tk 的值 Tk = result[k]
string result_alp[MAXN];
int indind = 0; //指示使用到的编号Tk的下标k
try{
do{
cout << timess++ << ": ";
for(int u = 0; u < s.size(); u++)
cout << s[u];
cout << setw(15) << "\t";
for(int u = 0; u < sm.size(); u++)
cout << sm[u];
cout << endl;
a = in_after[index++]; //下一输入符号
if(vt.count(s[k]) != 0) //即in_[i] 属于 vt
j = k;
else
j = k-1; //栈内最靠顶部的终结符
while(table[vt[s[j]]][vt[a]] == 1) //最靠近栈顶的终结符的优先级大于现行输入终结符 进行规约
{
do{
Q = s[j];
if(j>=1 && vt.count(s[j-1]) != 0)
j=j-1;
else
j=j-2;
}while(table[vt[s[j]]][vt[Q]] == 0); //找到可规约串的开头
//规约s[j+1] ~ s[k]
int ss = match(s,j+1,k); //找到此步进行规约用到的产生式编号
if(ss == -1)
{
illegal = false;
exit(1);
}
float op_l,op_r; //此步规约式的左右操作数
string temp1,temp2,temp3; //暂存左右操作数与操作符
//s[j+1] s[j+2] s[j+3]
if(ss == 1 || ss == 2 || ss == 4 || ss == 5) //若为 + - * / 运算
{
temp1 = sm[j+1]; //左操作数 (为Tk编号 或者 字符串)
temp2 = sm[j+2]; //操作符
temp3 = sm[j+3]; //右操作数 (为Tk编号 或者 字符串)
if(!num_alp) //不含字母/**/
{
// str.append(tos(result[get_ind(temp1)]) + tos(result[get_ind(temp3)]) + temp2);
if(temp1[0] == 'T')
op_l = result[get_ind(temp1)];
else
op_l = string_to_float(temp1);
if(temp3[0] == 'T')
op_r = result[get_ind(temp3)];
else
op_r = string_to_float(temp3);
//获取左右操作数的float形式
// cout << op_l << " " << op_r;
switch(temp2[0]) //对 + - * /分类 获取结果存入result[indind]
{
case '+':
result[indind] = op_l + op_r; break;
case '-':
result[indind] = op_l - op_r; break;
case '*':
result[indind] = op_l * op_r; break;
case '/':
result[indind] = op_l / op_r; break;
}
// cout << " " << result[indind] << endl;
string stream = "(" + sm[j+2] + ", " + sm[j+1] + ", " + sm[j+3] + ", " + pp + ")\t\t" + pp + "=";
fputs(stream.data(),f);
fprintf(f, "%0.6f\n",result[indind]); //写入文件
}
else
{
result_alp[indind] = temp1+temp2+temp3;
string stream = "(" + sm[j+2] + ", " + sm[j+1] + ", " + sm[j+3] + ", " + pp + ")\t\t" + pp + "=";
fputs(stream.data(),f);
/*fprintf(f, "%s\n",result_alp[indind]);*/
fputs((result_alp[indind]+'\n').data(),f);
//写入文件
}
}
// s[j+1]
else if(ss != 8) // 非F->(E) 即不带()的产生式
{
if(!num_alp)
{
if(sm[j+1][0] == 'T')
op_l = result[get_ind(sm[j+1])];
else
op_l = string_to_float(sm[j+1]);
result[indind] = op_l;
string stream = "( =: ," + sm[j+1] + ", " + pp + ")\t\t\t" + pp + "=";
fputs(stream.data(),f);
fprintf(f, "%0.6f\n",result[indind]);
}
else {
result_alp[indind] = sm[j+1];
string stream = "( =: ," + sm[j+1] + ", " + pp + ")\t\t\t" + pp + "=";
fputs(stream.data(),f);
// fprintf(f, "%s\n",result_alp[indind]);
fputs((result_alp[indind]+'\n').data(),f);
}
}
// s[j+1]='(' s[j+2] s[j+3]=')'
else // F->(E)单独分析 E位于sm[j+2]的位置
{
if(!num_alp)
{
if(sm[j+2][0] == 'T')
op_l = result[get_ind(sm[j+2])];
else
op_l = string_to_float(sm[j+2]);
result[indind] = op_l;
string stream = "( =: ," + sm[j+2] + ", " + pp + ")\t\t\t" + pp + "=";
fputs(stream.data(),f);
fprintf(f, "%0.6f\n",result[indind]);
}
else
{
result_alp[indind] = sm[j+2];
string stream = "( =: ," + sm[j+2] + ", " + pp + ")\t\t\t" + pp + "=";
fputs(stream.data(),f);
fputs((result_alp[indind]+'\n').data(),f);
}
}
// 删除s[j+1]~s[k]
for(int q = j+1; q <= k; q++)
{
s.erase(s.begin()+j+1);
// if(ss != 7 && ss != 6 && ss != 3 && ss != 0)
sm.erase(sm.begin()+j+1);
}
k = j+1; //重置符号栈栈顶位置
s.push_back(grammar[ss].substr(0,grammar[ss].find("->")));
// 将找到的规约所用的产生式的左部加入符号栈
pp = "T";
pp.append(to_string(indind++));
sm.push_back(pp);
//新建一个中间值Tk加入带语义的符号栈
pp = "T";
pp.append(to_string(indind)); //下一个存放中间值中间编号
cout << timess++ << ": ";
for(int u = 0; u < s.size(); u++)
cout << s[u];
cout << setw(15) << "\t";
for(int u = 0; u < sm.size(); u++)
cout << sm[u];
cout << endl;
//输出规约后的符号栈
}
//退出循环 即table[vt[s[j]]][vt[a]] != 1
if(table[vt[s[j]]][vt[a]] == -1 || table[vt[s[j]]][vt[a]] == 0)
{
// cout << "1";
k++;
s.push_back(a);
try{if(index >= 1)
sm.push_back(in_before[index-1]);}catch(exception &e){
cout << "002\n";
cout << index;
throw(e);
}
}
if(table[vt[s[j]]][vt[a]] == -2)//算符优先分析表中为空
cout << "error\n";
}
while(a != "#");}catch(exception &e){
cout << "here\n";
throw(e);
}
if(illegal)
{
string his = inText+"\n";
fputs(his.data(),history);
if(indind >=1 && !num_alp)
his = to_string(result[indind-1]);
else if(indind >= 1 && num_alp)
his = inText;
his+='\n';
fputs(his.data(),history);
}
fclose(history);
fclose(f);
in_before.clear();
in_after.clear();
pp.clear();
f = nullptr;
history = nullptr;
}
结果展示:
1.Vn、Vt、FirstVT、LastVT以及算符优先分析表:
2.用户输入及输出显示界面
3.程序进行算符优先分析与规约过程具体步骤(左分析栈 右属性栈)
4.历史记录(左侧为输入的算数表达式 右侧为结果)
5.历史记录文件history(从上到下依次为表达式、结果、表达式、结果…)
6.当前输入算术表达式分析过程文件curAnalysis
(左侧为四元式 右侧为中间结果)