用C语言写解释器(一)——我们的目标

声明

为提高教学质量,我所在的学院正在筹划编写C语言教材。《用C语言写解释器》系列文章经整理后将收入书中“综合实验”一章。因此该系列的文章主要阅读对象定为刚学完C语言的学生(不要求有数据结构等其它知识),所以行文比較罗嗦,请勿见怪。本人水平有限,如有描写叙述不恰当或错误之处请指教!特此声明。

起因

近期,我们学院老师联系我,希望我能提供一段用 C 语言编写的 BASIC 解释器,用于 C 语言课程设计教学。我前段时间也正好着迷于“语言”本身,本就有打算写一个解释器,这下正中我下怀,于是欣然接受。

曾经在图书馆看过梁肇新的《编程高手箴言》,第四章“编程语言的运行机理”中就包括了一段 C 语言编写的 BASIC 解释器代码,但代码好像并不完整(我翻了好几遍,都没发现函数 get_token 的实现代码);再者,这次的代码还有其它用处,不宜牵涉版权问题;最后的原因是我有“想自己编码”的冲动 ^_^。综上所述,我要从零開始用 C 语言来编写一个 BASIC 解释器。

前置知识

1. 要编写解释器,首先就要明确什么是解释器(具体的解释请參看维基百科:http://zh.wikipedia.org/zh-cn/解释器)。盗用《编程高手箴言》里的话:解释程序就是一个字符串的解释器(P165 解释语言的原理)。所以,假设仅仅是为我个人编写的话,我宁可会借助 lex & yacc 甚至 perl,而不会纯粹用 C 语言来写。

2. 在起因中已经提过,这个程序会在学弟学妹们学完 C 语言后作为综合实验。因此须要你熟悉 C 语言的语法、单链表加入/删除节点等操作以及栈的概念(这些内容大部分都能在 C 语言的教材中找到),一些相对冷僻的技术(比如 setjmp/longjmp)则不会出如今程序中。

关于语言

我在《编程和语言之我见》一文中提过,编程是一个非常宽泛的概念。从某种意义上来说全部的软件都是一种特定的语言,但依据程序本身的灵活性能够分为“硬编码”、“可配置”、“可控制”和“可编程”四类(详见《四类程序》)。假设一个程序的灵活性达到了“可编程”,它的配置文件就能够被看作一种“编程语言”,而该程序本身也就是一个“解释器”。

要做到“可编程”,程序至少应该具备“输入/输出”、“表达式运算”、“内存管理”和“按条件跳转”四个功能(详见《用DOS批处理来做数字图像处理》)。这正好相应了冯·诺依曼计算机的结构:以运算器和控制器为中心,输入/输出设备与存储器之间的传输数据都要经过运算器。以下具体介绍各个部分。

我们的目标

我们要编写解释器,自然也逃不出上面的条条例例。语法就參考 BASIC,但由于是设计我们自己的语言,当然能够依据个人兴趣进行“添油加醋”(比方表达式里提供神往已久的阶乘运算 ^_^)。以下是一段 BASIC 的演示样例代码(example.bas):

0009 N = 0
0010 WHILE N < 1 OR N > 20
0011   PRINT "请输入一个1-20之间的数"
0012   INPUT N
0013 WEND
0020 FOR I = 1 TO N
0030   L = "*"
0040   FOR J = 1 TO N - I
0050     L = " " + L
0060   NEXT
0070   FOR J = 2 TO 2 * I - 1 STEP 2
0080     L = L + "**"
0090   NEXT
0100   PRINT L
0110 NEXT
0120 I = N - 1
0130 L = ""
0140 FOR J = 1 TO N - I
0150   L = L + " "
0160 NEXT
0170 FOR J = 1 TO ((2*I) - 1)
0180   L = L + "*"
0190 NEXT
0200 PRINT L
0210 I = I - 1
0220 IF I > 0 THEN
0230   GOTO 130
0240 ELSE
0250   PRINT "By redraiment"
0260 END IF

BASIC 语法要求行首提供一个 1->9999 之间的数字作为该行的行号(当前行的行号不小于上一行的行号),供 GOTO 语句跳转时调用。BASIC 的语法比 C 严格,这不仅能够减少代码的复杂性还使语言本身更易学。上面的代码差点儿相同涵盖了我们须要实现的全部功能,假设能被正确解析,你将看到以下的运行效果:


以下来依次讨论要实现的功能。

输入/输出(IO)

通过输入/输出来和外部程序或人交互,这是脱离“硬编码”的最基本要求。输入/输出也是非常抽象的概念,它并不局限于标准输入输出端(键盘、显示器等),也能够通过文件、互联网等方式获得数据(因此 C 语言中除了 scanf、printf 等,事实上 #include 指令也算是一种 IO 操作)。我们这个程序并不强调 IO,因此仅仅要求实现 INPUT 和 PRINT 两条指令,分别用于从键盘输入数据和打印到屏幕。指令的格式例如以下:

INPUT var[, var ...]当中 var 代表变量名(下同),变量之间用逗号隔开。作用:从键盘获得一个或多个值,并赋值到相应的变量。同一时候输入多个变量时,输入的每一个数之间用空格、回车或制表符隔开。比如:INPUT A, B, C
PRINT expression[, expression ...]当中 expression 为表达式(下同),表达式之间用逗号隔开。作用:对表达式求值,将结果输出到屏幕并换行。假设有多个表达式,表达式之间用制表符(/t)隔开。比如:PRINT I * 3 + 1, (A + B)*(C + D)

表达式运算

在《DOS》中我称呼它为“算术运算”。但对于计算机来说,“算术运算”不仅包括诸如“四则运算”等算术运算,还包括“关系运算”和“逻辑运算”。为了避免歧义,在此就改称它为“表达式运算”。“表达式运算”是整个程序的核心,地位相当于计算机的运算器。在我们的程序中,须要实现以下几种运算符:

符号名称优先级结合性
(左括号17left2right
)右边17left2right
+12left2right
-12left2right
*13left2right
/13left2right
%取模13left2right
^求幂14left2right
+正号16right2left
-负号16right2left
!阶乘16left2right
>大于10left2right
<小于10left2right
=等于9left2right
<>不等于9left2right
<=不大于10left2right
>=不小于10left2right
AND逻辑与5left2right
OR逻辑或4left2right
NOT逻辑非15right2left

内存管理

在我们这个迷你型的解释器中,能够不用考虑内存空间动态分配的问题,仅仅要实现简单的变量管理。我们默认提供 A-Z 26个可用的弱类型变量(能够任意赋值为整数、浮点数或字符串)。变量要求先赋值才干使用,否则就会提示变量不可用(因此演示样例代码中第一行就是给 N 赋值为 0)。赋值语句的格式为

[LET] var = expression当中 LET 是可选的keyword。BASIC 中不同意出现 var1 = var2 = expression 这种赋值语句,由于在表达式中“=”被翻译为“等于”,所以赋值符合没有出如今上面的表格中。作用:计算表达式的值,并将结果赋值给变量 var。比如:I = (123 + 456) * 0.09

按条件跳转

假设设计一门最简洁的语言,那它的控制语句就仅仅需提供像汇编中的 JMP、JNZ 等依据条件跳转的语句就可以,通过它们的组合就可以模拟出 IF、WHILE、FOR、GOTO 等控制语句。但 BASIC 作为一门高级语言,须要提供更高层、更抽象的语句。我们将会实现以下四条语句:

1)
GOTO expression当中 expression 是一个数值表达式,计算结果必须为可用的行号。由于它是一个表达式,通过动态计算就能模拟子程序调用。作用:无条件跳转到指定行。比如:GOTO 120+10
2)
IF expression THENsentence1
[ELSEsentence2]
END IF当中 sentence 是语句块(下同),包括一条或多条可运行语句。ELSE 为可选部分。作用:分支结构。但表达式值为真(数字不等于0或者字符串不为空)时运行语句块1;否则,有 ELSE 语句块时运行 ELSE 语句块。比如:IF 1=1 THENPRINT "TRUE"ELSEPRINT "FALSE"END IF
3)
FOR var = expression TO expression [STEP expression]sentence
NEXT全部表达式均为数值表达式。STEP 为可选部分,为迭代器的步长。步长表达式的值不同意为 0。作用:循环迭代结构比如:FOR I = 1 TO 10 STEP 3PRINT INEXT
4)
WHILE expressionsentence
WEND作用:迭代运行语句块,直到表达式的值为假。比如:WHILE N < 10N = N + 1WEND

很多其它细节

  1. BASIC 的源代码不区分大写和小写;
  2. 本程序在实现中没有处理字符转义,因此无法无法输出双引號。在介绍全然部源代码后,假设你有兴趣能够尝试自行完好;
  3. 本程序相同没有考虑凝视(REM keyword)。事实上这非常easy,但这个问题相同留给你来处理 ^_^;
  4. 或许你也会有兴趣加入 GOSUB 和 RETURN keyword,让子程序功能从 GOTO 中解放出来。

总结

这一篇主要介绍了我们编写的解释器要实现的功能,接下来会有一系列文章来逐步具体介绍解释器的实现。在下一篇中会首先介绍解释器的核心部分——表达式求值。请关注《用C语言写解释器(二)》。


版权声明

请尊重原创作品。转载请保持文章完整性,并以超链接形式注明原始作者“redraiment”和主网站地址,方便其它朋友提问和指正。

联系方式

我的邮箱,欢迎来信(redraiment@gmail.com)
我的Blogger(子清行):http://redraiment.blogspot.com/
我的Google Sites(子清行):https://sites.google.com/site/redraiment
我的CSDN博客(梦婷轩):http://blog.csdn.net/redraiment
我的百度空间(梦婷轩):http://hi.baidu.com/redraiment

转载于:https://www.cnblogs.com/bhlsheji/p/4298144.html

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

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

