编译原理 实验4

写在前面

纯粹,为了记录.
以后某一天,回过头来看看.给大学留些痕迹hh.
PS:很多思路也都是学习前辈们的,如果能顺便帮到你,不客气!

强烈推荐学习资源:编译原理(哈工大)
本篇思路完全来自楼上链接,但是代码是纯自己瞎敲出来的。

一开始看这个非递归预测分析,一脸懵逼(比较笨),然后看了几遍教学终于看懂咯,如果你也搞不懂,也可以看看哈工大的教学。

内容

编译原理 实验4
利用c语言实现以下LL(1)文法的分析程序。
对于给定的文法G[E]
E->TE’
E’->+TE’ | ε
T->FT’
T’->*F T’| ε
F->(E) | i
实验步骤
1、建立该文法的分析表;
2、编程实现非递归的预测分析程序。
(注:id简化为i了)

思路

1、分析表
建立该文法的FIRST和FOLLOW集后,得分析表如下:
预测分析表
2、非递归预测分析过程
非递归预测分析代码思路
具体代码将根据上图所示思路实现。
3、具体代码实现
(1)模块划分
具体代码实现,模块划分
函数bao_map( ): 将分析表中的非终结符、输入符号映射到数组对应行、列号;
函数error( ): 报错处理,即不符合文法时退出程序并给出信息;
函数init( ): 进行初始化操作:
1、初始化工作栈 bao_stack
2、输入待分析的串 bao_str
3、初始化分析表 analysis_table[5][6]
函数is_end_sign( ): 判断输入的符号是否是终结符
函数print_situation():打印当前栈的情况和串的剩余输入
函数main():主体,进行非递归预测分析
(2)核心代码
栈顶为终结符情况
栈顶为非终结符且为报错条目
栈顶为非终结符,存在对应的转换
(3)运行结果
输入样例i+i*i
错误样例i*i++

源代码

#include <iostream>
#include <string>
#include <vector>

using namespace std;

vector <string> bao_stack;		//栈,栈底为结束符'$'
string bao_str;					//串的剩余输入,尾部需增加结束符'$'
string analysis_table[5][6];	//预测分析表,注:id简化为i,E'改为e,T'改为t
int idx = 0;	//串的指针,当前指向第一个输入符号

/********************************************
* 功能:报错处理
* 输入参数:
* 返回类型:
* 说明:
*********************************************/
void error() {
	cout << endl << "输入串不符合该文法定义!" << endl;
	cout << "程序已退出..." << endl;
	exit(0);
}

/********************************************
* 功能:将分析表中的非终结符、输入符号映射到数组对应行、列号
* 输入参数:非终结符E E' T T' F 终结符id + * ( ) $
* 返回类型:int
* 说明:自定义的map...虽然看起来挺low的hhhh
*********************************************/
int bao_map(string str) {
	int res = 2;

	//非终结符对应的行号
	if (str == "E") {
		res = 0;
	} else if (str == "e") {
		res = 1;
	} else if (str == "T") {
		res = 2;
	} else if (str == "t") {
		res = 3;
	} else if (str == "F") {
		res = 4;
	}
	//输入符号对应的列号
	else if (str == "i") {
		res = 0;
	} else if (str == "+") {
		res = 1;
	} else if (str == "*") {
		res = 2;
	} else if (str == "(") {
		res = 3;
	} else if (str == ")") {
		res = 4;
	} else if (str == "$") {
		res = 5;
	}

	return res;
}

/********************************************
* 功能:
	1、初始化工作栈 bao_stack:
		[E $]
		注:栈底在右边

	2、输入待分析的串 bao_str
		例如:i+i*i
		[i+i*i$]

	3、初始化分析表 analysis_table[5][6]

* 输入参数:无
* 返回类型:void
* 说明:初始化操作
*********************************************/
void init() {
	//初始化工作栈
	bao_stack.push_back("$");
	bao_stack.push_back("E");

	//输入待分析的串,末尾补结束符$
	cin >> bao_str;
	bao_str += "$";
	idx = 0;

	//初始化分析表,PS:就是把该文法的分析表抄进去
	//对应输入符号处理为空的做报错处理:如非终结符E遇到'+'
	for (int i = 0; i < 5; i ++ ) {
		for (int j = 0; j < 6; j ++ ) {
			analysis_table[i][j]  = "ERROR"; //暂且将全部置为错误情况
		}
	}
	//非终结符E对应输入情况
	analysis_table[bao_map("E")][bao_map("i")] = "Te";
	analysis_table[bao_map("E")][bao_map("(")] = "Te";
	//E'
	analysis_table[bao_map("e")][bao_map("+")] = "+Te";
	analysis_table[bao_map("e")][bao_map(")")] = "NULL";
	analysis_table[bao_map("e")][bao_map("$")] = "NULL";
	//T
	analysis_table[bao_map("T")][bao_map("i")] = "Ft";
	analysis_table[bao_map("T")][bao_map("(")] = "Ft";
	//T'
	analysis_table[bao_map("t")][bao_map("+")] = "NULL";
	analysis_table[bao_map("t")][bao_map("*")] = "*Ft";
	analysis_table[bao_map("t")][bao_map(")")] = "NULL";
	analysis_table[bao_map("t")][bao_map("$")] = "NULL";
	//F
	analysis_table[bao_map("F")][bao_map("i")] = "i";
	analysis_table[bao_map("F")][bao_map("(")] = "(E)";

}

