编译原理-实现LR语法分析器——沐雨先生

实验任务:

实现LR语法分析器

实验要求:

根据编译原理理论课教材中例3.22给出的算术表达式文法以及该文法的LR分析表,用C语言编写接受算术表达式为输入的语法分析器,以控制台(或文本文件,也可以结合词法分析器完成)为输入,控制台(或文件)输出产生式序列形式的分析结果。

实验内容:

教材中例3.22给出的算术表达式文法只有+、运算,对应的LR分析表也比较单一,为了编写接受算术表达式为输入的语法分析器,我将文法完善为下列文法,然后先在纸上写出LR(0)项目集规范族来构造LR分析表,再将其写入程序作为该文法的LR分析表。然后再依据使用分析表对输入符号串做分析的过程编写程序,使得用LR分析法对任意输入的符号串进行分析。
(1)E-> E+T
(2)E- >E-T
(3)E- >T
(3)T- >T
F
(4)T- >T/F
(5)T- >F
(6)F- >(E)
(7)F- >i

主要代码:

运行示例:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实验小结:

1.在看教材中的例3.22时,对于一个算术表达式而言绝不止+、*符号,故例3.22的文法具有一定的局限性,所以我们可以将文法进行拓展,即终结符有±*/,涵盖算术表示式应有的所有运算符,在此基础上我们还需要构造LR(0)项目集规范族,以构造出LR分析表,在确定正确的情况下将其输入程序中以作分析。

2.与上一个实验构造LL(1)语法分析器作对比,有很多的不同之处,LL(1)文法与LR(0)或LR(1)文法的分析技术就是不同的,所以本实验在汲取上个实验部分相同点的基础上需要改变分析思路,这样才能构造出正确的分析过程。

