【编译原理】LR(0)分析

news2024/11/13 11:13:55

一、实验目的

LR(0)分析法是一种移进归约过程,能根据当前分析栈中的符号串,同时也不用向右查看输入串的符号就可唯一确定分析器的动作。通过对给定的文法构造LR(0)分析表和实现某个符号串的分析掌握LR(0)分析法的基本思想。

二、实验要求

实现LR(0)分析需要:

(1)判别文法是否为LR(0)文法。

(2)构造LR(0)项目规范族,求出LR(0)分析表。

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

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

程序应满足下列要求:

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

输出格式,如:

步骤   状态栈       符号栈          输入串         ACTION    GOTO

(1)            0             #          i+i#                 S2

(2)           02              #i               +i#           r4         5

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

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

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

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

5.提前准备

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

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

三、实验过程:

  • 算法分析:

1. 时间复杂度:LR0分析算法的时间复杂度取决于输入字符串的长度和分析过程中的状态转换次数。在每一步中,算法需要从LR0表中查找转换规则,并执行相应的操作。因此,根据LR0表的规模和输入字符串的长度,LR0分析算法的时间复杂度可以达到O(n)级别。

2. 空间复杂度:LR0分析算法的空间复杂度主要取决于状态栈、符号栈和辅助变量的空间开销。在每一步中,状态栈和符号栈会根据LR0表的转换规则进行相应的推入和弹出操作。因此,根据状态栈和符号栈的最大长度以及辅助变量的空间开销,LR0分析算法的空间复杂度可以达到O(n)级别。

3. 最坏情况复杂度:LR0分析算法的最坏情况复杂度发生在输入字符串无法被文法接受的情况下。在这种情况下,算法将遍历整个输入字符串,并在每一步中执行状态转换和规约操作,直到遇到错误或结束。因此,最坏情况下,LR0分析算法的时间复杂度为O(n),空间复杂度为O(n)。

通过对LR0分析算法的算法分析,我们可以得出结论:LR0分析算法具有线性的时间复杂度和空间复杂度。它对于处理大规模的输入字符串和复杂的语法规则是有效的,并且在最坏情况下也能保持合理的性能。然而,它可能对一些特殊输入字符串和复杂的文法规则表现较差。这就需要进一步的算法优化和改进。

  • 程序流程图:

  • 程序代码:

LR0 = [["S2", "S3", "null", "null", "null", "1", "null", "null"],   # 0

       ["null", "null", "null", "null", "acc", "null", "null", "null"],   # 1

       ["null", "null", "S4", "S10", "null", "null", "6", "null"],   # 2

       ["null", "null", "S5", "S11", "null", "null", "null", "7"],   # 3

       ["null", "null", "S4", "S10", "null", "null", "8", "null"],   # 4

       ["null", "null", "S5", "S11", "null", "null", "null", "9"],   # 5

       ["r1", "r1", "r1", "r1", "r1", "null", "null", "null"],   # 6

       ["r2", "r2", "r2", "r2", "r2", "null", "null", "null"],   # 7

       ["r3", "r3", "r3", "r3", "r3", "null", "null", "null"],   # 8

       ["r5", "r5", "r5", "r5", "r5", "null", "null", "null"],   # 9

       ["r4", "r4", "r4", "r4", "r4", "null", "null", "null"],   # 10

       ["r6", "r6", "r6", "r6", "r6", "null", "null", "null"]]   # 11

L = "abcd#EAB"   # 列标签

del_rule = [0, 2, 2, 2, 1, 2, 1]   # 每个产生式规则的长度

head = ['S', 'E', 'E', 'A', 'A', 'B', 'B']   # 非终结符号

con = [0]   # 状态栈

cmp = ['#']   # 符号栈

cod = '0'   # 状态栈对应输出字符串

signal = ''   # 符号栈对应输出字符串

sti = '#'   # 符号栈对应输出字符串

def findL(b):

    """

    在L数组中找到列标签的索引。

    """

    for i in range(len(L)):

        if b == L[i]:

            return i

    return -1

def error(x, y):

    """

    当LR0表中的单元为空时,打印错误消息。

    """

    print(f"错误:单元格[{x}, {y}]为空!")

def calculate(l, s):

    """

    将LR0表中的数字字符串转换为整数。

    """

    num = int(s[1:l])

    return num

