合肥工业大学编译原理实验二 LL1分析

写在开头

当老师说这个实验最好写成图形界面时,我笑了(滑稽),心想终于可以用到python了,python真香,用python的数据结构可以很方便的表示LL1的某些东西(当然有利也有弊,方便的同时也会有一些坑)。当然Java也牛逼,Java的图形库有些东西用起来比python的还要方便。只是本人当前最熟的就是python。

准备工作

(熟悉python的可以跳过)首先至少得会基础的python语法,图形化界面的一些术语得熟悉,比如控件啊,窗口啊,事件循环啊等等。
这里用到图形库是最简单的python自带库tkinter,个人认为应付这次实验足以,没必要用其他高端的库比如Qt(其实是不熟)。
python版本是3.7,IDE是用的PyCharm专业版,用它还能生成一个简单的类图(没有表示关系的各种箭头)。想用专业版的小伙伴可以出门左拐搜搜怎么破解,或者去学校注册个学生邮箱,用这个邮箱申请个jetbrain账号,然后jetbrain全家桶就能免费使用一年啦。

先看看功能

(1)判断所选文法是否含直接或间接左递归,若有,则消除左递归;
(2)判断该文法是否含最左公因子,若有,提取左公因子并修改文法;
(3)求该文法所有非终结符的FIRST集和FOLLOW集;
(4)判断所选文法是否符合LL(1)文法的三个条件;
(5)由FIRST集和FOLLOW集建立该文法的预测分析表;
(6)利用分析表对该文法的一个句型进行分析;
(7)在图形界面上执行所有操作,并对可能出现的异常进行处理。

干货开始

先贴一个示例文法:
E->TG
G->+TG|-TG|ε
T->FS
S->*FS|/FS|ε
F->(E)|i
后面都以此文法为例。
在一个py文件里,放定义三个类,文法类Grammar,图形界面类LL1GUI,堆栈类Stack。文法类对象作为图形界面类对象的一个变量,堆栈类对象也作为图形界面类的一个变量。先看一个类图:
每个框是一个类,框里横线分割的上半部分是方法,下半部分是变量
总控程序在GUI类里面。程序整体思路是:
打开文法文件->求终结符和非终结符->判断文法是否左递归并修改->求FIRST集和FOLLOW集->判断是否符合LL1文法条件->生成预测分析表->等待输入待分析句型->执行分析。
先看一下初始化界面:程序初始化界面
选择文法后界面:
在这里插入图片描述

核心算法思路

文法表示:用python的字典来表示,以非终结符作为键,产生式组成的列表为值。程序里变量定义为self.grammar。

求FIRST集

书上的FIRST集求法是循环法,一直迭代迭代,反复求,直到所有符号的FIRST集大小不再变化为止。我觉得可能实现起来会有一些麻烦,于是就使用了递归的思路,遍历每个产生式,如果产生式右边第一个字符是非终结符(比如T->FS),就递归的去求它的FIRST集,求完后再看符号F和S的FIRST集里面有没有空字,再给T的FIRST集赋值。
python代码:

# 求一个文法的所有first集,定义成私有方法,只在创建对象时由初始化函数调用
	def __first(self):
		for nT in self.NonTerminater: #先赋值一个空列表
			self.First[nT] = []
		# 后面要用到递归,所以分开两个循环
		for T in self.Terminater: # 终结符的first集就是他自己
			self.First[T] = [T]
		for nT in self.NonTerminater:
			self.__subFirst(nT)
		
	# 求first集的递归子方法
	def __subFirst(self, X):
		tmpSize = len(self.First[X]) # 求之前的大小
		if X in self.Terminater and X not in self.First[X]: #如果X在终结符里, 则X属于first(X)
			self.First[X].append(X)
		else : # else X就不是终结符,对X的每个推导,依次判断推导的字符是什么
			for derivation in self.grammar[X]:
				# 先判断是不是空字,是空字就加入
				if derivation == '':
					if '' not in self.First[X]:
						self.First[X]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值