编译原理实验--实验三 预测分析法判断算术表达式的正确性--Python实现

本文主要是介绍编译原理实验--实验三 预测分析法判断算术表达式的正确性--Python实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、实验目的和要求

二、实验内容

三、实验环境

四、实验步骤

1、语法分析所依据的文法;

2、给出消除左递归及提取左公因子的LL(1)文法;

3、预测分析表

 4、关键代码

五、实验结果与分析


一、实验目的和要求

  1. 理解自顶向下语法分析方法;
  2. 用预测分析技术实现语法分析器;
  3. 熟练掌握预测分析程序的构造方法。

二、实验内容

        算术表达式的文法是G[E]:

E→E+T| E-T | T

T→T*F| T/F | F

F→(E)| i

        用预测分析法按文法G[E]对算术表达式(包括+、-、*、/、(、)的算术表达式)进行语法分析,判断该表达式是否正确。

三、实验环境

处理器     AMD Ryzen 7 5800H with Radeon Graphics3.20 GHz

机带RAM   16.0 GB(13.9 GB可用)

Win10家庭版20H2 X64  

PyCharm 2012.2

Python 3.10

四、实验步骤

1、阅读课本有关章节,将上述算术表达式的文法改造成LL(1)文法G’[E],即消除左递归和提取左公因子;

2、设计出文法G’[E]的预测分析表;

3、按算法4.5(P132)编写预测分析程序。(思考:预测分析程序包括四种动作——推导、匹配、接受、出错,详见P131,这些动作如何实现?)

1、语法分析所依据的文法;

      算术表达式的文法是G[E]:

E→E+T| E-T | T

T→T*F| T/F | F

F→(E)| i

2、给出消除左递归及提取左公因子的LL(1)文法;

将文法G[E]改造为LL(1)文法如下:

G’[E]:

E →  TE’

E’ → +TE’| -TE’|ε

T  →  FT’

T’→  *FT’|/FT’|ε

F  → (E)| i

3、预测分析表

 

 4、关键代码

<简要说明程序中所用到的主要变量、数组的作用,主要函数或过程的功能;给出主要功能实现的关键代码,如推导或匹配动作的实现,并加上适当的注释>

<!--BianYiYuanLiShiYan/yufafenxi_LL1.py-->


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/12/11 9:58
# @Author : LanXiaoFang
# @Site : 
# @File : yufafenxi_LL1.py
# @Software: PyCharmimport cifafenxi_LL1class Stack():  # 定义类def __init__(self):  # 产生一个空的容器self.__list = []def push(self, item):  # 入栈self.__list.append(item)def pop(self):  # 出栈return self.__list.pop()def speek(self):  # 返回栈顶元素return self.__list[-1]def is_empty(self):  # 判断是否已为空return not self.__listdef size(self):  # 返回栈中元素个数return len(self.__list)# 用来存储从txt文件中读取的字符串
aa = " "
# 用来标记字符
pp = 0
# 非终结符表
VN = ["E", "e", "T", "t", "F"]
# 终结符表 l->/ m->% i->id n->num
VT = ['*', 'l', 'm', '+', '-', '(', ')', 'i', 'num', '#']Fa = ["Te", "+Te", "-Te", "", "Ft", "*Ft", "nFt", "mFt", "", "(E)", "i", "num"]F = ["E->", "E'->", "E'->", "E'->", "T->", "T'->", "T'->", "T'->", "T'->", "F->", "F->", "F->"]
# 构造预测分析表,-1表示出错,-2表示该行终结符的follow集合,用于错误处理
analysis_table = [[-2, -2, -2, -2, -2, 0, -1, 0, 0, -1],[-2, -2, -2, 1, 2, -2, 3, -2, -2, 3],[-2, -2, -2, -1, -1, 4, -1, 4, 4, -1],[5, 6, 7, 8, 8, -2, 8, -2, -2, 8],[-2, -2, -1, -1, -1, 9, -1, 10, 11, -2]
]
# 定义栈
stack = Stack()# 判断字符x是否是终结符
def includevt(x):if x in VT:return 1else:return 0# 查找非终结符,终结符 在预测分析表中的坐标,返回坐标对应信息
def includean(x, a):# 非终结符for i in range(len(VN)):if VN[i] == x:break# 终结符for j in range(len(VT)):if VT[j] == a:breakreturn analysis_table[i][j]# 错误处理
def destory():flag = 0flagg = 0# 将 "#"和文法开始符依次压入栈中stack.push('#')# 将第一个非终结符入栈stack.push(VN[0])# 把第一个输入符号读入a, aaglobal ppa = aa[pp]x = ""while x != '#':# print(stack.__dict__.values())if flag == 0:# 把栈顶符号弹出并放入x = stack.pop()flag = 0#  如果a是终结符if includevt(a) == 1:if includevt(x) == 1:if a == x:if a == '#':flagg = 1print(x, "\t\t", a, "\t\t", " 结束")return 1else:print(x, "\t\t", a, "\t\t", " 匹配终结符", x)pp = pp + 1# 将下一输入符号读入aa = aa[pp]else:flag = 1print(x, "\t\t", a, "\t\t", " 出错 ,跳过", a)pp = pp + 1a = aa[pp]elif includean(x, a) >= 0:h = includean(x, a)print(x, "\t\t", a, "\t\t", " 展开非终结符 ", F[h], Fa[h])if Fa[h] in aa:stack.push(Fa[h])else:aF = Fa[h][::-1]for i in range(len(aF)):stack.push(aF[i])elif includean(x, a) == -1:flag = 1print(x, "\t\t", a, "\t\t", " 出错 ,从栈顶弹出", x)x = stack.pop()else:flag = 1print(x, "\t\t", a, "\t\t", " 出错 ,跳过", a)pp = pp + 1a = aa[pp]else:flag = 1print(x, "\t\t", a, "\t\t", " 出错 ,跳过", a)pp = pp + 1a = aa[pp]if flagg == 0:print(x, "\t\t", a, "\t\t", " 结束 \n")aa = cifafenxi_LL1.main()
print("语法分析工程如下 :")
print('-' * 20, '文法如下', '-' * 20)
print("E->TE'")
print("E'->+TE'|-TE'|~")
print("T->FT'")
print("T'->*FT'|/FT'|%FT'|~")
print("F->(E)|id|num")
print("要分析的语句是 :", aa)
print("语法分析工程如下 :")
print("栈顶元素 \t\t 当前单词记号 \t\t 动作 ")
print("-" * 50)
destory()