def analyze(string):

    """

    对给定的输入字符串执行LR0分析。

    """

    global con, cmp, cod, sti

    con = [0]

    cmp = ['#']

    cod = '0'

    sti = '#'

    cnt = 1

    LR = 0

    print("步骤     状态栈       符号栈       输入     ACTION     GOTO")

    while LR < len(string):

        # print(f"({cnt})     {cod}         {sti}", end="")

        # cnt += 1

        # print(string[LR:], end=" "*(10-(len(string)-LR)))

        print(f"({cnt})     {cod}         {sti}", end=" ")

        cnt += 1

        print(string[LR:], end=" " * (10 - (len(string) - LR)) + " ",)

        x = con[-1]

        y = findL(string[LR])

        if LR0[x][y] != "null":

            action = LR0[x][y]

            l = len(action)

            if action[0] == 'a':

                print("acc")

                return

            elif action[0] == 'S':

                print(action)

                t = calculate(l, action)

                con.append(t)

                sti += string[LR]

                cmp.append(string[LR])

                if t < 10:

                    cod += action[1]

                else:

                    k = 1

                    cod += '('

                    while k < l:

                        cod += action[k]

                        k += 1

                    cod += ')'

                LR += 1

            elif action[0] == 'r':

                print(action,end=" ")

                t = calculate(l, action)

                g = del_rule[t]

                while g > 0:

                    con.pop()

                    cmp.pop()

                    sti = sti[:-1]

                    g -= 1

                g = del_rule[t]

                while g > 0:

                    if cod[-1] == ')':

                        cod = cod[:-1]

                        while cod[-1] != '(':

                            cod = cod[:-1]

                        cod = cod[:-1]

                        g -= 1

                    else:

                        cod = cod[:-1]

                        g -= 1

                cmp.append(head[t])

                sti += head[t]

                x = con[-1]

                y = findL(cmp[-1])

                t = int(LR0[x][y][0])

                con.append(t)

                cod += LR0[x][y][0]

                print(t)

            else:

                t = int(LR0[x][y][0])

                print(" ", t)

                con.append(t)

                cod += LR0[x][y][0]

                sti += 'E'

                LR += 1

        else:

            error(x, y)

            return

try:

    with open("input.txt", "r") as file:

        for input_string in file:

            input_string = input_string.strip()  # 去掉末尾可能存在的换行符

            analyze(input_string)

except FileNotFoundError:

print("找不到文件 'input.txt'!")

 

四、思考题:

6、思考题:算符优先分析和LR分析都是自底向上分析方法,请说明两种分析思想的区别。

 算符优先分析和LR分析都是自底向上的语法分析方法,但是它们的思想和实现方式有一些区别。

1. 算符优先分析思想:

   - 算符优先分析是基于文法符号之间的优先关系进行分析的方法。

   - 算符优先文法定义了每个文法符号之间的优先级关系,例如运算符的优先级和结合性。

   - 算符优先分析使用优先关系表来判断在给定输入字符串中是否存在归约(reduce)或移进(shift)的动作。

   - 算符优先分析的核心思想是从输入字符串左边开始,通过比较符号栈和输入字符串中的符号的优先级来进行移进或归约的决策。

2. LR分析思想:

   - LR分析是基于有限状态自动机的状态转换进行分析的方法。

   - LR分析使用一个状态栈和一个符号栈来模拟状态转换的过程。

   - LR分析的核心思想是将状态栈和符号栈与LR分析表进行交互,根据当前状态和下一个输入符号来确定执行移进或归约的动作,并更新状态栈和符号栈。

   - LR分析的动作根据文法的产生式规则进行移进和归约,通过状态栈的状态转移来处理输入字符串。

算符优先分析和LR分析都是自底向上分析方法,都能处理各种上下文无关文法。但是它们的区别在于思想和实现方式。算符优先分析基于符号之间的优先关系进行判断,而LR分析基于状态转换和文法的产生式规则进行状态转换和动作选择。算符优先分析适用于具有运算优先级和结合性的表达式文法,而LR分析适用于更一般的上下文无关文法。此外,LR分析通常比算符优先分析更强大和更复杂,因为它可以处理更多的语法结构和文法规则。

五、实验小结:

在本次实验中,我们对LR0分析算法进行了实现和分析。通过分析LR0分析算法的代码和运行过程,我们加深了对LR0分析算法的理解,并学习了如何使用LR0表进行语法分析。

通过实验,我们了解到以下几点:

