语法分析器(c++)

                                 实验二  语法分析(算术表达式的扩充)

前景提示:

(本次代码实现了由分析项目簇和转换关系之前的所有步骤,后面的没搞(拿来写实验已经够用了),以后闲的没事干再搞,根据需要完善文法初始化函数便可)

一、实验目的:

掌握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. 构造分析表:

给出的文法必须是无二义性文法。(所以第一步应该是消除文法二义性)

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)---------不搞了,摆了!

  • 2
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值