c++编译原理LR分析程序 代码+报告

news2025/3/10 21:30:12

 编译原理实验报告

 

目  录

目录

1  实验目的

2  实验内容

3  实验要求

4  实验原理

4.1 TPL语言语法分析的文法

4.2设计思路

4.3LR分析表

5. 数据结构、函数说明和主要算法

5.1 主要的数据结构

5.2 所有函数的说明

5.3 主要算法

6. 实现与测试

6.1 源程序1测试

7  实验总结

8  参考文献

1  实验目的

(1) 掌握语法分析过程,即语法分析是如何根据语法规则逐一分析词法分析时得到的属性字,检查语法错误。

(2) 构造LR分析程序,利用它进行语法分析,判断给出的符号串是否为该文法识别的句子。

(3) 理解LR分析方法是严格的从左向右扫描,和自底向上的语法分析方法。

(4) 理解词法分析和语法分析的接口方式。

2  实验内容

完善TPL语言文法,然后手动或者编程创建LR分析表,然后编写TPL语言的语法分析程序,它从左到右依次对词法分析得到的结果数组或链表等存储结构中进行读取,判断是否符合语法规则,并给出语法分析过程和结果。

3  实验要求

(1) 根据TPL语言的文法规则建立LR分析表;

项目集、项目集之间的转换函数、LR分析表的构造过程,要求写程序实现。该程序的输入是文法的所有产生式,输出是LR分析表。程序尽可能通用,即输入的文法改变了,那么也可以给出对应的LR分析表。

有困难的同学,也可以手动构造LR分析表。

(2) 采用自底向上方法来设计TPL语法分析程序,实现以下功能:

① 能对任何TPL语言词法分析结果进行语法分析。

② 输出分析过程。

③ 若语法分析过程有错误,则定位错误,并指出错误原因。

4  实验原理

LR(Left-to-Right,Rightmost derivation)语法分析是一种常用的自底向上(bottom-up)的语法分析方法。LR分析器的核心思想是从输入串的左端推导出文法的开始符号,同时使用一个栈来保存已经识别的部分。LR分析器通过一系列的移进(Shift)和归约(Reduce)操作来构建分析树,并最终判断输入串是否符合文法。ACTION和GOTO表:LR分析表包括两个部分,一个是ACTION表,另一个是GOTO表。ACTION表用于处理终结符的移进和归约操作,而GOTO表用于处理非终结符的转移。

ACTION表中的项可以是移进操作、归约操作或接受操作。移进操作表示将输入符号移到栈中,归约操作表示使用产生式进行规约,接受操作表示输入串符合文法规则。

GOTO表用于在分析栈中进行非终结符的状态转移。

分析栈和输入缓冲区:LR语法分析使用一个分析栈来保存已经识别的部分,同时从输入缓冲区读入符号。根据ACTION和GOTO表的信息,分析器进行移进、归约等操作,直到接受或出错。

LR(1)语法分析:为了处理具有相同前缀的产生式,LR(1)语法分析引入了“查看符号”(Lookahead Symbol)的概念。LR(1)项目集包含了在某个位置上的项目以及紧随其后的一个终结符,使得分析器可以根据更多的信息进行决策。

4.1 TPL语言语法分析的文法

据程序设计语言的语法规则,描述包含赋值语句、控制语句的源程序的语法,TPL 语言对应的文法产生式P->A

A->BCH

A->BCD

A->BCG

B->39

C->86 56 87 78 C

C->86 56 87 79

D->17 71 E 72 H

D->17 71 E 72 G

D->17 71 E 72 F

G->34 71 E 72 F

G->34 71 E 72 H

G->34 71 E 72 D

E->86 I 87

F->86 56 87 79

F->86 56 86 J

H->15 71 B 86 56 87 79 E 79 86 45 72 75 D 76

H->15 71 B 86 56 87 79 E 79 86 45 72 D

H->15 71 B 86 56 87 79 E 79 86 45 72 75 H 76

H->15 71 B 86 56 87 79 E 79 86 45 72 H

H->15 71 B 86 56 87 79 E 79 86 45 72 75 G 76