1. LR0分析算法是一种自底向上的语法分析方法,用于解析输入字符串并验证其是否符合语法规则。

2. 在LR0分析过程中,使用LR0表来进行状态转换和规约。

3. LR0表是由文法产生式规则和状态转换规则组成的二维数组。每个单元格中的内容表示根据当前状态和输入符号进行的动作。

4. LR0分析算法通过状态栈和符号栈来模拟状态的变化和符号的推导过程。

5. 在LR0分析过程中,需要根据LR0表的规则对状态栈和符号栈进行更新,并根据产生式规则进行规约操作。

通过实验,我们对LR0分析算法的执行过程有了更清晰的了解,并学习了如何进行LR0分析。此外,我们还了解到算法分析的重要性,可以帮助我们评估算法的性能和效率,并进行算法的改进和优化。

在今后的学习和实践中,我们可以深入研究和应用LR0分析算法,探索更高级的语法分析方法,并将其应用于解决实际问题。

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

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

相关文章

推荐3款好用的AI智能写作工具

AI智能写作如今已经很成熟了&#xff0c;不仅有很多AI综合大模型可以实现AI写作&#xff0c;还有很多专门针对AI写作场景专门研发的垂直领域工具。 如果你在工作学习中也想提高写作效率&#xff0c;不妨试试下面3个国内可直接登录使用的AI写作工具&#xff0c;其中不乏有简单易…

【Java】IdentityHashMap 的使用场景

文章目录 前言1. Druid 应用场景2. IdentityHashMap 特性3. IdentityHashMap 同步化4. IdentityHashMap 处理key为空值后记 前言 最近有兴趣看一下 Druid 连接池怎么做连接管理的&#xff0c;看到一个类 IdentityHashMap &#xff0c;这里记录一下使用场景。 1. Druid 应用场…

民国漫画杂志《时代漫画》第26期.PDF

时代漫画26.PDF: https://url03.ctfile.com/f/1779803-1248635183-9832d2?p9586 (访问密码: 9586) 《时代漫画》的杂志在1934年诞生了&#xff0c;截止1937年6月战争来临被迫停刊共发行了39期。 ps: 资源来源网络!

【HarmonyOS4学习笔记】《HarmonyOS4+NEXT星河版入门到企业级实战教程》课程学习笔记(十二)

课程地址&#xff1a; 黑马程序员HarmonyOS4NEXT星河版入门到企业级实战教程&#xff0c;一套精通鸿蒙应用开发 &#xff08;本篇笔记对应课程第 19节&#xff09; P19《18.ArkUI组件-页面路由》 以访问京东页面为例&#xff0c;访问过的页面并没有消失&#xff0c;而是进入了…

[图解]企业应用架构模式2024新译本讲解01-事务脚本

1 00:00:00,220 --> 00:00:03,010 接下来&#xff0c;我们就要进入模式的讲解了 2 00:00:04,030 --> 00:00:05,940 这个是书里面的目录 3 00:00:06,230 --> 00:00:08,140 按照 4 00:00:08,150 --> 00:00:09,220 领域逻辑模式 5 00:00:09,230 --> 00:00:10,5…

一点点 cv 经验 1:cv方向、模型评估、输入尺寸、目标检测器设计

一点点 cv 经验 1&#xff1a;cv方向、模型评估、输入尺寸、目标检测器设计 cv 方向Pytorch数据集划分 模型评估误差偏差方差噪声 输入尺寸方法一&#xff1a;让数据适应模型方法二&#xff1a;修改模型适应数据方法三&#xff1a;划分Patch&#xff0c;分别处理 目标检测器结构…

探索演进:了解IPv4和IPv6之间的区别

探索演进&#xff1a;了解IPv4和IPv6之间的区别 在广阔的互联网领域中&#xff0c;设备之间的通信依赖于一组独特的协议来促进连接。前景协议中&#xff0c;IPv4&#xff08;Internet 协议版本 4&#xff09;和 IPv6&#xff08;Internet 协议版本 6&#xff09;是数字基础设施…

二、OpenWebUI 使用(.Net8+SemanticKernel+Ollama)

OpenWebUI的github上安装部署已经很详细&#xff0c;直接照着敲命令即可 GitHub&#xff1a;https://github.com/open-webui/open-webui 一、使用配置 1、访问&#xff1a;http://Ip:3000&#xff0c;打开如下OpenWebUI界面。 2、先点击“注册”&#xff0c;注册一个管理员帐号…

