编译原理-LL1语法分析器(消除左递归+消除回溯)

本文档详细介绍了如何构造和实现LL1语法分析器,包括消除左递归和回溯的过程。实验要求涵盖文法构造、LL(1)分析表的生成、预测分析程序的编写以及文法数据结构的设计。文中还提供了具体的代码实现,展示了消除左递归前后的对比,并给出了两个测试样例的分析过程。
摘要由CSDN通过智能技术生成

编译原理-LL1语法分析器(消除左递归+消除回溯)

实验要求:

要求一

1、 给出文法如下:
G[E]:
E->T|E+T;
T->F|T*F;
F->i|(E);

2、 根据该文法构造相应的LL(1)文法及LL(1)分析表,并为该文法设计预测分析程序,利用C语言或C++语言或Java语言实现;
3、 利用预测分析程序完成下列功能:
1) 手工将测试的表达式写入文本文件,每个表达式写一行,用“;”表示结束;
2) 读入文本文件中的表达式;
3) 调用实验一中的词法分析程序搜索单词;
4) 把单词送入预测分析程序,判断表达式是否正确(是否是给出文法的语言),若错误,应给出错误信息;
5) 完成上述功能,有余力的同学可以进一步完成通过程序实现对非LL(1)文法到LL(1)文法的自动转换

要求二

1、 将一个可转换的非LL(1)文法转换为LL(1)文法,要经过两个阶段,1)消除文法左递归,2)提取左因子,消除回溯。
2、 提取文法左因子算法:
1)对文法G的所有非终结符进行排序
2)按上述顺序对每一个非终结符Pi依次执行:
for( j=1; j< i-1;j++)
将Pj代入Pi的产生式(若可代入的话);
消除关于Pi的直接左递归:
Pi -> Piα|β ,其中β不以Pi开头,则修改产生式为:
Pi —> βPi′
Pi′—> αPi′|ε
3)化简上述所得文法。
3、 提取左因子的算法:
A —> δβ1|δβ2|…|δβn|γ1|γ2|…|γm
(其中,每个γ不以δ开头)
那么,可以把这些产生式改写成
A —> δA′|γ1| γ2…|γm
A′—>β1|β2|…|βn
4、 利用上述算法,实现构造一个LL(1)文法:
1) 读入文法,利用实验二附加资料2的实验要求将文法存入设计的数据结构;
2) 设计函数remove_left_recursion()和remove_left_gene()实现消除左递归和提取左因子算法,分别对文法进行操作,消除文法中的左递归和提出左因子;
3) 整理得到的新文法;
4) 在一个新的文本文件输出文法,文法输出按照一个非终结符号一行,开始符号引出的产生式写在第一行,同一个非终结符号的候选式用“|”分隔的方式输出。

要求三

1、 了解文法定义的4个部分:
G(Vn, Vt, S, P)
Vn 文法的非终结符号集合,在实验中用大写的英文字母表示;
Vt 文法的终结符号集合,在实验中用小写的英文字母表示;
S 开始符号,在实验中是Vn集合中的一个元素;
P 产生式,分左部和右部,左部为非终结符号中的一个,右部为终结符号或非终结符号组成的字符串,如S->ab|c
2、 根据文法各个部分的性质,设计一个合理的数据结构用来表示文法,
1) 若使用C语言编写,则文法可以设计成结构体形式,结构体中应包含上述的4部分,
2) 若使用C++语言编写,则文法可以设计成文法类形式,类中至少含有4个数据成员,分别表示上述4个部分
文法数据结构的具体设计由学生根据自己想法完成,并使用C或C++语言实现设计的数据结构。
3、 利用完成的数据结构完成以下功能:
1) 从文本文件中读入文法(文法事先应写入文本文件);
2) 根据文法产生式的结构,分析出文法的4个部分,分别写入定义好的文法数据结构的相应部分;
3) 整理文法的结构;
4) 在计算机屏幕或者文本框中输出文法,文法输出按照一个非终结符号一行,开始符号引出的产生式写在第一行,同一个非终结符号的候选式用“|”分隔的方式输出。

代码

#include <iostream>
#include <string>
#include <fstream>
#include <set>
#include <map>
#include <iomanip>
#include <stack>
using namespace std;
const int maxnlen = 1e4;
class Grammar {
private:
	set<char>Vn;
	set<char>Vt;
	char S;
	map<char, set<string> > P;
	map<char,set<char> >FIRST;
	map<char,set<char> >FOLLOW;
	map<string, string>Table;
public:
	Grammar(string filename) {
		Vn.clear();
		Vt.clear();
		P.clear();
		FIRST.clear();
		FOLLOW.clear();
		ifstream in(filename);
		if (!in.is_open()) {
			cout << "文法  文件打开失败" << endl;
			exit(1);
		}
		char *buffer = new char[maxnlen];
		in.getline(buffer, maxnlen, '#');
		string temps = "";
		bool is_sethead = 0;
		for (int i = 0; i < strlen(buffer); i++) {
			if (buffer[i] == '\n' || buffer[i] == ' ')continue;
			if (buffer[i] == ';') {
				if (!is_sethead) {
					this->setHead(temps[0]);
					is_sethead = 1;
				}
				this->add(temps)
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值