相关文章

1_MVC+EF+Autofac(dbfirst)轻型项目框架_core层(以登陆为例)

前言 在上一篇0_MVCEFAutofac(dbfirst)轻型项目框架_基本框架中&#xff0c;我已经介绍了这个轻型框架的层次结构&#xff0c;在下面的这篇文章中&#xff0c;我将以教师登陆功能为例&#xff0c;具体来扩充下我的core层的代码。 在这之前&#xff0c;我想先补充讨论下是否有必…

Python实现atm机的功能

主要还是参考网上内容&#xff0c;自己做了修改。虽然代码有小bug&#xff0c;但是不影响学习和测试。功能&#xff1a;1.额度&#xff1a;80002.可以提现&#xff0c;手续费5%3.每月最后一天出账单&#xff0c;写入文件4.记录每月日常消费流水5.提供还款接口1.atm的脚本[rootp…

使用Vitamio打造自己的Android万能播放器(7)——在线播放(下载视频)

前言 本章将实现非常实用的功能——下载在线视频。涉及到多线程、线程更新UI等技术&#xff0c;还需思考产品的设计&#xff0c;如何将新加的功能更好的融入到现有的产品中&#xff0c;并不是简单的加一个界面就行了&#xff0c;欢迎大家交流产品设计和技术细节实现&#xff01…

HTML声明文档类型后样式出错,doctype如何声明

如何doctype声明&#xff0c;新增的结构元素和功能元素HTML5已形成了最终的标准&#xff0c;概括来讲&#xff0c;它主要是关于图像&#xff0c;位置&#xff0c;存储&#xff0c;多任务等功能的增加。 新增的元素有绘画 canvas &#xff0c;用于媒介回放的 video 和 audio 元素…

Error-Project facet Java version 1.8 is not supported

最近导入最新的Strtus2.5.10.1 Demo时出现了这个错误 解决方案如下&#xff1a; 选中工程——右键——Properties 然后依次展开找到如图所示内容&#xff0c;将1.8改成1.7即可。 原因&#xff1a;工程默认配置是1.8&#xff0c;而本地环境JDK版本为1.7&#xff0c;两则不匹配造…

6.2

转载于:https://www.cnblogs.com/tutuaixiaomei/p/3354356.html

Tomcat全攻略

内容&#xff1a; 一&#xff1a;简单介绍二&#xff1a;安装及配置三&#xff1a;应用四&#xff1a;综述參考资料关于作者宗 锋西北大学计算机系硕士2001 年 12 月 随着java的流行&#xff0c;其在web上的应用也越来越广&#xff0c;tomcat作为一个开源的servlet容器&#xf…

Android Material风格的应用(三)--DrawerLayout

添加抽屉导航 Android Material风格的应用(一)--AppBar TabLayoutAndroid Material风格的应用(二)--RecyclerViewAndroid Material风格的应用(三)--DrawerLayoutAndroid Material风格的应用(四)--FloatActionButtonAndroid Material风格的应用(五)--CollapsingToolbar DrawerLa…

html5 数据缓存,HTML5: 本地缓存

HTML5 提供了两种在客户端存储数据的新对象&#xff1a;localStorage&#xff1a;没有时间限制的数据存储&#xff0c;在同一个浏览器中&#xff0c;只要没被手动清理&#xff0c;第二天、第二周或下一年之后&#xff0c;数据依然可用。sessionStorage&#xff1a;针对一个 ses…