H->15 71 B 86 56 87 79 E 79 86 45 72 G

H->15 71 B 86 56 87 79 E 79 86 45 72 F

I->50|47

J->40 87 J

J->40 86 J

J->40 87 79

J->40 86 79

4.2

设计思路

1、因为文法是自己设置的,所以可以自己规定文法的结构,所以规定,开始符的规则一定只有一条,所以不用补充开始符。因此所有非终结符就可以设置为一位的,就不用开二维数组来保存非终结符了。同时,因为用的VS编译器不支持输出ASCII码之外的阿拉伯符号,因此我用->表示规则中的箭头,.表示项目集中的点。

2、因为要对程序进行分析,然后词法分析器输出的是单词表中的种别码,所以,设置终结符全部为数字。因为语法分析器的输入应该是词法分析器的输出,所以,用一个全局一维数组来将词法分析输出的每个种别码保存,并记录个数,作为语法分析器的输入串。同时,因为将种别码对应的单词(关键字、标识符、运算符、界符、整型和浮点型)输出格式不好看,所以我直接对种别码进行分析,文法也是用种别码来当作终结符构造的。

  1. LR(1)文法的难度主要是在如何构造项目集和分析表。我创建了一个结构体来保存并构建项目集。项目集和项目集的闭包都是用模拟算法求的,也就是直接模拟做题时的步骤将算法写出。同时,为了构造分析表,在每个项目集求完闭包之后,要将项目集与下一个项目集的联系保存。为了保存项目之间的联系,用pair定义了两个新的二元组类型CI和PII。

因为非终结符是单个大写字母,而终结符是整型数字,所以创建了两个二元组来分别保存,二元组第一个元素表示的时非终结符或终结符,第二个元素则表示下一个项目集的编号。

因为LR(1)分析法求闭包需要求向前搜索符,所以我单独写了个求first集的函数,但是这个求first的函数仅求一个终结符并且不能求太复杂的规则的first。此外,因为在求项目集时要判断点后面的字符是非终结符还是终结符,因此还写了判断点后面是否是非终结符以及求点后面的非终结符和终结符的函数。还写了规则中点移动的函数,因为保存项目集的结构体是定义为全局变量的,所以如果直接将规则传入函数的话,会将项目集中的规则改变,所以定义了一个临时变量来进行移动,点移动之后在将临时变量的值赋给下一个项目集的规则

 4.3LR分析表

5. 数据结构、函数说明和主要算法

5.1 主要的数据结构

文法规则结构体(GS):

cpp

Copy code

struct GS {

    char vn[10]; // 非终结符数组

    int nvn;     // 非终结符个数

    int vt[10];  // 终结符数组

    int nvt;     // 终结符个数

    char gs[50][50]; // 扩展后的文法数组

    int ngs;     // 扩展后的文法个数

} gs;

项目集结构体(DFANode):

cpp

Copy code

struct IGS {

    char igs[50]; // 文法规则

    int x;        // 向前搜索符

};

struct DFANode {

    IGS gather[50]; // 项目集中的规则

    int sum;        // 项目集中的规则数量

    int i;          // 项目集编号

    // 下面是与其他项目集的联系

    pair<char, int> nextci[50];  // 与非终结符的联系

    pair<int, int> nextpii[50];  // 与终结符的联系

    int nci;        // 非终结符联系的个数

    int npii;       // 终结符联系的个数

} dfa[50];

LR(1)分析表项结构体(TableItem):

cpp

Copy code

struct TableItem {

    int i;   // 状态编号

    pair<char, int> ci[50];   // 非终结符与下一个状态的关系

    pair<int, int> pii[50];   // 终结符与下一个状态的关系

    int nci;  // 非终结符联系的个数

    int npii; // 终结符联系的个数

} table[50];

5.2 所有函数的说明

void open_file():

打开文件并读取文法规则,将文法规则扩展,生成 gs 结构体。

识别非终结符和终结符,并对终结符进行排序。

void print_gs():

输出从文件读入并扩展后的文法,以及非终结符和终结符的集合。

void print_dfa():