<!--BianYiYuanLiShiYan/cifafenxi_LL1.py-->

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2021/12/11 9:57
# @Author : LanXiaoFang
# @Site : 
# @File : cifafenxi_LL1.py
# @Software: PyCharmimport reclass Token(object):# 初始化def __init__(this):# 存储分词的列表this.results = []# 行号this.lineno = 1# 关键字this.keywords = ['auto', 'struct', 'if', 'else', 'for', 'do', 'while', 'const','int', 'double', 'float', 'long', 'char', 'short', 'unsigned','switch', 'break', 'defalut', 'continue', 'return', 'void', 'static','auto', 'enum', 'register', 'typeof', 'volatile', 'union', 'extern']'''regex中:*表示从0-, +表示1-, ?表示0-1。对应的需要转义{ 表示限定符表达式开始的地方 \{() 标记一个子表达式的开始和结束位置。子表达式可以获取共以后使用:\( \)r表示原生字符串。'''Keyword = r'(?P<Keyword>(auto){1}|(double){1}|(int){1}|(if){1}|' \r'(#include){1}|(return){1}|(char){1}|(stdio\.h){1}|(const){1})'# 运算符Operator = r'(?P<Operator>\+\+|\+=|\+|--|-=|-|\*|#|\*=|/=|/|%=|%)'# 分隔符/界符Separator = r'(?P<Separator>[,:\{}:)(<>])'# 数字: 例如:1 1.9Number = r'(?P<Number>\d+[.]?\d+)'# 变量名 不能使用关键字命名ID = r'(?P<ID>[a-zA-Z_][a-zA-Z_0-9]*)'# 方法名 {1} 重复n次Method = r'(?P<Method>(main){1}|(printf){1})'# 错误  \S 匹配任意不是空白符的字符# Error = r'(?P<Error>.*\S+)'Error = r'\"(?P<Error>.*)\"'# 注释  ^匹配行的开始 .匹配换行符以外的任意字符 \r回车符 \n换行符Annotation = r'(?P<Annotation>/\*(.|[\r\n])*/|//[^\n]*)'# 进行组装,将上述正则表达式以逻辑的方式进行拼接, 按照一定的逻辑顺序# compile函数用于编译正则表达式,生成一个正则表达式对象this.patterns = re.compile('|'.join([Annotation, Keyword, Method, ID, Number, Separator, Operator, Error]))# 读文件def read_file(this, filename):with open(filename, "r", encoding="UTF-8") as f_input:return [line.strip() for line in f_input]# 结果写入文件def write_file(this, lines, filename='results.txt'):with open(filename, "a") as f_output:for line in lines:if line:f_output.write(line)else:continuedef get_token(this, line):# finditer : 在字符串中找到正则表达式所匹配的所有字串, 并把他们作为一个迭代器返回for match in re.finditer(this.patterns, line):# group():匹配的整个表达式的字符 # yield 关键字:类似return ,返回的是一个生成器,generatoryield (match.lastgroup, match.group())def run(this, line, flag=True):tokens = []for token in this.get_token(line):if flag:tokens.append(token)print("line %3d :" % this.lineno, token)'''else:yield "line %3d :" % this.lineno + str(token) + "\n"'''return tokensdef printrun(this, line, flag=True):for token in this.get_token(line):if flag:print("lines x: ", token)def main():token = Token()filepath = input("请输入文件路径:")print('-' * 20, '词法分析', '-' * 20)lines = token.read_file(filepath)tokenss = []for line in lines:tokens = token.run(line, True)for i in tokens:tokenss.append(i[1])return tokenss

五、实验结果与分析

这篇关于编译原理实验--实验三 预测分析法判断算术表达式的正确性--Python实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/618800

相关文章

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

hdu4407(容斥原理)

题意:给一串数字1,2,......n,两个操作:1、修改第k个数字,2、查询区间[l,r]中与n互质的数之和。 解题思路:咱一看,像线段树,但是如果用线段树做,那么每个区间一定要记录所有的素因子,这样会超内存。然后我就做不来了。后来看了题解,原来是用容斥原理来做的。还记得这道题目吗?求区间[1,r]中与p互质的数的个数,如果不会的话就先去做那题吧。现在这题是求区间[l,r]中与n互质的数的和

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal