前面两次我们完成了对于固定的文法进行分析和从txt文件中生成预测分析表。下面我们改动第一次文件中本来应该可变的部分。
首先,我们修改关于分析表的一些函数,例如寻找产生式、寻找终结符的索引……然后我们进行一些优化,认为分析栈顶元素和剩余串时只有匹配和不匹配进行推导两种情况,并分别处理。最后,对于多于一个字符的非终结符进行处理。
#include"FileExchanger.h"
#include<stack>
FileExchanger fe;
bool invertStack(stack<string> &one_stack)
{
if (one_stack.empty())//如果栈是空的不进行倒置
{
return false;
}
else
{
//初始化一个栈来储存倒置后的栈
stack<string> invert;
while (!one_stack.empty())
{
invert.push(one_stack.top());
one_stack.pop();
}
//赋值回去
one_stack = invert;
return true;
}
}
void displayStack(stack<string> one_stack)//此处为值传递,不会改变原来的栈,用于栈的倒叙输出
{
invertStack(one_stack);
while (!one_stack.empty())
{
cout << one_stack.top();
one_stack.pop();
}
cout << " ";
}
string configureProduction(stack<string> const &analyse, int char_index)
{
int line = 0;
//确定栈顶非终结符所在的行号
for (int i =1; i < fe.getLineNumber(); i++)
{
if (analyse.top()==fe.analyse_sheet[i][0])
{
line = i;
}
}
//如果非空,返回规则
if (fe.analyse_sheet[line][char_index]!="null")
{
return fe.analyse_sheet[line][char_index];
}
return "error";
}
bool isMatching(stack<string> const &analyse, char odd_first_char)
{
if (analyse.top()[0] == odd_first_char)
{
return true;
}
return false;
}
int findTIndex(char some)//查找终结符在分析表中的列号
{
//temp完成字符向字符串的转换
string temp="a";
temp[0] = some;
for (int i = 1; i < fe.getColumnNumber(); i++)
{
if (fe.analyse_sheet[0][i]==temp)
{
return i;
}
}
return -1;
}
bool display(stack<string> &analyse, string &odd)
{
static int step = 1;
if (isMatching(analyse, odd[0]))
{
cout << step << " ";
displayStack(analyse);
cout << odd << " ";
if (odd[0] == '#')
{
cout << "接受" << endl;
return false;
}
cout << "“" << odd[0] << "”匹配" << endl;
odd = odd.substr(1, odd.length() - 1);//if match odd string decrease
analyse.pop();
step++;
return true;
}
else
{
//输出步骤
cout << step << " ";
//输出分析栈
displayStack(analyse);
//输出剩余串
cout << odd << " ";
//输出推倒所用产生式
int char_index = findTIndex(odd[0]);
if (char_index == -1)
{
return false;
}
string production = configureProduction(analyse, char_index);
cout << analyse.top() << "->" << production << endl;
if (production == "error")
{
return false;
}
step++;
if (production == "ε")
{
analyse.pop();
return true;
}
analyse.pop();//弹出栈顶元素
while (production.size()!=1)
{
string temp_one = production.substr(production.size() - 1, production.size() - 1);//获取最后一个字符
string temp_two = production.substr(production.size() - 2, production.size() - 1);//获取最后两个字符
//如果有非终结符是由三个以上字符组成只需在此处在添加处理
bool c = false;
for (int i = 1; i < fe.getLineNumber(); i++)
{
if (temp_one==fe.analyse_sheet[i][0])
{
analyse.push(temp_one);
production = production.substr(0, production.length() - 1);
c = true;
}
}
if (c)
{
continue;
}
for (int i = 1; i < fe.getLineNumber(); i++)
{
if (temp_two == fe.analyse_sheet[i][0])
{
analyse.push(temp_two);
production = production.substr(0, production.length() - 2);
}
}
}
analyse.push(production);
}
}
int main()
{
//产生预测分析表
fe.vInLine();//初始化终结符数组和非终结符数组
fe.buildSheet();//初始化整个预测分析表
cout << "请输入符号串,注意,以#号结尾"<<endl;
string inputstring;
cin >> inputstring;
//声明一个分析栈
stack<string> analyse_s;
analyse_s.push("#");
string identifer = fe.analyse_sheet[1][0];
analyse_s.push(identifer);
//声明剩余串
string odd = inputstring;
cout << "步骤 " << "分析栈 " << "剩余输入串 " << "推导所用产生式或匹配" << endl;
//the first step is succeed
while (!odd.empty() && display(analyse_s, odd));
system("pause");
return 0;
}
以下是所有代码的云共享:
http://yunpan.cn/c33zRqaRCUyyV 访问密码 e648