【编译原理】LL(1)预测分析法

一、实验目的

LL(1)的含义:第一个L表明自顶向下分析是从左向右扫描输入串,第2个L表明分析过程中将使用最左推导,1表明只需向右看一个符号便可决定如何推导,即选择哪个产生式进行推导。

LL(1) 预测分析方法是确定的自顶向下的语法分析技术。本次实验的主要目的就是要加深对LL(1)预测分析法的理论和预测分析程序工作过程的理解。

二、实验要求

实现LL(1)预测分析法需要:

(1)判别文法是否为LL(1)文法。为此需要依次计算FIRST集、FOLLOW集和SELLECT集,根据SELLECT集可判断文法否为LL(1)文法。

(2)构造出分析表。根据SELLECT集和文法产生式构造出LL(1)分析表。

(3)进行句子分析。依据分析表判断出某句子是否为给定文法的句子。

为了降低实现的难度,本实验只要求实现步骤(3)的部分,即手动实现步骤(1)和(2),然后依据步骤(2)建立的分析表编写一个总控程序,实现的句子的分析。

程序应满足下列要求:

  1. 输入一个分析表,则输出预测分析的步骤。要求从输入文件(input.txt)和键盘中输入预测分析表,把结果输出到结果文件(result.txt)和显示器。

输出格式,如:

步骤         符号栈        输入串       所用产生式

0        #E          i1*i2+i3#               

1      #ET          i1*i2+i3#         T-->FT

…       ………        …………        …………

2、程序应能判断出某句子是否为该文法的句子。(结论)

3、准备多组测试数据存放于input.txt文件中,测试数据中应覆盖是文法的句子和不是文法的句子两种情况,测试结果要求以原数据与结果对照的形式输出并保存在result.txt中,同时要把结果输出到屏幕。

4、对于上面步骤(1)和(2)虽不需要通过程序来实现,但要求和测试数据一起在实验报告中写明。

5、提前准备

① 实验前,先编制好程序,上机时输入并调试程序。

  • 准备好多组测试数据(存放于文件input.txt中)。

三、实验过程:

  • 算法分析:
  • 初始化文法和预测分析表:
  • 首先,定义了文法的终结符集合 v1 和非终结符集合 v2。
  • 接着,创建了几个产生式对象,并将它们赋值给预测分析表 C 的不同位置。
  • 读取文件内容:
  • 从指定的文件中读取文本内容,并存储在变量 exps 中,每行表示一个要分析的文法。
  • 预测分析:
  • 对于每个读取的文法,先检查是否只包含终结符,然后开始进行预测分析。
  • 预测分析过程通过遍历输入字符并根据预测分析表中的产生式进行推导和匹配。
  • 复杂度分析:
  • 初始化阶段的时间复杂度取决于产生式数量和预测分析表的大小,通常为 O(n)。
  • 读取文件内容和预测分析的时间复杂度主要取决于文法的长度和输入长度,通常为 O(m), 其中 m 为文法或输入的长度。
  • 空间复杂度主要取决于预测分析表的大小和其他数据结构的空间占用,通常为 O(n^2)。
  • 优点:
  • 预测分析器具有较好的可读性和易于实现的特点。
  • 可以快速识别输入串是否符合给定文法规则。
  • 局限性:
  • 预测分析器需要提前构建预测分析表,对于大型文法或复杂语言可能会变得复杂。
  • 对于某些文法,可能需要使用其他类型的解析器来处理。
  • 程序流程图:

  • 程序代码:

