编译器-PL0解释程序

编译器-PL0解释程序

这次实验不再进行详细说明,参考资料中都讲的很好,主要针对难点进行阐述,难点懂了,这个实验几乎就完成了 ✅。

难点


这次实验我一直搞不懂 DL 和 SL 的区别,看了文章也还没搞懂,最终最终问了 AI,让它帮我详细解释解释,才慢慢搞懂。

其实,结合代码来讲是最“形象”🉐。以下的代码来自我的PL0-Compiler仓库中的测试样例 2。

var x;
procedure B;
var y;
beginy := x;
end;procedure A;
begincall B;
end;beginx := 1;call A;
end.

上述代码的调用关系为:

  • 主函数(main)–调用->A
  • A–调用->B

SL 静态链和 DL 动态链都记录了当前层的上一层的信息,但这上一层和上一层之间也并不是完全一样。

  • SL 静态链:从代码中看程序的嵌套结构,过程 A 和 B 的上一层都是主程序,它们都是在主程序中定义的过程。

  • DL 动态链:从(函数)调用的角度看,因为主程序调用了 A,所以主程序是 A 的上一层,又因为 A 调用了 B,所以 A 又是 B 的上一层。这就有点不一样了,B 的上一层在代码层面明明是主程序,而在这里却成了 A。

这次我们发现了 DL 和 SL 的不同。而我们进行变量查找时,当前层次没找到,沿着静态链 SL 去上一层查找。我们进行过程(函数)返回时,需要恢复基址寄存器,这时是按照 DL 返回的。

DL (动态链):

  • 记录的是调用关系(运行时动态调用的顺序)。
  • 表示调用者,只知道当前子程序是由哪一个子程序调用的。
  • 回溯关系是 动态的,依赖实际的调用栈。

SL (静态链):

  • 记录的是词法作用域关系(程序的嵌套结构)。
  • 表示定义者,知道当前子程序是在哪一个作用域中定义的。
  • 回溯关系是 静态的,依赖编译时的嵌套层次。