上传Text文档并转换为PDF

今天在ASP.NET MVC环境中学习一些PDF相关的知识&#xff0c;想法是上传文件成功时&#xff0c;并把文件转换为PDF文档。 打开你的专案&#xff0c;运行NuGet包管理器&#xff0c;下载一个叫iTextSharp的东东&#xff1a;点击Install&#xff0c;按钮提示确认安装&#xff0c;成…

递归函数(九):最小不动点定理

递归函数&#xff08;一&#xff09;&#xff1a;开篇递归函数&#xff08;二&#xff09;&#xff1a;编写递归函数的思路和技巧递归函数&#xff08;三&#xff09;&#xff1a;归纳原理递归函数&#xff08;四&#xff09;&#xff1a;全函数与计算的可终止性递归函数&#…

html中单选框颜色怎么改,如何更改单选按钮的颜色?

侃侃无极一种快速的解决方法是使用来覆盖单选按钮的输入样式:after&#xff0c;但是创建自己的自定义工具箱可能是更好的做法。 input[typeradio]:after { width: 15px; height: 15px; border-radius: 15px; top: -2px; left: -1px; …

如何先执行input (checkbox,radio)再执行函数

2019独角兽企业重金招聘Python工程师标准>>> 遇到一个问题&#xff0c;当input type"checkbox"点击时&#xff0c;没有立即执行勾选或去勾&#xff0c;而是先执行函数&#xff0c;如下代码 $(".sidebar_cart .cart_list ul").on("click&qu…

Linux服务器上监控网络带宽的18个常用命令

本文介绍了一些可以用来监控网络使用情况的Linux命令行工具。这些工具可以监控通过网络接口传输的数据&#xff0c;并测量目前哪些数据所传输的速度。入站流量和出站流量分开来显示。 作者&#xff1a;布加迪编译来源&#xff1a;51CTO.com|2014-04-11 10:10移动端收藏分享【51…

[转]Windows Phone 7程序设计”完全版电子书可以免费下载了

本文转自&#xff1a;http://www.cnblogs.com/salam/archive/2010/10/29/1864246.html 现在学习Windows Phone 7开发资料十分有限&#xff0c;除了MSDN的官方开发文档外和一些博客外&#xff0c;几无其他的学习渠道。幸运地是美国的资深程序员兼作家Charles Petzold为大家免费放…

linux-redhat替换yum网络源为centos网络源

2019独角兽企业重金招聘Python工程师标准>>> 1.为什么要替换 redhat系统使用yum命令安装软件时会出现This system is not registered with RHN. RHN support will be disabled. 原因是redhat的yum安装软件需要注册&#xff0c;是收费的。而centos的yum源是免费的。这…

计算机如何打开无线网络适配器,win7系统下网络适配器打不开怎么解决

通常情况下我们的电脑中都会有一个网络适配器&#xff0c;这是计算机联网的设备&#xff0c;不过最近有深度技术win7旗舰版系统用户却遇到了网络适配器打不开的情况&#xff0c;该怎么办呢&#xff0c;接下来系统城小编就给大家分享一下win7系统下网络适配器打不开的具体解决方…

【Intellij Idea】设置JDK

1&#xff0c;File-->Project Structure 说明&#xff1a;可以设置整个工程的JDK&#xff0c;也设置每个modules的JDK,但是一般整个工程的JDK. 2&#xff0c;或者通过快捷键&#xff1a;ctrlaltshifts 转载于:https://www.cnblogs.com/august-shi/p/6655469.html

绘图用计算机配置要求,绘图笔记本电脑基本配置要求 绘图笔记本推荐

现在很多工业图、工程图都需要用电脑来话&#xff0c;比如CAD、PS、三维画图这些软件对电脑的配置要求还是比较高的&#xff0c;还有一些对色彩要求高的动画软件&#xff0c;那就更加需要配置了&#xff0c;下面小编就来简单说说绘图笔记本电脑最基本的配置要求以及绘图笔记本推…

计算机无法正常更新,无法完成更新正在撤销更改请不要关闭你的计算机如何修复...

我们电脑开机的时候可能会遇到各种问题&#xff0c;比如就有用户发现电脑开机的时候&#xff0c;一直提示无法完成更新正在撤销更改请不要关闭你的计算机&#xff0c;等待了很长时间也进不去系统&#xff0c;遇到这样的问题该怎么办呢&#xff1f;不用担心小编给大家支招&#…