class Type:def __init__(self):self.origin = 'N'  # 产生式左侧字符 大写字符self.array = ""  # 产生式右边字符self.length = 0  # 字符个数def init(self, a, b):self.origin = aself.array = bself.length = len(self.array)# 预测分析表C = [[Type() for _ in range(10)] for _ in range(10)]def is_terminator(c):# 判断是否是终结符v1 = "i+*()#"return c in v1def read_file(file_name):# 读文件res = []try:with open(file_name, 'r') as file:for line in file:res.append(line.strip())except Exception as e:print(e)return resdef init(exp):global ridx, len_exp, rest_stack, toptop = ridx = 0len_exp = len(exp)  # 分析串长度rest_stack = list(exp)def print_stack():# 输出分析栈和剩余栈global top, ridx, len_exp, analye_stack, rest_stackprint(''.join(analye_stack[:top + 1]), end=' '*(20-top))for i in range(ridx):print(' ', end='')for i in range(ridx, len_exp):print(rest_stack[i], end='')print('\t\t\t', end='')def analyze(exp):# 分析一个文法global ridx, len_exp, analye_stack, rest_stack, C, topinit(exp)k = 0analye_stack[top] = '#'top += 1analye_stack[top] = 'E'  # '#','E'进栈print("步骤\t\t分析栈 \t\t\t\t\t剩余字符 \t\t\t\t所用产生式 ")while True:ch = rest_stack[ridx]x = analye_stack[top]top -= 1  # x为当前栈顶字符print(str(k + 1).ljust(8), end='')if x == '#':print("分析成功!AC!\n")  # 接受returnif is_terminator(x):if x == ch:  # 匹配上了print_stack()print(ch, "匹配")ridx += 1  # 下一个输入字符else:  # 出错处理print_stack()print("分析出错,错误终结符为", ch)  # 输出出错终结符returnelse:  # 非终结符处理m = v2.find(x) if x in v2 else -1  # 非终结符下标n = v1.find(ch) if ch in v1 else -1  # 终结符下标if m == -1 or n == -1:  # 出错处理print_stack()print("分析出错,错误非终结符为", x)returnelif C[m][n].origin == 'N':  # 无产生式print_stack()print("分析出错,无法找到对应的产生式")  # 输出无产生式错误returnelse:  # 有产生式length = C[m][n].lengthtemp = C[m][n].arrayprint_stack()print(x, "->", temp)  # 输出所用产生式for i in range(length - 1, -1, -1):if temp[i] != '^':top += 1analye_stack[top] = temp[i]  # 将右端字符逆序进栈k += 1ExpFileName = "./input.txt"v1 = "i+*()#"  # 终结符v2 = "EGTSF"  # 非终结符e = Type()t = Type()g = Type()g1 = Type()s = Type()s1 = Type()f = Type()f1 = Type()e.init('E', "TG")t.init('T', "FS")g.init('G', "+TG")g1.init('G', "^")s.init('S', "*FS")s1.init('S', "^")f.init('F', "(E)")f1.init('F', "i")C[0][0] = C[0][3] = eC[1][1] = gC[1][4] = C[1][5] = g1C[2][0] = C[2][3] = tC[3][2] = sC[3][4] = C[3][5] = C[3][1] = s1C[4][0] = f1C[4][3] = fexps = read_file(ExpFileName)analye_stack = [' ' for _ in range(20)]for exp in exps:flag = Truefor ch in exp:if not is_terminator(ch):flag = Falsebreakif flag:analyze(exp)

  • 程序运行结果截图:

四、思考题:

请描述确定的自顶向下分析思想。

确定的自顶向下分析思想是指自顶向下地对输入串进行分析,在每一步都根据当前的符号栈顶符号和输入串的当前符号,在分析表中查找所用产生式,然后将产生式右部的符号依次推入符号栈中,直到符号栈中只剩下底符号和输入串中所有符号都被读入为止。如果在分析过程中遇到了分析表中没有对应的产生式,则分析失败。

五、实验小结: 

