自己动手写basic解释器(一)

2023-11-13

自己动手写basic解释器

刺猬@http://blog.csdn.net/littlehedgehog






注: 文章basic解释源码摘自梁肇新先生的《编程高手箴言》(据他所说这个代码也是网上摘录的),源码解读参考《java编程艺术》。《java编程艺术》里面自然是java版了(可能旭哥更加适合点儿),我这里还是解读的C版basic解释器代码。



那些客套话咱就不扯那么多了,啥写编译器是多少程序员梦想阿,多牛逼阿之类云云这之类的话咱就不聊了,主要是这里是C(不是java),C程序没java那么多套路,直接单刀赴会了。


这个是我们要解释的程序主干源代码,先不妨也看看。+点击浏览+



好了既然我们是写basic解释器,那我们至少先要明白两件事情:第一,什么是解释器;第二,basic语法这个至少要了解大概吧。



第一,什么是解释器?


编译器大家应该都知道,GCC,VC++(当然这个不纯粹是编译器了),简单的说呢,编译器将程序的源代码转化为可执行代码的形式。通常情况下,这种可执行代码由计算机的CPU指令组成,因此可以直接在计算机上执行。而解释器就不同了,它顺序读入程序的源代码,然后依次执行每一条语句。因此,解释器并不真正将源代码转化为目标代码,而是直接执行程序。


第二,basic语法(以及我们为什么选择basic解释器作为编写目标)

先说第一个为什么写basic? 因为basic语法简单,你听名字也大概知道了,比如我不会选择advance作为编写目标,名字就比较吓人。

basic我们不来详细讲了,因为我们做得这个解释器本来就很小,没涉及到多少东东,有需要的可以google一下。这里先贴一小段代码,混个脸熟:


  1. PRINT "A Simple Small BASIC Program"   '打印字符串

  2. FOR X = 1 TO 10   'for循环

  3. GOSUB 100   '跳到标号100 语句执行  注意这里100是标号

  4. NEXT   '下一个x  表示x要加一

  5. END   ‘程序结束

  6. 100 PRINT X   '这里相当于C中函数
  7. RETURN   '返回
代码一目了然,我们解释器基本上也就处理这几个关键字。现在摆在我们面前的就是如何处理这些关键字,换句话来说,我们如何在程序读取到相应关键字时,做出相应反应了。比如 我们执行print,我们就要用printf把print后面的东东打印出来。这还比较好办,但是如果是一个for循环呢,我们又该如何处理?


关键字处理是个大麻烦,因为我们面对不同关键字,要做出不同反应来。这个还是后话,眼前我们还是把主要框架先看看。


第一步  装载源代码

用过gcc么?郁闷 gcc都没用过!看来在windows下生活滋润惯了,学计算机还是要来open source阵营阿,话扯远了。我们用gcc编译c文件时,都是gcc -o    target   source   。 所以我们也仿照这格式,直接用命令行 (图形界面我们就不用实现了,再说俺也不懂)。


  1. main (int argc,char *argv[])
  2. {
  3.     char *p_buf;
  4.     char *t;

  5.     if (argc!=2)  {
  6.         printf ("usage: %s <filename>/n",argv[0]);
  7.         exit (1);
  8.     }

  9.     /* allocate memory for the program */
  10.     if (!(p_buf=(char *)malloc(PROG_SIZE)))  {
  11.         printf ("allocation failure");
  12.         exit (1);
  13.     }

  14.     /* load the program to execute */
  15.     if (!load_program(p_buf,argv[1]))  exit(1);
  16. }

这里我们开辟一个PROG_SIZE大小空间,供装载程序源码用。然后我们把程序代码用 load_program函数装入内存。代码如下:

  1. /* Load a program */
  2. load_program (char *p,char *fname)
  3. {
  4.     FILE *fp;
  5.     int i=0;
  6.    
  7.     if (!(fp=fopen(fname,"rb")))  return 0;

  8.     i=0;
  9.     do  {
  10.         *p = getc(fp);
  11.         p++;i++;
  12.     } while (!feof(fp)&&i<PROG_SIZE);
  13.     *(p-2) = '/0';   /* null terminate the program  */
  14.     fclose (fp);
  15.     return 1;
  16. }
