【问题描述】
给定以下文法G[E]:
E->TE′
E′->+TE′| ε \varepsilon ε
T ->FT′
T′->*FT′| ε \varepsilon ε
F -> a | (E)
构建LL(1)预测分析表,并用C++编程实现LL(1)语法分析器
【输入形式】
一个句子
【输出形式】
若句子语法正确,输出"Syntax analysis is right"
若语法语法错误,输出"Error on syntax analysis"
注:输出不包括引号
【样例输入】
a+a*a
【样例输出】
Syntax analysis is right
【样例说明】
【评分标准】
根据通过的测试数据个数评分
思路
最重要的是构造分析表
发现题目所给的文法跟课本上的文法相似,预测分析表已给出。所以只需要选择好恰当的数据结构用来存储非终结符集、终结符集、预测分析表。
在该实验中我使用了Vector来存储Vt和Vn,用vector 类型的数组即vector predict[10];来二维的存储预测分析表。用map<char, int> 进行终结符集、非终结符集的映射,这样做的目的是为了用字母索引下标。完成好上述数据结构后,用栈结构来模拟文法分析过程即可。
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <stack>
using namespace std;
vector<char> C;
vector<string> predict[10];
map<char, int> Vt2num; // 非终结符映射成数字下标。
map<char, int> Vn2num; // 终结符映射成数字下标,通过访问字符即可得到对应的数。
vector<char> Vt = {
'E','M','T','N','F' };
vector<char> Vn = {
'a','+','*','(',')','#' };
stack<char> s;
void PredictTable()
{
int k = 0;
for (vector<char>::iterator it = Vt.begin();it != Vt.end(); it++)
{
Vt2num.insert(pair<char,int>(*it, k));
k++;
}
k = 0;
for (vector<char>::iterator it = Vn.begin();it != Vn.end(); it++)
{
Vn2num.insert(pair<char, int>(*it, k));
k++;
}
for (int i = 0;i < 5;i++)
{
for (int j = 0;j < 6;j++)
{
predict[i].push_back("NULL");
}
}
// E' -> M
// T' -> N
predict[0][0] = "TM";
predict[0][3] = "TM";
predict[1][1] = "+TM";
predict[1][4] = "0";
predict[1][5] = "0";
predict[2][0] = "FN";
predict[2][3] = "FN";
predict[3][1] = "0";
predict[3][2] = "*FN";
predict[3][4] = "0";
predict[3][5] = "0";
predict[4][0] = "a";
predict[4][3] = "(E)";
}
int main()
{
string str;
cin >> str;
str += '#';
s.push('#');
s.push('E');
//int n = str.length();
PredictTable();
int i = 0;
while(1)
{
char ch = s.top();
int flag = 0;
//栈顶是终结符
for(vector<char>::iterator it = Vn.begin(); it!=Vn.end(); it++)
if ((*it) == ch)
{
if (str[i] == '#' && ch == '#')
{
cout << "Syntax analysis is right";
return 0;
}
if (str[i] == ch)
{
s.pop();
i++;
flag = 1;
break;
}
else
{
cout << "Error on syntax analysis";
return 0;
}
}
//栈顶是非终结符
//找到下标,入栈
if (flag == 1)
continue;
int num1 = Vt2num[ch];
int num2 = Vn2num[str[i]];
s.pop();
if (predict[num1][num2] == "NULL")
{
cout << "Error on syntax analysis";
return 0;
}
int len = predict[num1][num2].length();
for (int k = len - 1;k >= 0; k--)
{
if (predict[num1][num2][k] == '0')
continue;
s.push(predict[num1][num2][k]);
}
}
}