掌握算符优先分析法的一般结构和过程。 #include <fstream>
#include<iostream>
#include<string>
#include<vector>
#include<set>
#include<unordered_map>
#include<stack>
#include <iomanip>
using namespace std;
typedef string variable;//变量
typedef string terminal;//终结符
typedef string start;//开始符号
typedef struct production//产生式
{
string left;
vector<string> right;//将右部的产生式按照每一个变量和每一个终结符分割放入右部数组
}proudction;
typedef struct grammar
{
set<variable> V;//变量集合
set<terminal> T;//终结符集合
vector<production> P;//产生式
start S;//开始符号
unordered_map<variable, set<terminal>>FIRSTOP;//FIRST集合
unordered_map<variable, set<terminal>>LASTOP;//FLLOW集合
}grammar;
unordered_map<terminal, unordered_map<terminal, string>>Priority_Relationship_Matrix;//优先关系矩阵
int split(vector<production>& pro, string s)//分割字符串取出产生式左部和右部
{
production p;
int i = 0;
int spLR = -1;
for (i; i < s.size() - 1; i++)
{
if (s[i] == '-' && s[i + 1] == '>')
{
spLR = i;
break;
}
}
if (i == 0 || i >= s.size())
{
cout << endl << "这个产生式" << s << "错误!!!请重新输入";
return -1;
}
p.left = s.substr(0, i);
s.erase(0, i + 2);
p.right.push_back("");
for (i = 0; i < s.size(); i++)
{
if (s[i] == '|')
{
if (p.right[0].size() == 0)
{
p.right[0] = "$";
}
pro.push_back(p);
p.right[0] = "";
}
else
{
p.right[0] = p.right[0] + s[i];
}
}
if (p.right[0].size() == 0)
{
p.right[0] = "$";
}
pro.push_back(p);
return 0;
}
int getV_PR_S(grammar& G)//获得文法的变量,获得开始符号,以一个变量和一个终结符为单位分割产生式的右部
{
G.S = G.P[0].left;//获得开始符号
for (int i = 0; i < G.P.size(); i++)//获得变量
{
G.V.insert(G.P[i].left);
}
//以单一变量或者终结符为单位分割产生式右部
for (int i = 0; i < G.P.size(); i++)
{
string s = G.P[i].right[0];//获得此时的产生式
G.P[i].right.clear();//清空产生式右部分
if (s == "$")//如果此时的产生式本身就是空的话把$加入右部之后直接进入下一次循环
{
G.P[i].right.push_back("$");
continue;
}
int flag = 0;
while (flag != 1)
{
flag = 1;
int x = s.size();
for (auto j = G.V.begin(); j != G.V.end(); j++)//先用变量集合去匹配
{
string v = *j;
if (v.size() > s.size())//如果此时变量长度大于字符长度了就匹配下一个变量
{
continue;
}
string prfv = s.substr(s.size() - v.size(), v.size());
//cout <<v<<":" << prfv;
if (v == prfv)
{
G.P[i].right.insert(G.P[i].right.begin(), v);
//cout << G.P[i].right[0] << " ";
s.erase(s.size() - v.size());
}
//cout << endl;
}
for (auto j = G.T.begin(); j != G.T.end(); j++)//再用终结符集合去匹配
{
string t = *j;
if (t.size() > s.size())//如果此时终结符长度大于字符长度了就匹配下一个终结符
{
continue;
}
string prft = s.substr(s.size() - t.size(), t.size());
//cout << t << ":" << prft;
if (t == prft)
{
G.P[i].right.insert(G.P[i].right.begin(), t);
//cout << G.P[i].right[0] << " ";
s.erase(s.size() - t.size());
}
//cout << endl;
}
if (s.size() < x)
{
flag++;
}
}
if (s.size() > 0)
{
cout << "产生式中出现了不是变量也不是终结符的变量";
exit(0);
}
}
}
int showG(grammar& G)
{
cout << "\n\n终结符:";
cout << endl << "\t";
for (auto i = G.T.begin(); i != G.T.end(); i++)
{
cout << *i << " ";
}
cout << "\n\n变量:";
cout << endl << "\t";
for (auto i = G.V.begin(); i != G.V.end(); i++)
{
cout << *i << " ";
}
cout << "\n\n产生式:";
cout << endl;
for (int i = 0; i < G.P.size(); i++)
{
cout << "\t" << G.P[i].left << "->";
for (int j = 0; j < G.P[i].right.size(); j++)
{
cout << G.P[i].right[j];
}
cout << endl;
}
cout << "\n\nFIRSTOP集:";
cout << endl;
for (auto i = G.FIRSTOP.begin(); i != G.FIRSTOP.end(); i++)
{
cout << "\tFIRSTOP(" << i->first << "):\t{ ";
auto s = i->second.begin();
s++;
for (auto j = i->second.begin(); j != i->second.end(); j++)
{
cout << *j;
if (s != i->second.end())
{
cout << ",";
s++;
}
}
cout << " }\n";
}
cout << "\n\nLASTOP集:";
cout << endl;
for (auto i = G.LASTOP.begin(); i != G.LASTOP.end(); i++)
{
cout << "\tLASTOP(" << i->first << "):\t{ ";
auto s = i->second.begin();
s++;
for (auto j = i->second.begin(); j != i->second.end(); j++)
{
cout << *j;
if (s != i->second.end())
{
cout << ",";
s++;
}
}
cout << " }\n";
}
return 0;
}
void getFIRSTOP(grammar &G)
{
int flag = 0;
while (flag!=1)
{
flag = 1;
for (int i = 0; i < G.P.size(); i++)
{
int x = G.FIRSTOP[G.P[i].left].size();
if (G.T.find(G.P[i].right[0]) != G.T.end())//这里是处理如果产生式第一个是终结符则把这个终结符加入到这个产生式左部的firstop集合里去
{
G.FIRSTOP[G.P[i].left].insert(G.P[i].right[0]);
}
else //把这个产生式右部第一个变量之后的终结符加入到这个产生式左部的firstop集合里去,还要把第一个变量的firstop集合加入到这个产生式左部的firstop集合里去
{
for (auto j = G.FIRSTOP[G.P[i].right[0]].begin(); j != G.FIRSTOP[G.P[i].right[0]].end(); j++)
{
G.FIRSTOP[G.P[i].left].insert(*j);
}
if (G.P[i].right.size() >= 2)
{
G.FIRSTOP[G.P[i].left].insert(G.P[i].right[1]);
}
}
if (G.FIRSTOP[G.P[i].left].size() > x)
{
flag++;
}
}
}
}
void getLASTOP(grammar &G)//类似与求firstop的方法
{
int flag = 0;
while (flag != 1)
{
flag = 1;
for (int i = 0; i < G.P.size(); i++)
{
int x = G.LASTOP[G.P[i].left].size();
int m = G.P[i].right.size();
if (G.T.find(G.P[i].right[m-1]) != G.T.end())//这里是处理如果产生式倒数第一个是终结符则把这个终结符加入到这个产生式左部的lastop集合里去
{
G.LASTOP[G.P[i].left].insert(G.P[i].right[m-1]);
}
else //把这个产生式右部倒数第一个变量之后的终结符加入到这个产生式左部的lastop集合里去,还要把第一个变量的lastop集合加入到这个产生式左部的lastop集合里去
{
for (auto j = G.LASTOP[G.P[i].right[m-1]].begin(); j != G.LASTOP[G.P[i].right[m-1]].end(); j++)
{
G.LASTOP[G.P[i].left].insert(*j);
}
if (G.P[i].right.size() >= 2)
{
G.LASTOP[G.P[i].left].insert(G.P[i].right[m-2]);
}
}
if (G.LASTOP[G.P[i].left].size() > x)
{
flag++;
}
}
}
}
void getPriority_Relationship_Matrix(grammar &G)
{
for (auto i = G.T.begin(); i != G.T.end(); i++)//先创建这个表
{
Priority_Relationship_Matrix[*i];
for (auto j = G.T.begin(); j != G.T.end(); j++)
{
Priority_Relationship_Matrix[*i][*j];
}
}
for (int i = 0; i < G.P.size(); i++)//直接遍历这个产生式如果有终结符就处理
{
for (int j = 0; j < G.P[i].right.size(); j++)//经过分析大部分都符合这个情况,之后处理可能出现的情况(开头和末尾是终结符,按照这个文法来说不可能出现这种情况)
{
if (G.T.find(G.P[i].right[j]) != G.T.end())//如果此时的这个是终结符
{
if (j + 1 < G.P[i].right.size()&&G.T.find(G.P[i].right[j + 1]) != G.T.end())//如果后面的一个是终结符
{
Priority_Relationship_Matrix[G.P[i].right[j]][G.P[i].right[j + 1]] = "=";
}
else
{
if (j + 1 < G.P[i].right.size())
{
for (auto f = G.FIRSTOP[G.P[i].right[j + 1]].begin(); f != G.FIRSTOP[G.P[i].right[j + 1]].end(); f++)//处理后面是变量的情况
{
Priority_Relationship_Matrix[G.P[i].right[j]][*f] = "<";
}
}
if (j + 2 < G.P[i].right.size() && G.T.find(G.P[i].right[j + 2]) != G.T.end())//如果变量之后是终结符
{
Priority_Relationship_Matrix[G.P[i].right[j]][G.P[i].right[j + 2]] = "=";
}
}
if (j - 1 >= 0 && G.T.find(G.P[i].right[j - 1]) == G.T.end())//如果前面的一个是变量
{
for (auto l = G.LASTOP[G.P[i].right[j - 1]].begin(); l != G.LASTOP[G.P[i].right[j - 1]].end(); l++)//处理前面是变量的情况
{
Priority_Relationship_Matrix[*l][G.P[i].right[j]] = ">";
}
}
}
}
Priority_Relationship_Matrix["#"]["#"] = "停止";
/*
if (G.T.find(G.P[i].right[0]) != G.T.end()&& G.P[i].right.size()>=2)//如果第一个是终结符
{
for (auto f = G.FIRSTOP[G.P[i].right[1]].begin(); f != G.FIRSTOP[G.P[i].right[1]].end(); f++)//处理后面是变量的情况
{
Priority_Relationship_Matrix[G.P[i].right[0]][*f] = "<";
}
}
if (G.T.find(G.P[i].right[G.P[i].right.size() - 1]) != G.T.end()&& G.P[i].right.size() >= 2)//如果最后一个是终结符
{
for (auto l = G.LASTOP[G.P[i].right[G.P[i].right.size() - 2]].begin(); l != G.LASTOP[G.P[i].right[G.P[i].right.size() - 2]].end(); l++)//处理前面是变量的情况
{
Priority_Relationship_Matrix[*l][G.P[i].right[G.P[i].right.size() - 1]] = ">";
}
}
*/
}
}
void showPriority_Relationship_Matrix()
{
cout << "\n优先关系矩阵为:" << endl;
for (auto j = (Priority_Relationship_Matrix.begin())->second.begin();j!= (Priority_Relationship_Matrix.begin())->second.end();j++)
{
cout << "\t" << j->first;
}
cout << endl;
for (auto i = Priority_Relationship_Matrix.begin(); i != Priority_Relationship_Matrix.end(); i++)
{
cout << i->first<<"\t";
for (auto j = i->second.begin(); j != i->second.end(); j++)
{
cout << Priority_Relationship_Matrix[i->first][j->first]<<"\t";
}
cout << endl;
}
}
void split_sentence(string s, grammar G, vector<string>& sentence)
{
int flag = 0;
while (flag != 1)
{
flag = 1;
int x = s.size();
for (auto j = G.V.begin(); j != G.V.end(); j++)//先用变量集合去匹配
{
string v = *j;
if (v.size() > s.size())//如果此时变量长度大于字符长度了就匹配下一个变量
{
continue;
}
string prfv = s.substr(s.size() - v.size(), v.size());
if (v == prfv)
{
sentence.insert(sentence.begin(), v);
s.erase(s.size() - v.size());
}
}
for (auto j = G.T.begin(); j != G.T.end(); j++)//再用终结符集合去匹配
{
string t = *j;
if (t.size() > s.size())//如果此时终结符长度大于字符长度了就匹配下一个终结符
{
continue;
}
string prft = s.substr(s.size() - t.size(), t.size());
if (t == prft)
{
sentence.insert(sentence.begin(), t);
s.erase(s.size() - t.size());
}
}
if (s.size() < x)
{
flag++;
}
}
sentence.push_back("#");
if (s.size() > 0)
{
cout << "产生式中出现了不是变量也不是终结符的变量";
exit(0);
}
/*
for (int i = 0; i < sentence.size(); i++)
{
cout << sentence[i]<<"$";
}
*/
}
void showanalysis(int i,vector<string>&s,string &Priority_relationship,string &id,vector<string> &input)
{
cout << i << " \t";
cout <<"" << setw(8);
for (int i = 0; i < s.size(); i++)
{
cout << s[i];
}
cout <<"\t"<<setw(8)<< Priority_relationship << "\t\t" << id << "\t\t";
for (int i = 0; i < input.size(); i++)
{
cout << input[i];
}
cout << "\n";
}
void analysis(vector<string>&setence,grammar&G)
{
cout <<"步骤\t 栈\t 优先关系\t 当前输入字符R\t输入字符串" << endl;
vector<string>an;
an.push_back("#");
int number = 0;
string R = setence[0];
setence.erase(setence.begin() + 0);
while (1)
{
int i = an.size() - 1;
while (i > 0)
{
if (G.T.find(an[i]) != G.T.end())
{
break;
}
i--;
}
if (R == "#" && an[i] == "#")
{
break;
}
showanalysis(number, an, Priority_Relationship_Matrix[an[i]][R], R, setence);
while(Priority_Relationship_Matrix[an[i]][R] == ">")
{
string Q=an[i];
int j = i - 1;
while(j >= 0 && G.T.find(an[j])==G.T.end())
{
j--;
}
while (j>=0 && Priority_Relationship_Matrix[an[j]][Q] != "<")
{
if (Priority_Relationship_Matrix[an[j]][Q] == "=")
{
Q = an[j];
j--;
}
while (j>=0 && G.T.find(an[j]) == G.T.end() )
{
j--;
}
}
while (an.size() - 1 > j)
{
an.pop_back();
}
i = j;
an.push_back("N");
number++;
showanalysis(number, an, Priority_Relationship_Matrix[an[i]][R], R, setence);
}
if(Priority_Relationship_Matrix[an[i]][R] == "<" || Priority_Relationship_Matrix[an[i]][R] == "=" || Priority_Relationship_Matrix[an[i]][R]=="停止")
{
an.push_back(R);
}
else
{
cout << "出错,分析的句子不符合此文法!!!";
exit(0);
}
number++;
if (setence.size() > 0)
{
R = setence[0];
setence.erase(setence.begin() + 0);
}
}
}
int main()
{
ifstream infile;
infile.open("production.txt");
grammar G;
string s;
infile >> s;
//cin >> s;
cout << "请先输入终结符(输入stop表示终结符输入完成):\n";
while (s != "stop")
{
G.T.insert(s);
infile >> s;
//cin >> s;
}
cout << "\n请输入产生式(输入stop表示产生式输入完毕):\n";
infile >> s;
//cin >> s;
while (s != "stop")
{
split(G.P, s);
infile >> s;
//cin >> s;
}
getV_PR_S(G);
getFIRSTOP(G);
getLASTOP(G);
showG(G);
getPriority_Relationship_Matrix(G);
showPriority_Relationship_Matrix();
vector<string>setence;
cout << "\n请输入要分析的式子:\n";
infile >> s;
split_sentence(s, G, setence);
analysis(setence, G);
infile.close();
return 0;
}