输出 LR(1) 项目集规范族(DFA)的各个项目集及项目之间的联系。

void print_table():

输出由 DFA 构建的 LR(1) 分析表,包括 ACTION 和 GOTO 表。

void analysis_table():

生成分析表,填充 ACTION 和 GOTO 表。

void input_analysis():

对输入串进行 LR(1) 分析,输出每一步的状态栈、符号栈、输入串、产生式、ACTION、GOTO 等信息。

char* spcode_to_character(int n, char s[]):

将种别码转换为对应的关键字、分界符或运算符字符串。

add_vn(char c), add_vt(int n): 将非终结符和终结符添加到相应集合中。

pd_integer(char c): 判断字符是否为数字。

pd_character2(char c): 判断字符是否为非终结符。

pd_invn(char c), pd_invt(int n): 判断是否为非终结符或终结符的补充规则。

pd_pafter(char c): 判断规则后面是否为非终结符。

get_rule(char s[]): 获取输入的规则在文法中的位置。

5.3 主要算法

 DFA 构建算法:

void build_dfa() {

    initialize(); // 初始化一些数据结构

    int i = 0;

    while (i < ni) {

        // 创建新的项目集

        create_new_item_set(i);

        

        // 对项目集中的每个规则进行处理

        int k = 0;

        while (k < dfa[now_i].sum) {

            process_item(dfa[now_i].gather[k]);

            k++;

        }

        

        // 查重,合并相同的项目集

        handle_duplicates();

        i++;

    }

}

void process_item(IGS item) {

    // 处理项目集中的每个规则,更新dfa、table等数据结构

    // ...

}

void create_new_item_set(int i) {

    // 创建新的项目集,并处理其中的规则

    // ...

}

void handle_duplicates() {

    // 处理重复的项目集,合并相同的项目集

    // ...

}

LR(1) 分析算法:

void input_analysis() {

    int n = nsp, s[N] = { 0 };

    // 初始化输入串

    stack<int> stack_state;

    stack<int> stack_symbol;

    while (i < n) {

        // 从分析表中获取动作和产生式

        int k = stack_state.top();

        int np = get_action_or_goto(k, s[i]);

        if (np == 666) {

            // acc,成功接收

            break;

        }

        if (is_shift(np)) {

            // 移进操作

            shift_operation(np);

            i++;

        } else {

            // 归约操作

            reduce_operation(np);

        }

        step++;

    }

}

int get_action_or_goto(int state, int symbol) {

    // 从分析表中获取 ACTION 或 GOTO 值

    // ...

}

void shift_operation(int np) {

    // 处理移进操作

    // ...

}

void reduce_operation(int np) {

    // 处理归约操作

    // ...

}

这两个算法分别描述了LR(1)分析器的两个关键步骤:DFA的构建和LR(1)分析。在DFA的构建中,通过不断处理项目集和规则,构建LR(1)项目集规范族。在LR(1)分析中,通过分析表,不断进行移进和归约操作,最终完成对输入串的分析。这两个算法是LR(1)分析器的核心逻辑。

6. 实现与测试     

6.1 源程序1测试

 

7  实验总结

持续两个周的编译原理课程设计,让我学到了很多东西。首先是加深了对编译原理课程的理解,对词法分析、语法分析了有了更进一步的掌握,其次是编程能力的提高,这样的代码量,一年也只有几次能够遇到。有了前面课程设计的经验,这一次的编译原理课程设计,我更注重数据结构,数据结构的好坏直接决定了代码的复杂度,代码的量,调试困难,遇到错误常常会使程序直接崩溃。

我对一个编译器的组成有了更深层次的认识。通过本次的课程设计,我对自动机有了更深入的了解,也希望这些理论会再我们日后的学习中发挥更大的作用

8  参考文献

[1] 张素琴,吕映芝,蒋维杜等.编译原理[M].北京:清华大学出版社,2015.

[2] 张敬敏,李霞.编译原理实验指导书[Z].石家庄,2021.

指导教师评语

指导教师签字    

                            

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

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

相关文章

快速搞懂时间序列数据平稳检验

