编译原理实验2(自上而下语法分析)

news2024/11/16 0:25:51

一、实验目的

  1. 给出 PL/0 文法规范,要求编写 PL/0 语言的语法分析程序。
  2. 通过设计、编制、调试一个典型的自上而下语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析,进一步掌握常用的语法分析方法。
  3. 选择有代表性的语法分析方法,如LL(1)文法分析;
  4. 选择对各种常见程序语言都具备的语法结构,如赋值语句,特别是表达式,作为分析对象。
  5. 提高自己的实践能力和解决问题的能力。

二、实验原理

  1. 了解符已给 PL/0 语言文法,构造表达式部分的语法分析器。

分析对象〈算术表达式〉的 BNF 定义如下:

<表达式> ::= [+|-]<项>{<加法运算符> <项>}

 <项> ::= <因子>{<乘法运算符> <因子>}

<因子> ::= <标识符>|<无符号整数>| ‘(’<表达式>‘)’

<加法运算符> ::= +|-

<乘法运算符> ::= *|/

<关系运算符> ::= =|#|<|<=|>|>=

  1. 将实验一“词法分析”的输出结果,作为表达式语法分析器的输入,进行语法解析,对于语法正确的表达式,输出“语法正确”;对于语法错误的表达式,输出“语法错误”,指出错误原因。

三、实验内容

1.了解符已给 PL/0 语言文法,构造表达式部分的语法分析器。

分析对象〈算术表达式〉的 BNF 定义如下:

<表达式> ::= [+|-]<项>{<加法运算符> <项>}

 <项> ::= <因子>{<乘法运算符> <因子>}

<因子> ::= <标识符>|<无符号整数>| ‘(’<表达式>‘)’

<加法运算符> ::= +|-

<乘法运算符> ::= *|/

<关系运算符> ::= =|#|<|<=|>|>=

2.将实验一“词法分析”的输出结果,作为表达式语法分析器的输入,进行语法解析,对于语法正确的表达式,输出“语法正确”;对于语法错误的表达式,输出“语法错误”,指出错误原因。

3.输入:

4.输出:

四、实验算法流程图

  1. 算法思想

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

  1. LL(1)文法的判别需要依次计算FIRST集、FOLLOW集和SELLECT集,然后判断是否为LL(1)文法,然后再进行句子分析。
  2. 需要预测分析器对所给句型进行识别。即在LL(1)分析法中,每当在符号栈的栈顶出现非终极符时,要预测用哪个产生式的右部去替换该非终极符;当出现终结符时,判断其与剩余输入串的第一个字符是否匹配,如果匹配,则继续分析,否则报错。LL(1)分析方法要求文法满足如下条件:对于任一非终极符A的两个不同产生式A→a,A→β,都要满足下面条件:SELECT(A→a)n SELECT(A→p)=O
  1. 设计思想

扩充的巴克斯范式

<表达式> ::= [+|-]<项>{<加法运算符> <项>}

<项> ::= <因子>{<乘法运算符> <因子>}

<因子> ::= <标识符>|<无符号整数>| ‘(’<表达式>‘)’

<加法运算符> ::= +|-

<乘法运算符> ::= *|/

普通的巴克斯范式

  为表示方便:

  表达式E、项X、因子Y、标识符b,无符号整数z,加法运算符A,乘法运算符C

E->AX|X|EAX

X->Y|XCY

Y->b|z|(E)

A->+|-

C->*|/

消除左递归

E->XE’|AXE’

E’->AXE’|ε

X->YX’

X’->CYX’|ε

Y->b|z|(E)

A->+|-

C->*|/

改进后的文法满足LL(1)文法条件,所以该文法是LL(1)的。

手动求了First集和Follow集,方便后面进行程序的验证。

FIRST和FOLLOW集合