通过本次实验,我初步了解了LL(1)预测分析法的基本原理和实现方法,掌握了自顶向下分析思想。在实验过程中,我手动计算了文法的FIRST集、FOLLOW集和SELECT集,构造出了LL(1)分析表,并编写了一个总控程序,实现了句子的分析。在测试过程中,我准备了多组测试数据,覆盖了是文法的句子和不是文法的句子两种情况,测试结果以原数据与结果对照的形式输出并保存在result.txt中,同时输出到屏幕。通过本次实验,我深刻理解了LL(1)预测分析法的工作原理,并掌握了其实现方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/840735.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024年【N1叉车司机】免费试题及N1叉车司机模拟试题

题库来源:安全生产模拟考试一点通公众号小程序 N1叉车司机免费试题考前必练!安全生产模拟考试一点通每个月更新N1叉车司机模拟试题题目及答案!多做几遍,其实通过N1叉车司机模拟考试题库很简单。 1、【多选题】《中华人民共和国特…

第三讲 栈、队列和数组 (1)

文章目录 第三讲 栈、队列和数组3.1 栈3.1.1 出栈元素的不同排列与卡特兰数3.1.2 栈的顺序表实现3.1.3共享栈3.1.4 栈的链表实现3.1.5 栈的两种实现的优缺点3.1.6 c中的栈( s t a c k stack stack)容器适配器3.1.7 栈的应用:star:3.1.7.1 **栈在括号匹配中的应用**3.1.7.2 **栈…

m1系列芯片aarch64架构使用docker-compose安装rocketmq5.0以及运维控制台

之前看到 DockerHub 上有大佬制作了 m1 芯片, aarch64架构的 rocketmq 镜像, 所以就尝试的安装了下, 亲测可用: 一. docker-compose.yml 文件命令 volumes 挂载目录需要换成自己的目录 注意 depends_on 标签, broker 和 console 的 启动要晚于 namesrv, 因为 broker 需要注册…

MPLS LDP原理与配置

1.LDP基本概念 (1)LDP协议概述 (2)LDP会话、LDP邻接体、LDP对等体 (3)LSR ID 与LDP ID (4)LDP消息 ⦁ 按照消息的功能,LDP消息一共可以分为四大类型:发现…

JKI State Machine的特点与详细介绍

JKI State Machine是一种基于状态机的LabVIEW架构,由JKI公司开发。它广泛用于开发复杂的应用程序,提供了一种灵活且可扩展的结构,适用于多种任务的管理和执行。其设计目标是提高开发效率、代码可读性和可维护性。 2. 基本架构 JKI State Ma…

【算法题】520 钻石争霸赛 2024 全解析

都是自己写的代码,发现自己的问题是做题速度还是不够快 520-1 爱之恒久远 在 520 这个特殊的日子里,请你直接在屏幕上输出:Forever and always。 输入格式: 本题没有输入。 输出格式: 在一行中输出 Forever and always…

python给图片加上图片水印