在对时间序列数据进行分析预测时&#xff0c;平稳时间序列数据预测效果更好。所以首先要检测数据是否平稳&#xff0c;没有趋势的时间序列数据&#xff0c;我们称为平稳的&#xff0c;即随着时间的推移&#xff0c;表现出恒定的方差&#xff0c;具有恒定的自相关结构。本文介绍…

Vue实现多个input输入,光标自动聚焦到下一个input

遇到一个需求&#xff0c;需要实现和移动端短信输入一样&#xff0c;输入内容后&#xff0c;光标会进入下一个输入框 需要用到2个事件 keydown事件发生在键盘的键被按下的时候 keyup 事件在按键被释放的时候触发 <template><div class"box"><el-fo…

读书笔记之《我的大脑好厉害》:脑科学启蒙

《我的大脑好厉害》的作者是赵思家&#xff0c;于 2022年出版。 赵思家是牛津大学神经科学博士后&#xff0c;科普作者&#xff0c;知乎神经科学领域大V&#xff0c;46万关注&#xff0c;擅长为充满好奇的读者提供新鲜、有趣又不失严谨的神经科学知识。赵思家2013年毕业于伦敦大…

Linux CentOS stream 9 安装docker

在计算机技术中,虑拟化是一种资源管理技术,是将计算机的各种实体资源(CPU、内存、磁盘空间、网络适配器等),予以抽象、转换后呈现出来并可供分区、组合为一个或多个电脑配置环境。 目前,大多数服务器的容量的利用率不足15%,这导致服务器数量激增以及增加了复杂性。服务…

C语言系列(所需基础:大学C语言及格)-1-编译器/简单的求和代码/数据类型/变量的分类/变量的作用域和生命周期

文章目录 一、编译器&#xff08;使用在线编译器&#xff09;二、简单的求和代码三、数据类型四、变量的分类五、变量的作用域和生命周期 一、编译器&#xff08;使用在线编译器&#xff09; 为了方便&#xff0c;我使用的是在线的C语言编译器进行程序的运行。 链接&#xff1…

Vue的一些基础设置

1.浏览器控制台显示Vue 设置找到扩展&#xff0c;搜索Vue 下载这个 然后 点击扩展按钮 点击详细信息 选择这个&#xff0c;然后重启一下就好了 ——————————————————————————————————————————— 2.优化工程结构 src的components里要…

Tomcat要点总结

一、Tomcat 服务中部署 WEB 应用 1.什么是Web应用 &#xff08;1&#xff09; WEB 应用是多个 web 资源的集合。简单的说&#xff0c;可以把 web 应用理解为硬盘上的一个目录&#xff0c; 这个目录用于管理多个 web 资源。 &#xff08;2&#xff09;Web 应用通常也称之为…

[嵌入式系统-24]:RT-Thread -11- 内核组件编程接口 - 网络组件 - TCP/UDP Socket编程

目录 一、RT-Thread网络组件 1.1 概述 1.2 RT-Thread支持的网络协议栈 1.3 RT-Thread如何选择不同的网络协议栈 二、Socket编程 2.1 概述 2.2 UDP socket编程 2.3 TCP socket编程 2.4 TCP socket收发数据 一、RT-Thread网络组件 1.1 概述 RT-Thread 是一个开源的嵌入…

微星B85 PCMATE 配合 E3-1230V3锁全核3.7

参考&#xff1a; Non-K超频&#xff0c;i5-12490F 微星 MAG B760M MORTAR MAX WIFI DDR4 超频分享 - 知乎 微星科技 | 微星科技 ring ratio 的说明 英特尔CPU 可以调整的ring ratio (ring 频率&#xff09;是什么&#xff1f; - 知乎 1. 主要调节的是 CPU倍频&#xf…

磁盘删除的文件怎么恢复?4个简单方法(2024更新版)

“我有很多文件都保存在电脑磁盘里了&#xff0c;想问问电脑磁盘删除的文件有什么方法可以快速恢复吗&#xff1f;非常感谢大家&#xff01;” 在日常工作和生活中&#xff0c;我们经常会在磁盘中存储大量的文件。这些文件对我们来说或许都有特殊的意义。磁盘删除的文件怎么恢复…

