- 实验目的
- 了解LL(1)预测分析法适用的文法特征。
- 了解LL(1)预测分析法基本结构。
- 理解LL(1)预测分析法基本原理,编程实现,并验证。
- 实验预备知识
- 理解表驱动的LL(1)预测分析法中预测表的求解和作用。
- 参考配套教材《编译原理》预测分析法原理与方法。
#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>>FIRST;//FIRST集合
unordered_map<variable, set<terminal>>FLLOW;//FLLOW集合
}grammar;
unordered_map<variable, unordered_map<terminal, vector<string>>>foresee_table;//预测分析表
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 << "\nFIRST集:";
cout << endl;
for (auto i = G.FIRST.begin(); i != G.FIRST.end(); i++)
{
cout << "\tFIRST(" << 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 << "\nFOLLOW集:";
cout << endl;
for (auto i = G.FLLOW.begin(); i != G.FLLOW.end(); i++)
{
cout << "\tFOLLOW(" << i->first << "):\t{ ";
auto s = i->second.begin();
if(s!= i->second.end())
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;
}
int getFIRST(grammar& G)
{
//1.显式规则1
int n = G.P.size();
for (int i = 0; i < n; i++)
{
if (G.P[i].right.size() == 1 && G.P[i].right[0] == "$")
{
G.FIRST[G.P[i].left].insert("$");
}
}
//2.显式规则2
for (int i = 0; i < n; i++)
{
string s = G.P[i].right[0];
if (G.T.find(s) != G.T.end())
{
G.FIRST[G.P[i].left].insert(s);
}
}
//3.隐式规则1如果右边的第一个是变量的话把变量的first集合去空给first(左部)
int flag = 0;
while (flag != 1)
{
flag = 1;
for (int i = 0; i < n; i++)
{
int num = G.FIRST[G.P[i].left].size();
string s = G.P[i].right[0];
if (G.V.find(s) != G.V.end())
{
set<terminal>se(G.FIRST[s]);
se.erase("$");
for (auto j = se.begin(); j != se.end(); j++)
{
G.FIRST[G.P[i].left].insert(*j);
}
}
if (G.FIRST[G.P[i].left].size() > num)
{
flag++;
}
}
}
//4.隐式规则2和3
flag = 0;
while (flag != 1)
{
flag = 1;
for (int i = 0; i < n; i++)
{
int num = G.FIRST[G.P[i].left].size();
int m = G.P[i].right.size();
int j = 0;
for (; j < m; j++)
{
string s = G.P[i].right[j];
if (G.V.find(s) != G.V.end() && G.FIRST[s].find("$") != G.FIRST[s].end())//这里是变量能推出来空
{
set<terminal>se(G.FIRST[s]);
se.erase("$");
for (auto j = se.begin(); j != se.end(); j++)
{
G.FIRST[G.P[i].left].insert(*j);
}
}
else if (G.V.find(s) != G.V.end())//这里是变量不能推出来空
{
set<terminal>se(G.FIRST[s]);
for (auto j = se.begin(); j != se.end(); j++)
{
G.FIRST[G.P[i].left].insert(*j);
}
break;
}
else//这里是终结符的FIRST集
{
G.FIRST[G.P[i].left].insert(s);
break;
}
}
if (j == m)
{
G.FIRST[G.P[i].left].insert("$");
}
if (G.FIRST[G.P[i].left].size() > num)
{
flag++;
}
}
}
//所有的终结符的first集是自己
for (auto i = G.T.begin(); i != G.T.end(); i++)
{
G.FIRST[*i].insert(*i);
}
return 0;
}
int getFLLOW(grammar& G)
{
//1.显式规则
G.FLLOW[G.S].insert("#");
//2.显式规则
for (int i = 0; i < G.P.size(); i++)
{
for (int j = 0; j < G.P[i].right.size() - 1; j++)
{
if (G.V.find(G.P[i].right[j]) != G.V.end() && G.T.find(G.P[i].right[j + 1]) != G.T.end())
{
G.FLLOW[G.P[i].right[j]].insert(G.P[i].right[j + 1]);
j++;
}
}
}
//3.隐式规则
int flag = 0;
while (flag != 1)
{
flag = 1;
vector<int>flag1(G.V.size());
int x = 0;
for (auto vv = G.V.begin(); vv != G.V.end(); vv++, x++)
{
flag1[x] = G.FLLOW[*vv].size();
}
//cout << "***";
//隐式规则1
for (int i = 0; i < G.P.size(); i++)
{
int j = 0;
for (; j < G.P[i].right.size() - 1; j++)
{
string s = G.P[i].right[j];
if (G.V.find(s) != G.V.end())//此时的必须是变量
{
//把下一个字符的first集去空给这个变量的follow集
set<terminal>se(G.FIRST[G.P[i].right[j + 1]]);
if (se.find("$") != se.end())//如果此时后面的量的first集有空$
{
se.erase("$");
for (auto seb = se.begin(); seb != se.end(); seb++)
{
G.FLLOW[s].insert(*seb);
}
set<terminal>se1(G.FLLOW[G.P[i].right[j + 1]]);
for (auto se1b = se1.begin(); se1b != se1.end(); se1b++)
{
G.FLLOW[s].insert(*se1b);
}
}
else
{
se.erase("$");
for (auto seb = se.begin(); seb != se.end(); seb++)
{
G.FLLOW[s].insert(*seb);
}
//break;
}
}
}
if (j == G.P[i].right.size() - 1 && G.V.find(G.P[i].right[j]) != G.V.end())//如果此时已经走到右部末尾了且最后一个还是变量那就要把左部的follow集给这个变量了
{
for (auto f = G.FLLOW[G.P[i].left].begin(); f != G.FLLOW[G.P[i].left].end(); f++)
{
G.FLLOW[G.P[i].right[j]].insert(*f);
}
}
}
x = 0;
for (auto vv = G.V.begin(); vv != G.V.end(); vv++, x++)
{
if (flag1[x] != G.FLLOW[*vv].size())
{
flag++;
break;
}
}
}
return 0;
}
void getforesee_table(grammar G)//开始插入这个表
{
for (auto i = G.V.begin(); i != G.V.end(); i++)
{
foresee_table[*i];
for (auto j = G.T.begin(); j != G.T.end(); j++)
{
if (*j != "$")
{
foresee_table[*i][*j];
}
}
foresee_table[*i]["#"];
}
for (int i = 0; i < G.P.size(); i++)
{
int j;
for (j = 0; j < G.P[i].right.size(); j++)//通过右部分
{
int flag = 0;
for (auto m = G.FIRST[G.P[i].right[j]].begin(); m != G.FIRST[G.P[i].right[j]].end(); m++)//通过右边部分的first集合往里面填写
{
if (*m != "$")
{
for (int s_z = 0; s_z < G.P[i].right.size(); s_z++)//这里是追加右部
{
foresee_table[G.P[i].left][*m].push_back(G.P[i].right[s_z]);
}
}
else
{
flag = 1;
}
}
if (flag == 0)
{
break;
}
}
if (j >= G.P[i].right.size())
{
for (auto m = G.FLLOW[G.P[i].left].begin(); m != G.FLLOW[G.P[i].left].end(); m++)
{
foresee_table[G.P[i].left][*m].push_back("$");
}
}
}
}
void show(grammar G)
{
cout << "\n预测分析表为:" << endl;
for (auto j = G.T.begin(); j != G.T.end(); j++)
{
if (*j != "$")
{
cout << "\t" << *j;
}
}
cout << "\n";
for (auto i = G.V.begin(); i != G.V.end(); i++)
{
foresee_table[*i];
cout << *i << "\t";
for (auto j = G.T.begin(); j != G.T.end(); j++)
{
if (*j != "$")
{
for (int m = 0; m < foresee_table[*i][*j].size(); m++)
{
cout << foresee_table[*i][*j][m];
}
cout << "\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 foresee_analyze(vector<string>sentence,grammar&g)//用传进来的字符串数组完成
{
stack<string>sta;
sta.push("#");
sta.push(g.S);
int i = 0;
string out = "";
cout << "步骤\t\t栈\t\t输入缓存区\t\t输出\n";
while (sta.top() != "#")
{
cout << i << "\t\t";
stack<string>outsta;
while (!sta.empty())
{
outsta.push(sta.top());
sta.pop();
}
while (!outsta.empty())
{
cout << outsta.top();
sta.push(outsta.top());
outsta.pop();
}
cout << "\t\t";
string se = "";
for (int i = 0; i < sentence.size(); i++)
{
se = se + sentence[i];
}
cout << setw(8) << se;
if (out == "")
{
cout << endl;
}
else
{
cout << "\t\t" << out << "\n";
}
out.clear();
string st = sta.top();
sta.pop();
if (st == sentence[0])
{
i++;
sentence.erase(sentence.begin());
continue;
}
if (foresee_table[st][sentence[0]].size() == 0)
{
cout << "此句子不符合本文法";
return ;
}
for (int i = foresee_table[st][sentence[0]].size() - 1; i >= 0; i--)
{
if (foresee_table[st][sentence[0]][i] != "$")
sta.push(foresee_table[st][sentence[0]][i]);
}
out = out + st + "->";
for (int i = 0; i < foresee_table[st][sentence[0]].size(); i++)
{
out = out + foresee_table[st][sentence[0]][i];
}
i++;
}
cout << i << "\t\t";
stack<string>outsta;
while (!sta.empty())
{
outsta.push(sta.top());
sta.pop();
}
while (!outsta.empty())
{
cout << outsta.top();
sta.push(outsta.top());
outsta.pop();
}
cout << "\t\t";
string se = "";
for (int i = 0; i < sentence.size(); i++)
{
se = se + sentence[i];
}
cout << setw(8) << se;
if (out == "")
{
cout << endl;
}
else
{
cout << "\t\t" << out << "\n";
}
}
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);
getFIRST(G);
getFLLOW(G);
showG(G);
getforesee_table(G);
show(G);
vector<string>setence;
cout << "\n请输入要分析的式子:\n";
infile >> s;
split_sentence(s, G, setence);
foresee_analyze(setence,G);
infile.close();
return 0;
}