实验二 语法分析(算术表达式的扩充)
前景提示:
(本次代码实现了由分析项目簇和转换关系之前的所有步骤,后面的没搞(拿来写实验已经够用了),以后闲的没事干再搞,根据需要完善文法初始化函数便可)
一、实验目的:
掌握LR分析表的设计方法和语义加工程序的扩充
二、实验要求
参照算术表达式LR分析表的设计方法,设计扩充后的算术表达式LR分析表,并对原语义加工程序修改,加入新添的内容。
三、实验内容
算术表达式文法扩充如下:
E→E+E| E-E|E*E |E/E| (E) | I
试根据该文法重新设计LR分析表,并修改语义加工程序,最后验证修改的结果。
四、分析(代码在最后面):
存储文法的结构:
struct Grammar//文法开始符略 { set<string> Vt; //存放终结符 set<string> Vn; //存放非终结符 vector<pair<string, string>> Infer; //产生式 }; |
文法的初始化函数:
void init_grammar(Grammar& gra) |
- 构造分析表:
给出的文法必须是无二义性文法。(所以第一步应该是消除文法二义性)
1)、构造拓广文法:
相应函数:
Grammar getAugGra(const Grammar& gra);//将给出的文法写成拓广文法G' |
生成:
原文法:
相应的拓广文法:
2)、列出对应的所有项目:
相应函数:
vector<pair<string, string>> get_projects(const Grammar& gra);//产生所有项目 |
3)、构造项目闭包:
相应函数:
vector<pair<string, string>> get_closure(const vector<pair<string, string>>& I, const Grammar& gra);//由项目集产生项目集闭包 |
E’ -> E 的闭包:
4)、Goto函数:
vector<pair<string, string>> Goto(const Grammar& gra, const vector<pair<string, string>>& I, const string& flag); |
5)、由closure 和 goto 产生项目集规范族:
相应函数:
vector< vector<pair<string, string>>> get_all_closure(const Grammar& gra, const vector<pair<string, string>>& S, map<pair<int, string>, int>& table);//产生项目集规范族,并记下所有Goto 关系 |
所有的项目集闭包:(出现有移入规约冲突)
相应的转换关系:
五、源代码:
// 编译原理实验二.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <set>
#include <map>
#include <vector>
using namespace std;
struct Grammar//文法开始符略
{
set<string> Vt; //存放终结符
set<string> Vn; //存放非终结符
vector<pair<string, string>> Infer; //产生式
};
void init_grammar(Grammar& gra); //初始化文法
void printGrammar(const Grammar& gra);
void print_project(const vector<pair<string, string>>& I);
Grammar getAugGra(const Grammar& gra);//将给出的文法写成拓广文法G'
vector<pair<string, string>> get_projects(const Grammar& gra);//产生所有项目
vector<pair<string, string>> get_closure(const vector<pair<string, string>>& I, const Grammar& gra);//由项目集产生项目集闭包
vector<pair<string, string>> Goto(const Grammar& gra, const vector<pair<string, string>>& I, const string& flag);
vector< vector<pair<string, string>>> get_all_closure(const Grammar& gra, const vector<pair<string, string>>& S, map<pair<int, string>, int>& table);//产生项目集规范族,并记下所有Goto 关系
map<pair<int, string>, int> LR_0(Grammar gra); //为了方便调试,将建表分为两部操作
//map<pair<int, string>, string> LR_0(map<pair<int, string>, int> table, vector< vector<pair<string, string>>> allclosure);
int main()
{
//给出无二义性文法
Grammar gra;
init_grammar(gra);
//产生相应的增广文法
gra = getAugGra(gra);
//LR(0)
auto table = LR_0(gra);
cout << "\n转换关系:" << endl;
for (map<pair<int, string>, int>::iterator iter = table.begin(); iter != table.end(); iter++)
{
cout << "[ " << iter->first.first << ", " << iter->first.second << " ] -> " << iter->second << endl;
}
}
void init_grammar(Grammar& gra)
{
//gra.Vt.insert("a");
//gra.Vt.insert("b");
//gra.Vt.insert("c");
//gra.Vt.insert("d");
//gra.Vn.insert("E");
//gra.Vn.insert("A");
//gra.Vn.insert("B");
//gra.Infer.push_back(make_pair("E", "aA|bB"));
//gra.Infer.push_back(make_pair("A", "cA|d"));
//gra.Infer.push_back(make_pair("B", "cB|d"));
gra.Vt.insert("+");
gra.Vt.insert("-");
gra.Vt.insert("*");
gra.Vt.insert("/");
gra.Vt.insert("(");
gra.Vt.insert(")");
gra.Vt.insert("i");
gra.Vn.insert("E");
gra.Infer.push_back(make_pair("E", "E+E|E-E|E*E|E/E|(E)|i"));
}
void printGrammar(const Grammar& gra)
{
cout << "终结符(Vt):" << endl;
for (set<string>::iterator iter = gra.Vt.begin(); iter != gra.Vt.end(); iter++)
cout << *iter << " ";
cout << "\n非终结符(Vn):" << endl;
for (set<string>::iterator iter = gra.Vn.begin(); iter != gra.Vn.end(); iter++)
cout << *iter << " ";
cout << "\n产生式:" << endl;
auto size = gra.Infer.size();
for (int i = 0; i < size; i++)
cout << "\t" << gra.Infer[i].first << " -> " << gra.Infer[i].second << endl;
}
void print_project(const vector<pair<string, string>>& I)
{
auto size = I.size();
for (int i = 0; i < size; i++)
{
cout << I[i].first << " -> " << I[i].second << endl;
}
}
//将给出的文法写成拓广文法G'
Grammar getAugGra(const Grammar& gra)
{
Grammar newGra;
set<string> newVn;
vector<pair<string, string>> newInfer;
newInfer.push_back(make_pair("", "")); //保留一个位置作为入口
auto size = gra.Infer.size();
for (int i = 0; i < size; i++)
{
auto flag = gra.Infer[i].second.find('|');
if (flag == string::npos)
{
auto first = gra.Infer[i].first;
auto second = gra.Infer[i].second;
newInfer.push_back(make_pair(first, second));
continue;
}
else
{
auto temp = gra.Infer[i].second;
auto len = temp.size();
string first;
string second;
for (int j = 0; j < len;)
{
first = gra.Infer[i].first;
second.assign(temp, j, flag - j);
newInfer.push_back(make_pair(first, second));
j = flag + 1;
flag = temp.find('|', j);
if (flag == string::npos)
{
flag = len;
second.assign(temp, j, flag - j);
newInfer.push_back(make_pair(first, second));
break;
}
}
}
}
auto first = newInfer[1].first + "'";
auto second = newInfer[1].first;
newInfer[0] = make_pair(first, second);
size = newInfer.size();
for (int i = 0; i < size; i++)//找非终结符
newVn.insert(newInfer[i].first);
newGra.Infer = newInfer;
newGra.Vn = newVn;
newGra.Vt = gra.Vt;
return newGra;
}
//产生所有项目
vector<pair<string, string>> get_projects(const Grammar& gra)
{
vector<pair<string, string>> I;//项目集
auto size = gra.Infer.size();
for (int i = 0; i < size; i++)
{
auto first = gra.Infer[i].first;
auto second = gra.Infer[i].second;
string elem;
auto len = second.size();
for (int j = 0; j < len + 1; j++)
{
auto temp = second;
temp.insert(j, ".");
I.push_back(make_pair(first, temp));
}
}
return I;
}
//由项目集产生项目集闭包
vector<pair<string, string>> get_closure(const vector<pair<string, string>>& I, const Grammar& gra)
{
vector<pair<string, string>> closure = I;//项目集本身属于其闭包
auto size = closure.size();
string first;//存储.后面的第一个符号
for (int i = 0; i < size; i++)
{
auto pos = closure[i].second.find(".");
if (pos == string::npos)
{
cout << "所给项目集有误!" << endl;
cout << closure[i].first << " -> " << closure[i].second << endl;
return closure;
}
auto ch = closure[i].second[pos + 1]; //找 .后面的是否为非终结符(pos+1 永远不会越界)
first.push_back(ch);
if (gra.Vn.find(first) == gra.Vn.end())//不是则进行下一轮
{
first.clear();//清空 first
continue;
}
auto len = gra.Infer.size();
for (int i = 0; i < len; i++)
{
if (first == gra.Infer[i].first)
{
auto second = gra.Infer[i].second;
second.insert(0, ".");
bool flag = 0;
for (int j = 0; j < size; j++)
{
if (second == closure[j].second) //如果项目已包含,则不需要加进去
{
flag = 1;
break;
}
}
if (flag == 0)
{
closure.push_back(make_pair(first, second));
}
}
}
first.clear();//清空 first
size = closure.size();
}
return closure;
}
vector<pair<string, string>> Goto(const Grammar& gra, const vector<pair<string, string>>& I, const string& flag)
{
vector<pair<string, string>> J; //下一跳闭包
auto size = I.size();
for (int i = 0; i < size; i++)
{
auto pos = I[i].second.find(".");
if (pos == string::npos)
{
cout << "给出的项目集闭包有误!" << endl;//这里用抛出错误处理会更好
cout << I[i].first << " -> " << I[i].second << endl;
return J;
}
else
{
auto ch = I[i].second[pos + 1];
if (ch == '\0')
continue;
string temp;
temp.push_back(ch);
if (temp != flag)
continue;
else
{
auto first = I[i].first;
auto second = I[i].second;
second[pos] = second[pos + 1];
second[pos + 1] = '.';
J.push_back(make_pair(first, second));
}
}
}
//构建好J 后,构建J 的闭包
auto T = J;
J = get_closure(T, gra);
return J;
}
//产生项目集规范族,并记下所有Goto 关系
vector< vector<pair<string, string>>> get_all_closure(const Grammar& gra, const vector<pair<string, string>>& S, map<pair<int, string>, int>& table)
{
vector< vector<pair<string, string>>> allClosure;
allClosure.push_back(S);
auto size = allClosure.size();
for (int i = 0; i < size; i++)
{
set<string> flag; //存储下一跳标志,集合存储,无需考虑是否重复
auto len = allClosure[i].size();
for (int j = 0; j < len; j++)
{
auto pos = allClosure[i][j].second.find(".");
if (pos == string::npos)
{
cout << "所给项目集有误!" << endl;
cout << allClosure[i][j].first << " -> " << allClosure[i][j].second << endl;
return allClosure;
}
else
{
auto ch = allClosure[i][j].second[pos + 1];
if (ch == '\0')//如果原点 . 在最后,则不需要加入集合
continue;
string str;
str.push_back(ch);
flag.insert(str);
}
}
for (set<string>::iterator iter = flag.begin(); iter != flag.end(); iter++)
{
auto closure = Goto(gra, allClosure[i], *iter);
if (closure.size() == 0)
continue;
else
{
bool stop = 0;
for (int k = 0; k < size; k++)
{
if (allClosure[k] == closure)
{
table.insert(make_pair(make_pair(i, *iter), k));//Table
stop = 1;
break;
}
}
if (stop == 1)
continue;
allClosure.push_back(closure);
table.insert(make_pair(make_pair(i, *iter), allClosure.size() - 1));
}
}
size = allClosure.size();
}
return allClosure;
}
map<pair<int, string>, int> LR_0(Grammar gra)
{
cout << "\n语法为:" << endl;
printGrammar(gra);
//cout << "\n所有项目:" << endl;
//print_project(get_projects(gra)); //打印所有项目
auto first = gra.Infer[0].first;
auto second = gra.Infer[0].second;
second.insert(0, ".");
vector<pair<string, string>> START;
START.push_back(make_pair(first, second)); //构造开始项目集
auto S = get_closure(START, gra);
//cout << "I0 项目:" << endl;
//print_project(S);
//产生 Goto 关系表
map<pair<int, string>, int> table;
auto allClosure = get_all_closure(gra, S, table);
cout << "项目集规范族:" << endl;
auto size = allClosure.size();
for (int i = 0; i < size; i++)
{
cout << "\nI_" << i << ":" << endl;
print_project(allClosure[i]);
}
//LR_0(table, allClosure);
return table;
}
//map<pair<int, string>, string> LR_0(map<pair<int, string>, int> table, vector< vector<pair<string, string>>> allclosure)
//{
// map<pair<int, string>, string> newTable;
// //1. 找出规约项
// set<int> pro;
// auto size = allclosure.size();
// for (int i = 0; i < size; i++)
// {
// auto in_size = allclosure[i].size();
// bool flag = 1;
// for (int j = 0; j < in_size; j++)
// {
// if (allclosure[i][j].second[(allclosure[i][j].second.find(".") + 1)] != '\0')//如果出现原点后不是 '\0'的项,说明其不是规约项集
// {
// flag = 0;
// break;
// }
// }
// if (flag == 1)
// pro.insert(i);
// }
//
// return newTable;
//}
最后由转换关系和项目集闭包构建分析表:
根据需要可构建LR(0), LR(1), SLR(1)---------不搞了,摆了!