源程序

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<stack>
using namespace std;///					   0		1		2		3		4		5		6		7		8		9		10
///表格数组                +       -        *       /       i      (      )       # 	    E	    T		 F
char LR0[50][50][100] = {{"null" ,"null" ,"null", "null" ,"S4"   ,"S5"   ,"null" ,"null" ,"1"    ,"2"    ,"3"   },///   0{"S6"   ,"S7"   ,"null", "null" ,"null ","null" ,"null" ,"acc"  ,"null" ,"null" ,"null"},///   1{"r3"   ,"r3"   ,"S8"  , "S9"   ,"null" ,"null" ,"r3"   ,"r3"   ,"null" ,"null" ,"null"},///   2{"r6"   ,"r6"   ,"r6"  , "r6"   ,"null" ,"null" ,"r6"   ,"r6"   ,"null" ,"null" ,"null"},///   3{"r8"   ,"r8"   ,"r8"  , "r8"   ,"null" ,"null" ,"r8"   ,"r8"   ,"null" ,"null" ,"null"},///   4{"null" ,"null" ,"null", "null" ,"S4"   ,"S5"   ,"null" ,"null" ,"10"   ,"2"    ,"3"   },///   5{"null" ,"null" ,"null", "null" ,"S4"   ,"S5"   ,"null" ,"null" ,"null" ,"11"   ,"3"   },///   6{"null" ,"null" ,"null", "null" ,"S4"   ,"S5"   ,"null" ,"null" ,"null" ,"12"   ,"3"   },///   7{"null" ,"null" ,"null", "null" ,"S4"   ,"S5"   ,"null" ,"null" ,"null" ,"null" ,"13"  },///   8{"null" ,"null" ,"null", "null" ,"S4"   ,"S5"   ,"null" ,"null" ,"null" ,"null" ,"14"  },///   9{"S6"   ,"S7"   ,"null", "null" ,"null" ,"null" ,"S15"  ,"null" ,"null" ,"null" ,"null"},///   10{"r1"   ,"r1"   ,"S8"  , "S9"   ,"null" ,"null" ,"r1"   ,"r1"   ,"null" ,"null" ,"null"},///   11{"r2"   ,"r2"   ,"S8"  , "S9"   ,"null" ,"null" ,"r2"   ,"r2"   ,"null" ,"null" ,"null"},///   12{"r4"   ,"r4"   ,"r4"  , "r4"   ,"null" ,"null" ,"r4"   ,"r4"   ,"null" ,"null" ,"null"},///   13{"r5"   ,"r5"   ,"r5"  , "r5"   ,"null" ,"null" ,"r5"   ,"r5"   ,"null" ,"null" ,"null"},///   14{"r7"   ,"r7"   ,"r7"  , "r7"   ,"null" ,"null" ,"r7"   ,"r7"   ,"null" ,"null" ,"null"},///   15};
char L[200]="+-*/i()#ETF";    ///列判断依据
int  del[10]={0,3,3,1,3,3,1,3,1};//0-6号文法每个文法长度
char head[20]={'S','E','E','E','T','T','T','F','F'};
stack<int>con;    ///状态栈
stack<char>cmp;   ///符号栈
char cod[300]="0";///初始状态栈对应输出数组
int cindex = 0;
char sti[300]="#";///初始符号栈对应输出数组
int sindex = 0;
int findL(char b)///对应列寻找
{for(int i = 0; i <= 10; i++){if(b==L[i]){return i;}}return -1;
}
void error(int x, int y)       ///报错输出
{printf("第%d行%c列为空!",x,L[y]);
}int calculate(int l, char s[])
{int num = 0;for(int i = 1; i < l; i ++){num =  num*10+(s[i]-'0');}return num;
}
void analyze(char str[],int len)///分析主体过程
{int cnt = 1;printf("步骤		状态栈		符号栈    输入串    ACTION    GOTO\n");int LR = 0;while(LR<=len){printf("(%d)		%-10s	%-10s",cnt,cod,sti);///步骤,状态栈,符号栈输出cnt++;for(int i = LR; i < len; i++)///输入串输出{printf("%c",str[i]);}for(int i = len-LR; i<10;i++)printf(" ");int x = con.top();///状态栈栈顶int y = findL(str[LR]);///待判断串串首if(strcmp(LR0[x][y],"null")!=0){int l = strlen(LR0[x][y]);///当前Ri或Si的长度if(LR0[x][y][0]=='a')///acc{printf("acc        \n");///ACTION与GOTOreturn ;}else if(LR0[x][y][0]=='S')///Si{printf("%-10s \n",LR0[x][y]);///ACTION与GOTOint t = calculate(l,LR0[x][y]);///整数con.push(t);sindex++;sti[sindex] = str[LR];cmp.push(str[LR]);if(t<10){cindex++;cod[cindex] = LR0[x][y][1];}else{int k = 1;cindex++;cod[cindex] = '(';while(k<l){cindex++;cod[cindex] = LR0[x][y][k];k++;}cindex++;cod[cindex] = ')';}LR++;}else if(LR0[x][y][0]=='r')//ri,退栈,ACTION和GOTO{printf("%-10s",LR0[x][y]);int t = calculate(l,LR0[x][y]);int g = del[t];while(g--){con.pop();cmp.pop();sti[sindex] = '\0';sindex--;}g = del[t];while(g>0){if(cod[cindex]==')'){cod[cindex]='\0';cindex--;for(;;){if(cod[cindex]=='('){cod[cindex]='\0';cindex--;break;}else{cod[cindex]='\0';cindex--;}}g--;}else{cod[cindex] = '\0';cindex--;g--;}}///cmp.push(head[t]);sindex++;sti[sindex] = head[t];x = con.top();y = findL(cmp.top());if(x==5&&y==8){t = 10;cindex++;cod[cindex] = '(';cindex++;cod[cindex] = '1';cindex++;cod[cindex] = '0';cindex++;cod[cindex] = ')';}else if(x==6&&y==9){t = 11;cindex++;cod[cindex] = '(';cindex++;cod[cindex] = '1';cindex++;cod[cindex] = '1';cindex++;cod[cindex] = ')';}else if(x==7&&y==9){t=12;cindex++;cod[cindex] = '(';cindex++;cod[cindex] = '1';cindex++;cod[cindex] = '2';cindex++;cod[cindex] = ')';}else if(x==8&&y==10){t=13;cindex++;cod[cindex] = '(';cindex++;cod[cindex] = '1';cindex++;cod[cindex] = '3';cindex++;cod[cindex] = ')';}else if(x==9&&y==10){t=14;cindex++;cod[cindex] = '(';cindex++;cod[cindex] = '1';cindex++;cod[cindex] = '1';cindex++;cod[cindex] = '4';}else{t = LR0[x][y][0]-'0';cindex++;cod[cindex] = LR0[x][y][0];}con.push(t);printf("%-10d\n",t);}else{int t = LR0[x][y][0]-'0';char ch = ' ';printf("%-10c%-10d\n",ch,t);con.push(t);cindex++;cod[cindex] = LR0[x][y][0];sindex++;sti[sindex] = 'E';LR++;}}else{error(x,y);return ;///报错}}}
void chart()///测试表函数
{printf("-\t+\t-\t*\t/\ti\t(\t)\t#\tE\tT\tF\n");for(int i = 0; i <= 15; i++){printf("%d",i);for(int j = 0 ; j <= 11; j++)printf("\t%s",LR0[i][j]);cout<<endl;}cout<<endl;
}
int main()
{chart();con.push(0);cmp.push('#');char str[200];///输入串cout<<"请输入字符串(带#):"<<endl;cin>>str;int len = strlen(str);//输入串长度 analyze(str,len);return 0;
}

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

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

相关文章

C语言种sizeof()和strlen的区别

sizeof 是 C 语言内置的操作符关键字&#xff0c;而 strlen 是 C 语言库函数&#xff1b; sizeof 仅用于计算数据类型的大小或者变量的大小&#xff0c;而 strlen 只能以结尾为 \0 的字符串作为参数&#xff1b; 编译器在编译时就计算出了 sizeof 的结果&#xff0c;而 strlen …

Spring Security的开发

文章目录 1,介绍2, 核心流程3, 核心原理3.1 过滤器链机制3.2 主体3.3 认证3.4 授权3.5 流程图4, 核心对象4.1 UserDetailsService 接口4.2 PasswordEncoder 接口4.3 hasAuthority方法4.4 hasAnyAuthority方法4.5 hasRole方法4.5 hasAnyRole方法5, 核心注解5.1 @PreAuthorize5.1…

【Linux】系统开启和关闭过程

Linux 系统启动过程 BIOS 自检&#xff1a;在计算机开机时&#xff0c;BIOS 会进行自检&#xff0c;检查硬件设备是否正常。 加载引导程序&#xff1a;BIOS 自检完成后&#xff0c;会加载引导程序&#xff0c;如 GRUB、LILO 等。引导程序会加载内核和初始化 RAM 磁盘&#xff…

想入门Web测试,看这篇文章!

今天要谈的是很多软件测试工程师都需要面对的——Web测试 不管你是处在二十不惑的青春有你阶段还是三十而已的乘风破浪阶段我们都需要面对“Web测试”。 Web测试其实有以下几个方面&#xff1a; 1、页面测试 大多数的Web网站的网页都是html语言编写的&#xff0c;测试工程师…

HTML世界之标签Ⅳ

目录 一、ins 标签 二、kbd 标签 三、label 标签 四、link 标签 五、main 标签 六、map 标签 七、mark 标签 八、meta 标签 一、ins 标签 <ins> 标签定义已经被插入文档中的文本。 属性 值 描述 语法 cite URL 规定一个文档的 URL&#xff0c;该文档解释了…

3.3 RK3399项目开发实录-板载Ubuntu系统的使用(wulianjishu666)

嵌入式物联网常用90款传感器开发例程。链接&#xff1a;https://pan.baidu.com/s/1oisHMZXDzKqa4EspY83V-A?pwdo5f4 1. 介绍 Ubuntu 使用手册是针对 Firefly 官方发布的 Ubuntu 系统固件特性所编写&#xff0c;适用于 Ubuntu Desktop 与 Minimal 系统&#xff0c;部分与 UI 显…

开源文本挖掘引擎:情感分析|API接口|可私有化部署

中文的表达方式五花八门&#xff0c;比如成语、俗语、还有那些让人哭笑不得的双关语&#xff0c;这些都让情感分析变得复杂。再者&#xff0c;中文里头的情感表达很多时候得看上下文&#xff0c;一句话放在不同的情景里&#xff0c;意思可能就大相径庭了。 中文里面的否定和讽…

openGauss学习笔记-245 openGauss性能调优-SQL调优-典型SQL调优点-算子级调优

文章目录 openGauss学习笔记-245 openGauss性能调优-SQL调优-典型SQL调优点-算子级调优245.1 算子级调优245.1.1 算子级调优介绍245.1.2 算子级调优示例 openGauss学习笔记-245 openGauss性能调优-SQL调优-典型SQL调优点-算子级调优 SQL调优是一个不断分析与尝试的过程&#x…

Vector Magic:矢量图像转换神器,轻松驾驭Mac与Win双平台

在数字化时代&#xff0c;图像已经成为我们生活和工作中不可或缺的一部分。无论是设计师、艺术家&#xff0c;还是普通用户&#xff0c;都对图像质量有着极高的要求。而矢量图像&#xff0c;以其清晰度高、可无限放大的特点&#xff0c;逐渐受到广大用户的青睐。今天&#xff0…

长安链正式发布三周年,技术更迭支撑产业变革

导语&#xff1a; 2024年1月27日长安链正式发布三周年&#xff0c;开源社区借开年之际与大家一同回顾长安链三年来的技术发展历程&#xff0c;每一个里程碑的建设都得益于与长安链同行的合作伙伴与开发者&#xff0c;希望在2024年可以共同携手继往开来&#xff0c;为数字经济发…

跨域的几种方式?(详解)

跨域&#xff08;Cross-Origin&#xff09;指的是在浏览器环境中&#xff0c;当一个网页的 JavaScript 代码试图访问不同源&#xff08;Origin&#xff09;的资源时发生的安全限制。同源策略&#xff08;Same-Origin Policy&#xff09;要求网页只能与同一源&#xff08;协议、…

python类多态的理解

类多态(Class Polymorphism)是面向对象编程中的一个重要概念,它允许我们使用父类的引用变量来引用子类的对象,从而实现不同子类对象的统一处理。 在Python中,类多态可以通过以下方式实现: 1. 继承:子类可以继承父类的方法和属性,并且可以重写父类的方法,即子类可以拥…

2024腾龙杯web签到题-初识jwt(签到:这是一个登录页面)

什么是 jwt? 它是 JSON Web Token 的缩写&#xff0c;是一个开放标准&#xff0c;定义了一种紧凑的、自包含的方式&#xff0c;用于作为JSON对象在各方之间安全地传输信息&#xff0c;该信息可以被验证和信任&#xff0c;因为它是数字签名的。它就是一种认证机制&#xff0c;…

Kotlin: 协程的四种启动模式(CoroutineStart)

点击查看CoroutineStart英文文档 创建协程的三种方式 runBlocking 运行一个协程并且会阻塞当前线程&#xff0c;直到它完成。launch 启动一个新的协程&#xff0c;不会阻塞当前线程&#xff0c;并且返回一个Job&#xff0c;可以取消。async async和await是两个函数&#xff0c…

词令微信小程序怎么添加到我的小程序?

微信小程序怎么添加到我的小程序&#xff1f; 1、找到并打开要添加的小程序&#xff1b; 2、打开小程序后&#xff0c;点击右上角的「…」 3、点击后底部弹窗更多选项&#xff0c;请找到并点击「添加到我的小程序」&#xff1b; 4、添加成功后&#xff0c;就可以在首页下拉我的…

Elasticsearch:使用 OpenAI、LangChain 和 Streamlit 的基于 LLM 的 PDF 摘要器和 Q/A 应用程序

嘿&#xff01; 您是否曾经感觉自己被淹没在信息的海洋中&#xff1f; 有这么多的书要读&#xff0c;而时间却这么少&#xff0c;很容易就会超负荷&#xff0c;对吧&#xff1f; 但猜猜怎么了&#xff1f; 你可以使用大型语言模型创建自定义聊天机器人&#xff0c;该模型可以帮…

CTF题型 Http请求走私总结Burp靶场例题

CTF题型 Http请求走私总结&靶场例题 文章目录 CTF题型 Http请求走私总结&靶场例题HTTP请求走私HTTP请求走私漏洞原理分析为什么用前端服务器漏洞原理界定标准界定长度 重要!!!实验环境前提POST数据包结构必要结构快速判断Http请求走私类型时间延迟CL-TETE-CL 练习例题C…

开发遇到的bug:设置好的请求头不起作用

前言&#xff1a;有个接口的请求头是content-type: "application/json"&#xff0c;我已经在拦截器里设置添加了该请求头&#xff0c;但实际请求却一直是content-type:application/x-www-form-urlencoded 问题&#xff1a;封装请求函数的文件有两个&#xff0c;相当于…

【XR806开发板试用】WSL环境搭建问题及解决措施

本文主要记录在WSL环境下搭建XR806开发环境的过程中遇到的一些问题&#xff0c;如果后续大家有遇到类似问题可以参考&#xff1b;有部分地方的解决方法不一定是最好的&#xff0c;有些步骤也不一定是必要的&#xff0c;经过多次尝试和资料查询才最终解决&#xff0c;因此没有特…

深入解析分布式ID生成机制

一、概述 背景&#xff1a;随着数据库数据量的增长, 基于性能原因需要进行分库分表&#xff0c;分库分表会导致主键ID重复问题。 特点&#xff1a; 全局唯一性[必须];趋势递增[非必须]。由于互联网大部分采用Mysql的Innodb引擎,因此保持有序主键ID有利于insert的效率;单调递增…