代码很简单。因为我们现在还没有开始处理语法,下面才是正式开始。






本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自己动手写basic解释器(一) 的相关文章

  • Gson.toString() 给出错误“IllegalArgumentException:多个名为 mPaint 的 JSON 字段”

    我想将自定义对象转换为字符串并保存在 SharedPreferences 中 这是我的最终目标 我尝试了下面的行但失败了 String matchString gson toJson userMatches Logcat 10 11 15
  • 使用比较器对对象进行排序给出空指针

    我正在尝试对包含 3 张卡的 ArrayList 进行排序 我正在用比较器来做这件事 这是否太过分了 Card getRank 返回 2 到 14 之间的整数 我完全不知道哪里出了问题 我之前已经成功完成了这个 并与我的其他代码进行了比较
  • Hibernate 自定义架构创建

  • 如何在 Groovy 中的 JSON Converter 方法中保留字母大小写?

    我正在尝试将 groovy 对象解析为 JSON 属性名称不遵循正确的驼峰式大小写形式 class Client String Name Date Birthdate 当我使用这个时 Client client new Client Nam
  • 匿名内部类显示不正确的修饰符

    据我了解 以下代码应该打印true作为输出 但是 当我运行这段代码时 它正在打印false 来自 Java 文档15 9 5 匿名类 https docs oracle com javase specs jls se8 html jls 1
  • 分析 ELF 部分和符号大小的工具

    我需要一种方法来分析 ARM 的 GCC 编译器的输出文件 我正在为裸机进行编译 并且我非常关心大小 我可以用arm none eabi objdump由交叉编译器提供 但如果存在用于此任务的工具 则解析输出并不是我渴望做的事情 您知道存在
  • RSA 加密-解密:BadPaddingException:数据必须以零开头

    对于一个被问了很多次的问题 我很抱歉向您询问您的技能 我有一个关于 RSA 加密的问题 我已经检查过有关此问题的其他主题 但没有找到任何有用的答案 我希望你能帮助我 我想读取一个文件 加密其内容 然后解密它并将这些解密的字节放入一个新文件中
  • PrintStream是有缓冲的,但是flush不会降低性能,而BufferedOutputStream会加速性能

    我预计由于 PrintStream 是缓冲的 通过在每次 print 之后添加刷新操作 速度性能应该会显着降低 但事实并非如此 如下面的代码片段所示 此外 将 PrintStream 包裹在 BufferedOutputStream 周围可
  • 在 javafx 中注册鼠标处理程序,但处理程序不是内联的

    我有一个 JavaFX 应用程序变得有点大 我想保持代码的可读性 我有一个折线图 我希望内置缩放功能 该功能在单击鼠标时发生 我知道我需要向图表注册鼠标侦听器 我无法从 Oracle 示例中弄清楚什么 即如下所示 http docs ora
  • 在 JSON 对象中强制执行非空字段

    我们的 REST API 接收一些 JSON 对象输入 其中某些字段要求不为空 这些可以是字符串 整数 甚至可以是其他一些类实例作为参考 我们正在尝试找到一种方法来强制这些字段不为空 而不是在 API 中进行空检查的正确方法 当前的 if
  • Java 中意外的负数

    import java util public class Prac9FibonacciNumbers public static void main String args int x new int 100 x 0 1 x 1 1 fo
  • 将传入字符串的 unicode 表示形式转换为 UTF-8?

    我正在读取一些已经转换为 html 样式 代码的数据 我现在需要将其转换回 UTF 8 字符以供查看 不幸的是我无法使用浏览器查看该字符串 我读过有关 java 中的转换的内容 似乎如果你有一个 uxxxx 字符串 那么编译器会为你转换 然
  • 获取证书链

    我正在 Java 中使用 X509 证书 给定一个证书 是否可以在签名层次结构中找到所有其他证书 直到找到根证书 我有一个证书文件 带有 cer扩展名 我想提取父签名证书 我想继续查找该证书的父证书 直到获得最终的自签名根证书 我已经检查了
  • 如何在Webview中保存用户名和密码

    目前 我还在学习Android开发的过程中 所以如果我的这个问题对你来说不太容易理解 请原谅 我创建了一个 Android 应用程序 它使用 RecyclerView 显示一组列表 当用户单击列表中的每个名称时 它会将它们重定向到一组不同的
  • 相当于 C# 中 Java 的“ByteBuffer.putType()”

    我正在尝试通过从 Java 移植代码来格式化 C 中的字节数组 在 Java 中 使用方法 buf putInt value buf putShort buf putDouble 等等 但我不知道如何将其移植到 C 我尝试过 MemoryS
  • 为什么 HttpServletRequest 输入流为空?

    我有这段代码 我从请求输入流读取输入并使用 JacksonMapper 转换为 POJO 它在具有 guice 支持的 jetty 7 容器中运行 Override protected void doPost HttpServletRequ
  • 在 Linux 上将 libquadmath 与 C++ 链接

    我有一个示例代码 include
  • 如何确保超类的子类方法的线程安全?

    我参加了一次面试 并被要求为以下要求设计一个课程 假设我有一个 A 类 它可以有任意数量的子类 即子类 类 A 有一个名为 doSomething 的方法 该方法是同步的 要求是 A 的所有子类都是强制性的重写 doSomething me
  • 如何正确使用Google Calendar API Events.Insert命令?

    所以我一直使用REST方法来调用Google的API 我需要将事件插入到我拥有 ID 的特定日历中 这是我发送的 POST 请求 地址 https www googleapis com calendar v3 calendars https
  • 在Java的System.out中以表格格式输出

    我正在从数据库获取结果 并希望将数据作为 Java 标准输出中的表输出 我尝试过使用 t 但我想要的第一列的长度变化很大 有没有办法将其显示在类似输出的漂亮表格中 Use System out format http java sun co

