【vc++精品源码栏目提醒】:文章导读:在新的一年中,各位网友都进入紧张的学习或是工作阶段。
网学会员整理了vc++精品源码-【精品】动手编Basic解释器 - 其它资料的相关内容供大家参考,祝大家在新的一年里工作和学习顺利!
这个呵呵那些客套话咱就不扯那么多了,啥写编译器是多少程序员梦想阿,多牛逼阿之类云云这之类的话咱就不聊了,主要是这里是 C不是 java,C 程序没 java 那么多套路,直接单刀赴会了。
好了既然我们是写 basic 解释器,那我们至少先要明白 两件事情:第一,什么是解释器;第二,basic 语法这个至少要了解大概 吧。
第一,什么是解释器?编译器大家应该都知道,GCC,VC++当然这个不纯粹是编译器了,简单的说呢,编译器将程序的源代码转化为可执行代码的形式。
通常情况下,这种可执行代码由计算机的 CPU 指令组成,因此可以直接在
计算机上执行。
而解释器就不同了,它顺序读入程序的源代码,然后依次执行每一条语句。
因此,解释器并不真正将源代码转化为目标代码,而是直接执行程序。
第二,basic 语法以及我们为什么选择 basic 解释器作为编写目标先说第一个为什么写 basic? 因为 basic 语法简单,你听名字也大概知道了,比如我不会选择advance 作为编写目标,名字就比较吓人。
basic 我们不来详细讲了,因为我们做得这个解释器本来就很小,没涉及到多少东东,有需要的可以 google 一下。
这里先贴一小段代码,混个脸熟:PRINT quotA Simple Small BASIC Programquot 打印字符串FOR X 1 TO 10 for 循环GOSUB 100 跳到标号 100 语句执行 注意这里 100 是标号NEXT 下一个 x 表示 x 要加一END ‘程序结束100 PRINT X 这里相当于 C 中函数RETURN 返回代码一目了然,我们解释器基本上也就处理这几个关键字。
现在摆在我们面前的就是如何处理这些关键字,换句话来说,我们如何在程序读取到相应关键字时,做出相应反应了。
比如 我们执行 print,我们就要用 printf 把 print 后面的东东打印出来。
这还比较好办,但是如果是一个 for 循环呢,我们又该如何处理?关键字处理是个大麻烦,因为我们面对不同关键字,要做出不同反应来。
这个还是后话,眼前我们还是把主要框架先看看。
第一步 装载
源代码用过 gcc 么?郁闷 gcc 都没用过! 在 windows 下生活滋润惯了 看来 ,学计算机还是要来 opensource 阵营阿,话扯远了。
我们用 gcc 编译 c 文件时,都是 gcc -o target source 。
所以我们也仿照这格式,直接用命令行 图形界面我们就不用实现了,再说俺也不 懂。
main int argcchar argv char p_buf char t if argc2 printf quotusage: s ltfilenamegtnquotargv0 exit 1 / allocate memory for the program / if p_bufchar mallocPROG_SIZE printf quotallocation failurequot exit 1 / load the program to execute / if load_programp_bufargv1 exit1这里我 们开辟一个 PROG_SIZE 大小空间,供装载程序源码用。
然后我们把程序代码用load_program 函数装入内存。
代码如下:/ Load a program /load_program char pchar fname FILE fp int i0 if fpfopenfnamequotrbquot return 0 i0 do p getcfp pi while feoffpampampiltPROG_SIZE p-2 0 / null terminate the program / fclose fp return 1代码很简单。
因为我们现在还没有开始处理语法,下面才是正式开始。
上次我们把程序装载入内存,这里我们开始做词法分析了。
hoho 开始一开始我们先再来回顾下:当我们的解释器在执行时,每次读入一条语句,并且根据这条语句执行特定的操作;然后再读入下一条语句,依此执行下去。
也就是说解释器执行时,每次从程序的源代码中读入一个标识符。
如果读入的是关键字,解释器就按照该关键字的要求执行规定的操作。
举例来说,当解释器读入一个 PRINT 后,它将打印 PRINT 之后的字符;当读入一个 GOSUB 时,它就执行指定的子
程序。
在到达程序的结尾之前,这个过程将反复进行。
按照上面的分析,我们所做的第一步就是要读取标识符,要一个单词一个数字的区分,比如print 要作为一个关键字读入,2345 要作为一个数字读入,而 a=3 这里要作为三个标识符读入,分别是变量 a、赋值符号=以及数值 3。
看来我们在读取标识符时,我们还需要给标识符分类。
define DELIMITER 1 //分界符 比如逗号 分号 等号 都属于这之列define VARIABLE 2 //变量define NUMBER 3 //数字define COMMAND 4 //关键字命令define STRING 5 //字符串这个比较特殊 既包括关键字 又包括常量字符串define QUOTE 6 //常量字符串 比如quothello worldquot这里仔细谈分类收获不大,待看了 get_token 这个取标识符的函数之后我们就大致明白为什么要这样分了。
token 主要目的就是读取当前的标识符,放入 token 字符数组中,并确定标识符类型,放入 token_type 中,如果是关键字,那么我们还需要处理 tok,标记为相应关键字。
/