数据模型概念

一、概念 (1) 定义 在数据库系统中针对不同的使用对象和应用目的&#xff0c;采用不同的数据模型。根据模型的应用的不同目的&#xff0c;可以将这些模型划分为两类&#xff1a; (2) 分类 A&#xff1a;概念数据模型 它也称信息模型它是按用户的观点&#xff08;观念世界&…

GPT-SoVITS-WebUI 克隆声音 macos搭建

强大的少样本语音转换与语音合成Web用户界面 macos运行参考 macos conda create -n GPTSoVits python3.9 conda activate GPTSoVits激活环境 conda activate GPTSoVits停用 conda deactivate mkdir GPTSoVits cd GPTSoVits git clone https://github.com/RVC-Boss/GPT-SoVITS…

C++之内存对齐

目录 内存对齐 一、内存对齐解释 二、为什么要内存对齐&#xff1f; 三、内存对齐的三大规则 3.1、数据成员对齐规则 3.2、结构(或联合)的整体对齐规则 3.3、结构体作为成员 3.4、代码例子 内存对齐 一、内存对齐解释 对齐规则是按照成员的声明顺序&#xff0c;依次安排…

学历太低,可以学这5个技术,不但好找工作,工资也挺高的!

前言 我今年23岁&#xff0c;勉强把高中上完了。 大家都说上高中的时候非常辛苦&#xff0c;但在我看来&#xff0c;却不是这样的。 因为那时候根本就没有&#xff0c;把精力放在学习上面&#xff0c;而是经常出去泡网吧。 没办法&#xff0c;一个班级里面&#xff0c;大多…

2024年【道路运输企业主要负责人】找解析及道路运输企业主要负责人试题及解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年【道路运输企业主要负责人】找解析及道路运输企业主要负责人试题及解析&#xff0c;包含道路运输企业主要负责人找解析答案和解析及道路运输企业主要负责人试题及解析练习。安全生产模拟考试一点通结合国家道路…

【制作100个unity游戏之25】3D背包、库存、制作、快捷栏、存储系统、砍伐树木获取资源、随机战利品宝箱12(附带项目源码)

效果演示 文章目录 效果演示系列目录前言悬停显示物品详情源码完结 系列目录 前言 欢迎来到【制作100个Unity游戏】系列&#xff01;本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第25篇中&#xff0c;我们将探索如何用unity制作一个3D背包、库存、制作、快…

【C++】c++中的函数模板

文章目录 前言什么是函数模板为什么要有模板怎么用函数模板 前言 c语言中没有提供模板&#xff0c;要求实现一个Add函数&#xff0c;对于不同的数据类型可能存在Add_int(),Add_double(&#xff09;等函数&#xff0c;这种重复操作比较的低效&#xff0c;c提供了函数重载的功能…

【感知机】感知机(perceptron)学习算法的对偶形式

感知机( perceptron )是二类分类的线性分类模型&#xff0c;其输入为实例的特征向量&#xff0c;输出为实例的类别&#xff0c;取1 和-1二值。感知机对应输入空间(特征空间)中将实例划分为正负两类的分离超平面&#xff0c;是一种判别模型。感知机是神经网络与支持向量机的基础…

第十二章[模块]:12.5:标准库:zipfile

一,认识zipfile: 1,什么是zipfile? zipfile是python里用来做zip格式编码的压缩和解压缩的, 它采用平时应用非常常见的zip格式, 所以这个模块使用频率也很高 2,官方文档: zipfile --- 使用ZIP存档 — Python 3.12.2 文档源代码: Lib/zipfile/ ZIP 文件格式是一个常用的归…

一款服务于医院临床数据资源建设的平台,助力医疗信息化发展

随着医疗技术的不断发展&#xff0c;医院需要越来越多的临床数据来支持科研、教学和临床实践。然而&#xff0c;在传统的医疗系统中&#xff0c;数据分散、信息割裂、无法有效整合和共享。为了解决这一问题&#xff0c;临床数据资源整合平台应运而生。 临床数据资源整合平台是…