python给图片加上图片水印 作用效果代码 作用 给图片加上图片水印图片水印的透明度,位置可自定义 效果 原始图片: 水印图片: 添加水印后的图片: 代码 from PIL import Image, ImageDraw, ImageFontdef add_watermark(in…

体检系统商业源码,C/S架构的医院体检系统源码,大型健康体检中心管理系统源码

体检系统商业源码,C/S架构的医院体检系统源码,大型健康体检中心管理系统源码 体检信息管理系统软件是对医院体检中心进行系统化和规范化的管理。系统从检前,检中,检后整个业务流程提供标准化以及精细化的解决方案。实现体检业务市…

优化css样式的网站

一、按钮的css样式 https://neumorphism.io/#e0e0e0https://neumorphism.io/#e0e0e0 二、渐变样式 Fresh Background Gradients | WebGradients.com 💎Come to WebGradients.com for 180 beautiful linear gradients in CSS3, Photoshop and Sketch. This collect…

Git Core Lecture

1、Git 简介 官方介绍:Git is a fast distributed revision control system (Git 是一个快速的分布式版本控制系统) 2、Git Core Command 2.1 git init git 工程初始化,会在工作区 (working directory) 根目录中创建.git 目录 # 创建目录 $ mkdir git-i…

C# 深拷贝和浅拷贝

文章目录 1.深拷贝2.浅拷贝3.拷贝类4.浅拷贝的实现5.深拷贝实现5.1 浅拷贝对象,对引用类型重新一个个赋值5.2 反射实现5.3 利用XML序列化和反序列化实现 1.深拷贝 拷贝一个对象时,不仅仅把对象的引用进行复制,还把该对象引用的值也一起拷贝。…

python期末作业:批量爬取站长之家的网站排行榜数据并保存,数据分析可视化

爬虫作业,含python爬取数据和保存文件,数据分析使用pyecharts做数据可视化 整体上分析网站的排名,直观看各个网站的热度。 数据分析之后大致的效果: 整个项目分为两个大的部分,第一部分就是抓取网站排名数据,然后保存为Excel、csv等格式,其次就是从文件中…

【30天精通Prometheus:一站式监控实战指南】第8天:redis_exporter从入门到实战:安装、配置详解与生产环境搭建指南,超详细

亲爱的读者们👋   欢迎加入【30天精通Prometheus】专栏!📚 在这里,我们将探索Prometheus的强大功能,并将其应用于实际监控中。这个专栏都将为你提供宝贵的实战经验。🚀   Prometheus是云原生和DevOps的…

arc-eager算法XJTU-NLP自然语言处理技术期末考知识点

arc-eager算法:以我/做了/一个/梦为例来描述arc-eager算法的四个操作:shift,left-arc,right-arc,reduce XJTU-NLP期末考点2024版 题型:5*6简答题4*15计算题 简答题考点: (1&#…

Java+Spring+ IDEA+MySQL云HIS系统源码 云HIS适合哪些地区的医院?

JavaSpring IDEAMySQL云HIS系统源码云HIS适合哪些地区的医院? 云HIS适合哪些地区的医院? 云HIS(云医院信息系统)适合多种地区的医院,特别是那些希望实现医疗服务的标准化、信息化和规范化,同时降低IT运营成…

42-2 应急响应之计划任务排查

一、进程排查 进程排查是指通过分析系统中正在运行的进程,以识别和处理恶意程序或异常行为。在Windows和Linux系统中,进程是操作系统的基本单位,因此对于发现和处理恶意软件或异常活动至关重要。恶意程序通常会以进程的形式在系统中运行,执行各种恶意操作,比如窃取信息、破…

每日一题 包含不超过两种字符的最长子串

目录 1.前言 2.题目解析 3.算法原理 4.代码实现 1.前言 首先我打算介绍一下,我对滑动窗口的理解。 滑动窗口可以分为四个步骤: 进窗口: 在这一步骤中,我们决定了要在窗口中维护的信息。例如,在这个问题中&#xff…

Codeforces Round 946 (Div.3)

C o d e f o r c e s R o u n d 946 ( D i v . 3 ) \Huge{Codeforces~Round~946~(Div.3)} Codeforces Round 946 (Div.3) 题目链接:Codeforces Round 946 (Div. 3) 文章目录 Problems A. Phone Desktop题意思路标程 Problems B. Symmetric Encoding题意思路标程 Pr…

ubuntu 配置用户登录失败尝试次数限制

前言: 通过修改pam配置来达到限制密码尝试次数! 1:修改 /etc/pam.d/login 配置(这里只是终端登录配置,如果还需要配置SSH远程登录限制,只配置下面的 /etc/pam.d/pam.d/common-auth 即可) vim…

SpringCloud的Config配置中心,为什么要分Server服务端和Client客户端?

SpringCloud的Config配置中心,为什么要分Server服务端和Client客户端? 在SpringCloud的Config配置中心中分了Server服务端和Client客户端,为什么需要这样分呢?它的思想是所有微服务的配置文件都放到git远程服务器上,让…