FIRST(E)={b,z,(,+,-}   FOLLOW(E)={#,)}

FIRST(E’)={ε,+,-}    FOLLOW(E’)={#,)}

FIRST(X)={b,z,(}       FOLLOW(X)={+,-,#,)}

FIRST(X’)={ε,,/}     FOLLOW(X’)={+,-,#,)}

FIRST(Y)={b,z,(}       FOLLOW(Y)={,/,+,-,#}

FIRST(A)={+,-}         FOLLOW(A)={b,z,(}

FIRST©={,/}            FOLLOW©={b,z,(}

  1. 关键步骤

构建预测分析表。要构建预测分析表就要根据产生式来生成三个集合First set, Follow Set, Select Set

  1. First set的构建

功能:对一个给定的非终结符,通过一系列语法推导后,能出现在推导表达式最左端的所有终结符的集合,统称为该非终结符的FIRST SET。

  1.  如果A是一个终结符,那么FIRST(A)={A}
  2. 对于以下形式的语法推导:

S -> a B

S是非终结符,a是终结符,B是零个或多个终结符或非终结符的组合,那么 a属于 FIRST(S).

  1. 对于推导表达式:

s -> b a

s 和 b 是非终结符,而且b 不是nullable的,那么first(s) = first(b)

  1. 对于推导表达式:

s -> a1 a2 … an b

如果a1, a2 … an 是nullable 的非终结符,b是非终结符但不是nullable的,或者b是终结符,那么

first(s) 是 first(a1)… first(an) 以及first(b)的集合。

  1. Follow Set的构建

对于某个非终结符通过一系列推导变换后,某个终结符出现在该非终结符的后面,那么我们称该终结符属于对应非终结符的FOLLOW SET。

  1. 先计算每一个非终结符的first set,并把每个非终结符的follow set设置为空.
  2. 对于表达式 s -> …a b…, a 是一个非终结符,b 是终结符或非终结符, 那么FOLLOW(a) 就包含 FIRST(b).
  3. 对于表达式 s->…a a1 a2 a3… an b…, 其中a是非终结符,a1, a2 a3… an 是nullable的非终结符,b是终结符或非nullable的非终结符,那么FOLLOW(a) 包含FIRST(a1)… FIRST(an) FIRST(b)的集合。
  4. 对于表达式s -> … a 其中a是非终结符,而且a出现在右边推导的最后面,那么FOLLOW(a) 包含 FOLLOW(s)
  5. 对于表达式 s -> a a1 a2…an ,其中a是非终结符而且不是nullable的,a1 a2…an 是nullable的非终结符,那么FOLLOW(a), FOLLOW(a1)…FOLLOW(an) 都包含FOLLOW(s)

  1. Select Set的构建

对于标号为N的推导表达式s->a,以及当前输入T,那么Selest(N)要包括T的话,当栈顶元素是s,且输入为T时,要使用推导表达式N来进行下一步推导。

  1. 计算所以非终结符的first set 和follow set.
  2. 对应非nullable的表达式 , s -> a b… 其中s是非终结符,a 是一个或多个nullable的非终结符,b是终结符或是非终结符但不是nallable的,b后面可以跟着一系列符号,假设其标号为N,那么该表达式的选择集就是FIRST(a) 和 FIRST(b)的并集。如果a不存在,也就是b的前面没有nullable的非终结符,那么SELECT(N) = FIRST(b).
  3. 对应nullable的表达式: s -> a, s是非终结符,a是零个或多个nullable非终结符的集合,a也可以是ε,假设该表达式标号为N,那么SELECT(N)就是 FIRST(a) 和 FOLLOW(s)的并集。由于a可以是0个非终结符,也就是s -> ε,从而s可以推导为空,如果s推导为空时,那么我们就需要看看当前输入字符是不是FOLLOW(s),也就是跟在s推导后面的输入字符,如果是的话,我们才可以采用s->ε,去解析当前输入。
  1. 构建完整的预测分析表
  1. 将解析表所有元素初始化为-1
  2. for (每一个推导表达式 N) {

lhs = 推导表达式箭头左边的非终结符

for (对应每一个在SELECT(N)中的token) {

parse_table[lhs][token] = N

}

}

  1. 算法流程

LL(1)大概的工作流程:

1)将开始符号压入栈中

2)根据输入符号和分析表来选择产生式

3)把产生式都压入栈中

4)如果当前栈顶是终结符,就进行匹配

5)匹配失败退出,成功则读入,再回到第二个步骤

  • 实验结果与分析
  1. 编译成功

用例1

用例2

itc验证

递归下降分析也成功。

根据程序运行得到的结果可以看出:编写的代码正确。

  • 实验体会

第二次编译原理的实验课,最大的收获是复习了LL(1)文法的相关知识,从代码的层面深入的学习了符号表的建立与使用,同样提高了动手写代码的熟练程度。

这次实验难度不大,主要是理解和掌握建立FIRST集、FOLLOW集、SELECT集等操作,以及对预测分析表的理解对编写代码尤为重要。

这次编译原理实验课,总结上一次实验课的经验与教训:理解好项目给出的数据结构,以及演示模式程序执行的步骤和输出结果,熟练掌握数据结构的相关知识是完成代码的关键。

总的来说,通过这次实验课,既加深了我对编译原理课程重点内容的理解,又复习了数据结构、c/c++的相关知识,提高了编写代码的能力,收获良多。

最后,特别感谢刘老师一直以来的耐心指导和同学的热心帮助!

  • 附录

代码如下

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

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

相关文章

一款轻量、干净的 Vue 后台管理框架

开始之前 在开始介绍之前我想谈谈为什么要自己做一个后台管理&#xff0c;我知道很多人都用一些开源的后台管理项目&#xff0c;这些老前辈有很多亮点值得学习&#xff0c;但是存在的一些问题同样不可忽视&#xff0c;我认为很多开发者会被困扰(仅代表个人观点) 技术栈老旧不升…

面试(03)————多线程和线程池

一、多线程 1、什么是线程?线程和进程的区别? 2、创建线程有几种方式 &#xff1f; 3、Runnable 和 Callable 的区别&#xff1f; 4、如何启动一个新线程、调用 start 和 run 方法的区别&#xff1f; 5、线程有哪几种状态以及各种状态之间的转换&#xff1f; 6、线程…

Docker容器与虚拟化技术:OpenEuler 部署 ES 与 Kibana

目录 一、实验 1.环境 2.OpenEuler 部署 ES (EalasticSearch) 3.OpenEuler 部署 Kibana 4.部署 Elasticvue插件 5.使用cpolar内网穿透 6.使用Elasticvue 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 系统架构版本IP备注LinuxopenEuler22.03 LTS SP2 1…

flex布局align-items和align-content、justfiy-content的区别

justfiy-content&#xff1a;定义主轴的对齐方式align-items&#xff1a;定义交叉轴的对齐方式align-content&#xff1a;将flex子项作为一个整体起作用 只在两种情况下有效果&#xff1a; ①子项多行且flex容器高度固定 ②子项单行&#xff0c;flex容器高度固定且设置了fle…

Mac安装配置Appium

一、安装 nodejs 与 npm 安装方式与 windows 类似 &#xff0c;官网下载对应的 mac 版本的安装包&#xff0c;双击即可安装&#xff0c;无须配置环境变量。官方下载地址&#xff1a;https://nodejs.org/en/download/ 二、安装 appium Appium 分为两个版本&#xff0c;一个是…

HarmonyOS实战开发-屏幕属性(仅对系统应用开放)

介绍 本示例主要展示了屏幕管理相关的功能&#xff0c;使用ohos.display、ohos.screen接口&#xff0c;ohos.display接口提供获取默认display对象、获取所有display对象&#xff0c;开启监听、关闭监听功能&#xff1b;ohos.screen接口提供创建虚拟屏幕、销毁虚拟屏幕、扩展屏…

LeetCode-热题100:118. 杨辉三角

题目描述 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]] 示例 2: 输入: numRows 1 输出: [[1]]…

什么软件可以保密公司文件?

#天锐绿盾# 天锐绿盾是一款专为企业设计的文件加密与数据防泄密软件&#xff0c;旨在通过一系列高级安全功能来保护公司的敏感信息和重要文件不被未经授权的访问、窃取或泄露。 PC地址&#xff1a; https://isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c5dfe…

蓝奏云直链获取在线解析网站源码

源码简介 蓝奏云直链获取在线解析网站源码 蓝奏云链接解析 本地API接口 支持有无密码和短期直链和永久直链&#xff0c;同时还可以显示文件名和大小。 这个解析器无需数据库即可搭建&#xff0c;API接口已经本地化&#xff0c;非常简单易用。 安装环境 php5.6 搭建教程 …

HTML - 你如何使H5页面禁止手动缩放

难度级别:初级及以上 提问概率:40% 我们知道,这道题其实是在考察meta标签的viewport属性,正常情况下设置viewport的代码为 <head><meta name="viewport" content="width=device-width,initial-scale=1.0" …

全网最详细的网络安全自学笔记

1.选择方向 首先是选择方向的问题&#xff0c;网络安全是一个很宽泛的专业&#xff0c;包含的方向特别多。比如 web安全&#xff0c;系统安全&#xff0c;无线安全&#xff0c;二进制安全&#xff0c;运维安全&#xff0c;渗透测试&#xff0c;软件安全&#xff0c;IOT安全&am…

【运输层】网络数据报协议 UDP

目录 1、UDP 的特点 2、UDP 的首部格式 UDP 只在 IP 协议之上增加了很少的一些功能&#xff0c;比如复用、分用以及差错检测等。 1、UDP 的特点 UDP是无连接的&#xff0c;即发送数据之前不需要建立连接&#xff0c;因此减少了开销和发送数据之前的时延。 UDP使用尽最大努力…

python函数练习2

找出10000以内能被5或6整除&#xff0c;但不能被两者同时整除的数&#xff08;函数&#xff09; def func():for i in range(1,50):if (i % 5 0 or i % 6 0 ):if i % 5 0 and i % 6 0:continue #利用continue跳过能被5和6整除的数print(i) func()写一个方法&#xff0c;计算…

Windbg查看函数调用过程中的内存布局

我们在分析问题的时候经常会需要查看进程的栈和帧中的值&#xff0c;下面我们就用一个简单的例子来分析一下这个过程。 源代码&#xff1a; #include <iostream> int add(int a, int b) {return a b; }int main() {int a, b;a 3;b 4;int ret add(a, b);std::cout &…

【Python】快速排序法 Leetcode 148. 排序链表

题目 给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [4,2,1,3] 输出&#xff1a;[1,2,3,4] 代码 第一次使用朴素快速排序&#xff0c;基准值为头节点值&#xff0c;居然超时了&#xff0c;然后…

pymilvus创建IVF_FLAT向量索引

索引简介 索引的作用是加速大型数据集上的查询。 目前&#xff0c;向量字段仅支持一种索引类型&#xff0c;即只能创建一个索引。 milvus支持的向量索引类型大部分使用近似最近邻搜索算法(ANNS,approximate nearest neighbors search) 。ANNS 的核心思想不再局限于返回最准确…

什么是数据治理?你都了解吗?

在当今数字化时代&#xff0c;数据已成为企业重要的战略资产。有效管理数据对于企业提高运营效率、降低成本、做出更好的决策至关重要。数据治理作为一种重要的管理方法&#xff0c;可以帮助企业确保数据的质量、安全、合规性和有效利用。 一、数据治理的定义与重要性 近日&a…

2024.4.6-day11-CSS 背景和精灵图

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 作业2024.4.6学习笔记1 背景2 背景图片3 CSS 精灵图 作业 <!DOCTYPE html&…

C语言初阶—9函数

函数的声明 &#xff08;main函数前&#xff09;----告诉有一个函数 格式&#xff1a; 类型 函数名&#xff08;参数&#xff09;&#xff1b; 函数的声明 放到头文件add.c 函数的定义 ----创建函数----放到add.c 格式&#xff1a;类型 函数名(参数) { 语句项; } 在文…

【Qt 学习笔记】使用两种方式实现helloworld

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 使用两种方式实现helloworld 文章编号&#xff1a;Qt 学习笔记 / 05 …