执行过程模拟(手动


上述的代码生成的中间代码为:

// 指令数组
codelist:
0 F: JMP L: 0 A: 10
1 F: JMP L: 0 A: 2
2 F: INT L: 0 A: 4
3 F: LOD L: 1 A: 3
4 F: STO L: 0 A: 3
5 F: OPR L: 0 A: 0
6 F: JMP L: 0 A: 7
7 F: INT L: 0 A: 3
8 F: CAL L: 1 A: 1
9 F: OPR L: 0 A: 0
10 F: INT L: 0 A: 4
11 F: LIT L: 0 A: 1
12 F: STO L: 0 A: 3
13 F: CAL L: 0 A: 6
14 F: OPR L: 0 A: 0

符号表:

{address=3, level=1, kind=SYM_VAR, name=x}
{address=1, level=1, kind=SYM_PROCEDURE, name=B}
{address=3, level=2, kind=SYM_VAR, name=y}
{address=6, level=1, kind=SYM_PROCEDURE, name=A}

因为这个程序比较简单,下面我们手动模拟一遍:

先定义各个寄存器和栈空间:

B:0 // 基址寄存器
T:-1 // 栈顶指针
code:null // 要执行的指令
P:0 // 要执行的下一条指令的下标(指令数组的下标null
stack

首先,获取 JMP 无条件跳转指令

B:0
T:-1
code:JMP,0,10 // 会修改P
P:10null
stack

跳转到第 10 条指令,分配栈空间

B:0
T:3
code:INT,0,4
P:113 0 x  <- T
2 0 RA
1 0 DL
0 0 SL <- B
stack

将常量 1 放入栈顶

B:0
T:4
code:LIT,0,1
P:124 1 常量 <- T
3 0 x
2 0 RA
1 0 DL
0 0 SL  <- B
stack

将常量存储到变量 x 中

B:0
T:3
code:STO,0,3
P:134 1 常量
3 1 x  <- T
2 0 RA
1 0 DL
0 0 SL <- B
stack

调用 A

B:4
T:4
code:CAL,0,6
P:76  14  RA
5  0   DL
4  0   SL <- T/B
3  1   x
2  0   RA
1  0   DL
0  0   SL
stack

跳转

B:4
T:4
code:JMP,0,7
P:76  14  RA
5  0   DL
4  0   SL <- T/B
3  1   x
2  0   RA
1  0   DL
0  0   SL
stack

分配空间

B:4
T:6
code:INT,0,3
P:86  14  RA <- T
5  0   DL
4  0   SL <- B
3  1   x
2  0   RA
1  0   DL
0  0   SL
stack

调用 B

B:7
T:7
code:CAL,1,1
P:19  9   RA
8  4   DL
// 通过代码中get_sl计算
7  0   SL <- T/B
6  14  RA
5  0   DL
4  0   SL
3  1   x
2  0   RA
1  0   DL
0  0   SL
stack

跳转指令

B:7
T:7
code:JMP,0,2
P:29  9   RA
8  4   DL
7  0   SL <- T/B
6  14  RA
5  0   DL
4  0   SL
3  1   x
2  0   RA
1  0   DL
0  0   SL
stack

分配空间

B:7
T:10
code:INT,0,4
P:310 0   y  <- T
9  9   RA
8  4   DL
7  0   SL <- B
6  14  RA
5  0   DL
4  0   SL
3  1   x
2  0   RA
1  0   DL
0  0   SL
stack

将 x 的值移到栈顶

B:7
T:11
code:LOD,1,3 //层差是1,需要沿着SL到上一层(main),然后获取B+3(在这里为3)地址x的值
P:411 1   x  <- T
10 0   y
9  9   RA
8  4   DL
7  0   SL <- B
6  14  RA
5  0   DL
4  0   SL
3  1   x
2  0   RA
1  0   DL
0  0   SL
stack

将栈顶的值存到变量 y 中

B:7
T:10
code:STO,0,3
P:511 1   x
10 1   y  <- T
9  9   RA
8  4   DL
7  0   SL <- B
6  14  RA
5  0   DL
4  0   SL
3  1   x
2  0   RA
1  0   DL
0  0   SL
stack

过程返回

B:4
T:6
code:OPR,0,0
P:911 1   x
10 1   y
9  9   RA
8  4   DL
7  0   SL
6  14  RA <- T
5  0   DL
4  0   SL <- B
3  1   x
2  0   RA
1  0   DL
0  0   SL
stack

过程返回

B:0
T:3
code:OPR,0,0
P:1411 1   x
10 1   y
9  9   RA
8  4   DL
7  0   SL
6  14  RA
5  0   DL
4  0   SL
3  1   x  <- T
2  0   RA
1  0   DL
0  0   SL <- B
stack

程序结束

B:0
T:-1
code:OPR,0,0
P:0 // 程序结束11 1   x
10 1   y
9  9   RA
8  4   DL
7  0   SL
6  14  RA
5  0   DL
4  0   SL
3  1   x
2  0   RA
1  0   DL
0  0   SL <- B
stack

参考资料


  • 编译原理课设尝试(一)——PL/0 编译器分析
  • PL\0 编译原理实验(南航)四:中间代码的解释器
  • 完整代码:https://github.com/jacket-mouse/PL0-Compiler

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

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

相关文章

【模型级联】YOLO-World与SAM2通过文本实现指定目标的零样本分割

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

Postman之变量操作

系列文章目录 Postman之变量操作 1.pm.globals全局变量2.pm.environment环境变量3.pm.collectionVariables集合变量4.pm.variables5.提取数据-设置变量-进行参数化串联使用 postman中分为全局变量、环境变量、集合变量、和普通变量 分别使用pm.globals、pm.environment、pm.co…

linux 常用命令指南(存储分区、存储挂载、docker迁移)

前言&#xff1a;由于目前机器存储空间不够&#xff0c;所以‘斥巨资’加了一块2T的机械硬盘&#xff0c;下面是对linux扩容的一系列操作&#xff0c;包含了磁盘空间的创建、删除&#xff1b;存储挂载&#xff1b;docker迁移&#xff1b;anaconda3迁移等。 一、存储分区 1.1 …

python读取Oracle库并生成API返回Json格式

一、安装必要的库 首先&#xff0c;确保已经安装了以下库&#xff1a; 有网模式 pip install flask pip install gevent pi install cx_Oracle离线模式&#xff1a; 下载地址&#xff1a;https://pypi.org/simple/flask/ # a. Flask Werkzeug-1.0.1-py2.py3-none-any.whl J…

Nature子刊 | 单细胞测序打开发育系统溯源新视角

神经系统是人体最为复杂且最为重要的器官之一。深入理解神经发育对于神经科学研究和再生医学具有举足轻重的作用。但神经元多样性的起源仍是一个亟待解决的难题。日益发展的单细胞测序技术让研究人员们有机会从细胞的异质性入手&#xff0c;对不同细胞类型之间的关联和分化路径…

5G CPE与4G CPE的主要区别有哪些

什么是CPE&#xff1f; CPE是Customer Premise Equipment&#xff08;客户前置设备&#xff09;的缩写&#xff0c;也可称为Customer-side Equipment、End-user Equipment或On-premises Equipment。CPE通常指的是位于用户或客户处的网络设备或终端设备&#xff0c;用于连接用户…

新增道路查询最短路径

一、问题描述 给你一个整数 n 和一个二维整数数组 queries。 有 n 个城市&#xff0c;编号从 0 到 n - 1。初始时&#xff0c;每个城市 i 都有一条单向道路通往城市 i 1&#xff08; 0 < i < n - 1&#xff09;。 queries[i] [ui, vi] 表示新建一条从城市 ui 到城市…

【数据结构】链表解析与实战运用(1.8w字超详细解析)

目录 引言 链表概念及结构 链表的优缺点 链表的分类 1.单向或者双向 2.带头或者不带头 3.带循环或者非循环 单链表接口函数的实现 接口函数一览 创建空节点&打印链表 尾部插入 头部插入 尾部删除 头部删除 查找 在pos位置之后插入节点 在pos位置之前插入节…

Python练习31

Python日常练习 题目&#xff1a; 分别输入两个整数以及一个加减乘除中的算术运算符&#xff0c;输出运算结果&#xff0c; 若输入其它运算符&#xff0c;则退出程序; 例如&#xff1a; 输出格式如下 【输入一个整数&#xff1a;】1 【输入另一个整数&#xff1a;】2 …

uniapp 自定义加载组件,全屏加载,局部加载 (微信小程序)

效果图 全屏加载 页面加载使用 局部加载 列表加载里面使用 使用gif html <template><view><view class"" v-if"typeFullScreen"><view class"loading" v-if"show"><view class""><i…

Mac 修改默认jdk版本

当前会话生效 这里演示将 Java 17 版本降低到 Java 8 查看已安装的 Java 版本&#xff1a; 在终端&#xff08;Terminal&#xff09;中运行以下命令&#xff0c;查看已安装的 Java 版本列表 /usr/libexec/java_home -V设置默认 Java 版本&#xff1a; 找到 Java 8 的安装路…

动态规划-最长公共子序列

题目 最长公共子序列 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长公共子序列的长度。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串在不改变字符的相对顺序的情况下删除某些字符&#xff08;也可以不删除任何字符&#xff0…

nvm安装node遇到的若干问题(vscode找不到npm文件、环境变量配置混乱、npm安装包到D盘)

问题一&#xff1a;安装完nvm后需要做哪些环境变量的配置&#xff1f; 1.打开nvm文件夹下的setting文件&#xff0c;设置nvm路径和安装node路径&#xff0c;并添加镜像。 root: D:\software\nvm-node\nvm path: D:\software\nvm-node\nodejs node_mirror: https://npmmirror.c…

Zookeeper的简单使用Centos环境下

目录 前言 一、ZOokeeper是什么&#xff1f; 二、安装Zookeeper 1.进入官网下载 2.解压到服务器 3.配置文件 三.使用Zookeeper 3.1启动相关指令 3.2其他指令 3.3ACL权限 总结 前言 记录下安装zookeeper的一次经历 一、ZOokeeper是什么&#xff1f; ZooKeeper是一…

疫情中的图书馆管理:Spring Boot系统设计

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了疫情下图书馆管理系统的开发全过程。通过分析疫情下图书馆管理系统管理的不足&#xff0c;创建了一个计算机管理疫情下图书馆管理系统的方案。文章介绍了疫情下图…

Excel数据动态获取与映射

处理代码 动态映射 动态读取 excel 中的数据&#xff0c;并通过 json 配置 指定对应列的值映射到模板中的什么字段上 private void GetFreightFeeByExcel(string filePath) {// 文件名需要以快递公司命名 便于映射查询string fileName Path.GetFileNameWithoutExtension(fi…

网络(TCP)

目录 TCP socket API 详解 bind(): 我们的程序中对myaddr参数是这样初始化的: listen(): accept(): 理解accecpt的返回值: 饭店拉客例子 connect tcp服务器和udp类似的部分代码 把套接字设置为监听状态&#xff08;listen&#xff09; 测试 查看端口号和IP地址&…

了解鱼叉式网络钓鱼攻击的社会工程学元素

一提到网络攻击&#xff0c;你可能会想象一个老练的黑客躲在类似《黑客帝国》的屏幕后面&#xff0c;利用自己的技术实力积极入侵网络。然而&#xff0c;许多攻击的现实情况远比这平凡得多。 一封带有“未送达”等无害主题的简单电子邮件被放在员工的垃圾邮件文件夹中。他们心…

TS流详解

目录 TS流结构 PSI 节目关联表&#xff08;PAT Program Association Table&#xff09; 条件接收表&#xff08;CAT Conditional Access Table&#xff09; 节目映射表&#xff08;PMT Program Map Table&#xff09; 网络信息表&#xff08;NIT Nerwork Information Tabl…

【图像处理识别】数据集合集!

本文将为您介绍经典、热门的数据集&#xff0c;希望对您在选择适合的数据集时有所帮助。 1 CNN-ImageProc-Robotics 机器人 更新时间&#xff1a;2024-07-29 访问地址: GitHub 描述&#xff1a; 通过 CNN 和图像处理进行机器人对象识别项目侧重于集成最先进的深度学习技术和…