/********************************************
* 功能:判断输入的符号是否是终结符
* 输入参数:文法中的终结符
* 返回类型:bool
* 说明:true、false
*********************************************/
bool is_end_sign(string s) {
	if (s == "i" || s == "+" || s == "*" || s == "(" || s == ")")
		return true;
	return false;
}

/********************************************
* 功能:打印当前栈的情况和串的剩余输入
* 输入参数:
* 返回类型:
* 说明:
*********************************************/
void print_situation() {
	//栈当前情况
	for (int i = bao_stack.size() - 1; i >= 0; i -- ) {
		if (bao_stack[i] == "e") {
			cout << "E'";
		} else if (bao_stack[i] == "t") {
			cout << "T'";
		}  else {
			cout << bao_stack[i];
		}
	}
	cout.width(18 - bao_stack.size());	//对齐哟
	cout << " ";
	//输入串剩余输入
	for (int i = idx; i < bao_str.size(); i ++ ) {
		cout << bao_str[i];
	}
	cout.width(18 - bao_stack.size());	//对齐哟
	cout << " ";
}

int main() {

	init();	//初始化

//	//分析表输出测试
//	for (int i = 0; i < 5; i ++ ) {
//		for (int j = 0; j < 6; j ++ ) {
//			cout.width(12); //对齐
//			cout << analysis_table[i][j];
//		}
//		cout << endl;
//	}
	cout << "栈               "  << "剩余输入                " << "           输出" << endl;
	while (bao_stack.back() != "$") {	//栈非空

		string X = bao_stack.back(), a;
		a.assign(bao_str, idx, 1);
		print_situation();

		/*栈顶是终结符的情况*/
		//若栈顶是一个终结符,且等于串中当前指向的符号
		if (is_end_sign(X) && X == a) {
//			cout << "标记1" << endl;
			bao_stack.pop_back();	//弹出栈顶
			idx ++ ; 				//当前输入匹配完成,读取串中下一个输入
		}
		//若栈顶是一个终结符号,但不等于串中当前指向的符号
		else if (is_end_sign(X)) {
//			cout << "标记2" << endl;
			error();
		}

		/*栈顶是非终结符的情况*/
		//若预测分析表中是一个报错条目,即 初始化时的"ERROR"
		else if (analysis_table[bao_map(X)][bao_map(a)] == "ERROR") {
//			cout << "标记3" << endl;
			error();
		}
		//预测分析法存在其对应的转换
		else {

			//输出对应产生式
			cout.width(12);
			string out_buf = X + "->" + analysis_table[bao_map(X)][bao_map(a)];
			for (int i = 0; i < out_buf.size(); i ++ ) {
				if (out_buf[i] == 'e') {
					cout << "E'";
				} else if (out_buf[i] == 't') {
					cout << "T'";
				}  else {
					cout << out_buf[i];
				}
			}
			cout << endl;

			//弹出栈顶
			bao_stack.pop_back();

			//将对应产生式入栈,注意要逆序进栈,
			//例如:F->TE',进栈顺序是E'、T
			string tmp = analysis_table[bao_map(X)][bao_map(a)];
			if (tmp == "NULL")	//替换为空串的情况,直接继续
				continue;
			for (int i = tmp.size() - 1; i >= 0; i -- ) {
				string buf;
				buf.assign(tmp, i, 1);
				bao_stack.push_back(buf);
			}
		}
		cout << endl;
	}
	cout << "##    输入串符合该文法!" << endl;
	return 0;
}
//i+i*i

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值