从普通神经网络到transformer

1.单隐藏层的多层感知机 2. 循环神经网络 3.现代循环神经网络。 GRU 门控循环单元 LSTM 长短期记忆网络 候选记忆元&#xff1a; ˜C t ∈ R &#xff08;nh&#xff09; 记忆元

重生之 SpringBoot3 入门保姆级学习(04、 包扫描)

重生之 SpringBoot3 入门保姆级学习&#xff08;04、 包扫描&#xff09; 2.1 包扫描 2.1 包扫描 默认包扫描规则&#xff1a; SpringBootApplication 标注的就是主程序 SpringBoot 只会扫描主程序下面的包 自动的 component-scan 功能 在 SpringBootApplication 添加参数可以…

一文搞透常见的Python编码陷阱(上)(分析+案例)

一个认为一切根源都是“自己不够强”的INTJ 个人主页:用哲学编程-CSDN博客专栏:每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 一、别忘了冒号 1. if 语句 2. while 语句 3. for 语句 4. 函数定义 5. 类定义 6. try/except 语句 …

把maven本地库(windows)导入Nexus3(ubuntu)

1、在nexus中创建导入仓库 点“Create repository” 选择maven2(hosted) 填上对应的仓库name&#xff0c;Version policy选“Mixed” Hosted中的Deployment policy选择“Allow redeploy” 点“Create repository”创建仓库 创建好的仓库如下 记下仓库的url&#xff0c;下…

HTML-JavaWeb

目录 1.标题排版 2.标题样式 ​编辑 ​编辑 小结 3.超链接 4.正文排版 ​编辑​编辑​编辑5.正文布局 6.表格标签 7.表单标签 8.表单项标签 1.标题排版 ● 图片标签 :< img> src:指定图像的ur1(绝对路径/相对路径) width:图像的宽度(像素/相对于父元素的百…

OrangePi AIpro 开箱初体验及语音识别样例

OrangePi AIpro 开箱初体验及语音识别样例 一、 前言 首先非常感谢官方大大给予这次机会&#xff0c;让我有幸参加此次活动。 OrangePi AIpro联合华为精心打造&#xff0c;采用昇腾AI技术路线&#xff0c;具体为4核64位处理器AI处理器&#xff0c;集成图形处理器&#xff0c;…

【Linux环境搭建实战手册】:打造高效开发空间的秘籍

文章目录 &#x1f680;Linux环境搭建&#x1f4a5;1. 设备要求❤️2. 了解虚拟机&#x1f680;3. 安装VMware&#x1f308;4. 终端基础信息解读 &#x1f680;Linux环境搭建 &#x1f4a5;1. 设备要求 处理器&#xff08;CPU&#xff09;&#xff1a;至少具有1 GHz的处理能力&…

《Ai企业知识库》-模型实践-rasa开源学习框架-搭建简易机器人-环境准备(针对windows)-02

rasa框架 Conversational AI Platform | Superior Customer Experiences Start Here 阿丹: 其实现在可以使用的ai的开发框架有很多很多&#xff0c;就需要根据各个模型的能力边界等来讨论和设计。 rasa整体流程以及每一步的作用 NLU(自然语言理解): 自然语言理解&#xff…

07、SpringBoot 源码分析 - SpringApplication启动流程七

SpringBoot 源码分析 - SpringApplication启动流程七 初始化基本流程SpringApplication的prepareContext准备上下文postProcessApplicationContext处理applyInitializers初始化器初始化load SpringApplication的refreshContext刷新上下文refreshServletWebServerApplicationCon…

谷歌开发者账号身份验证不通过?该怎么办?

我们都清楚&#xff0c;随着谷歌上架行业的快速发展&#xff0c;谷歌政策也在不断更新变化&#xff0c;对开发者账号的审核标准也在不断提升。其中一项要求就是&#xff0c;开发者账号需要进行身份验证才能发布应用。 Your identity couldnt be verified&#xff01;“我们无法…

BookStack VS HelpLook两款知识库软件的区别

现在很多企业都会进行知识管理&#xff0c;在这个过程中&#xff0c;选择一个合适的知识库软件是一个不可避免的问题。在众多知识库软件中&#xff0c;HelpLook和BookStack这两款软件备受企业瞩目。不知如何选择&#xff0c;今天LookLook同学就简单介绍一下这两款知识库的区别&…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-24.1,2 SPI驱动实验-SPI协议介绍

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…