随机推荐

  • c taskspawn 需要申请堆栈的大小 怎么设置_FreeRTOS Task.h/Task.c详解

    刚入门 把自己的理解记录以下 ifndef INC FREERTOS H error include FreeRTOS h must appear in source files before include task h endif 在
  • vaware上安装Linux详细步骤(Slackware10.2)

    环境 HostOS Win2K SP4 GuestOS Slackware10 2 VMware Workstation 5 5 1 b19175 1 建立虚拟机 在VMware上新建一个2 4 x内核的Linux虚拟机 因为Slackwa
  • 消防图像火灾探测器原理

    消防图像火灾探测器是一种基于图像处理技术的先进火灾探测设备 它的工作原理是通过对火灾图像进行分析和识别 实现对火灾的早期探测和报警 这种火灾探测器采用了先进的计算机视觉技术 可以实时监测火灾发生的地点 并在火灾发生之初就能够及时发出警报 从
  • 永擎服务器主板稳定性,永擎双路服务器主板+Platinum铂金8124 8172M 8272CL 8222L套装...

    以下套餐均为单CPU价格 不含主板 不含内存 不要再重复问了 谢谢 套餐一 铂金Platinum 8251 正显版 2 12核24线程 基础频率3 8G 24线程满载4 0G 睿频4 2G 套餐二 铂金 3647 Platinum 8175
  • 如何调试VUE代码(VUE调试利器 vue devtools)

    前言 最新想开发一个前后端分离的项目 一直想开始的 拖延了好久终于决定要对它下手了 最早的时候开发的时候使用的还是JSP 那个时候使用的还是EL表达式 后来切换到Spring和SpringMVC之后采用的是HTML JS的all in on
  • python单元测试框架(继承、unittest参数化、断言、测试报告)

    一 继承 继承能解决什么问题 unittest每个模块都要用到前提条件以及清理 如果有上百个模块 我们要改域名和浏览器 就会工作量很大特别麻烦 这时我们可以用继承的思想只用改一次 我们可以将前提和清理提出来单独放到一个文件里 具体代码如下
  • 图论:Dijkstra算法——最详细的分析,图文并茂,一次看懂!

    文章目录 1 Dijkstra算法简介 2 算法实现范例 3 邻接矩阵 4 Dijkstra 算法的 C 描述 5 Dijkstra 算法的 Matlab 描述 6 温故知新 1 Dijkstra算法简介 背景 迪杰斯特拉算法 Dijkst
  • Java中double类型大小比较的五种方法

    文章目录 1 使用BigDecimal 2 使用包装类Double 3 在误差范围内运行相等 4 转换成字符串 5 使用doubleToLongBits 方法 在Java中 int类型数据的大小比较可以使用双等号 double类型则不能使用
  • 设置SSH密钥对的必要性

    SSH介绍 SSH 为 Secure Shell 的缩写 由 IETF 的网络小组 Network Working Group 所制定 SSH 为建立在应用层基础上的安全协议 SSH 是较可靠 专为远程登录会话和其他网络服务提供安全性的协议
  • golang加载双向认证加密的证书key文件

    证书的key是可以加密保存的 我们需要进行解密加载 func MyLoadX509KeyPair certFile keyFile password string tls Certificate error certPEMByte err
  • 开放API接口或URL链接给第三方使用

    使用场景 场景1 应用做到一定程度后 会有一些第三方用户或机构要对接部分的功能进入他们自己的应用 比如 要通过URL的方式提供一个含有加密视频文件的H5页面给第三方使用 实现思路 1 后台管理系统给不同的第三方开权限 分别提供AppID和A
  • 学习率衰减

    在训练深度神经网络时 通常会随着训练的进行降低学习率 这可以通过使用预定义的学习率计划或自适应学习率方法来完成 学习率表 学习率时间表旨在根据预先定义的时间表降低学习率 从而在训练过程中调整学习率 常见的学习率时间表包括基于时间的衰减 逐步
  • AES算法的CBC和ECB模式!——密钥加密

    一 AES算法 AES Advanced Encryption Standard 是一种对称密钥加密算法 AES算法采用分组密码的方式 将明文划分成固定长度的数据块 对每个数据块进行加密 最终得到密文 AES算法的密钥长度可以为128位 1
  • 利用Netty构建自定义协议的通信

    在复杂的网络世界中 各种应用之间通信需要依赖各种各样的协议 比如 HTTP Telnet FTP SMTP等等 在开发过程中 有时候我们需要构建一些适应自己业务的应用层协议 Netty作为一个非常优秀的网络通信框架 可以帮助我们完成自定义协
  • 【Linux + 安装库】Ubuntu18.4.0下安装gmp+ntl+crytpo++库的相关操作

    一 装Ubuntu 1 虚拟机下装好的ubuntu系统安装编译器 首先需要添加源 代码 sudo add apt repository ppa ubuntu toolchain r test 2 添加源之后 安装编译器 gcc安装 sudo
  • Spring Boot 学习研究笔记(十二)Dcoker 中部署SpringBoot jar包

    Linux Centos8 使用 DOCKER 部署JAR包 1 进入项目根目录 cd project 2 创建存放jar包的目录 mkdir springboot test 3 进入 project springboot test 编写D
  • 软件调试之堆和堆检查

    当用户启动一个程序时 系统会将程序文件从外部存储器 硬盘等 加载到内存中 当程序工作时 需要使用内存空间来放置代码和数据 在使用一段内存之前 程序需要以某种方式 API或库函数 发出申请 接受到申请的一方 内存管理器或C运行库 根据申请者的
  • 【Ansible自动化运维实战】使用ansible批量部署开机启动时为字符界面

    Ansible自动化运维实战 使用ansible批量部署开机启动时为字符界面 一 查看当前启动默认的引导目标 二 编辑playbook 三 测试playbook语法 四 运行playbook 五 测试结果 一 查看当前启动默认的引导目标 a
  • 【信息技术】【2018.01】射频功率放大器的行为建模与数字预失真

    本文为奥地利格拉茨技术大学的博士论文 共147页 数字无线发射机中的射频功率放大器 RF PA 是关系到能量消耗和信号质量的关键部件 特别是由于当今宽带多载波调制方法产生的信号峰均比很高 很难构建出能量效率高 满足标准严格线性要求的射频功率
  • 自己动手写basic解释器(一)

    自己动手写basic解释器 刺猬 http blog csdn net littlehedgehog 注 文章basic解释源码摘自梁肇新先生的 编程高手箴言 据他所说这个代码也是网上摘录的 源码解读参考 java编程艺术 java编程艺术