自己动手写basic解释器
刺猬@http://blog.csdn.net/littlehedgehog
注: 文章basic解释源码摘自梁肇新先生的《编程高手箴言》(据他所说这个代码也是网上摘录的),源码解读参考《java编程艺术》。《java编程艺术》里面自然是java版了(可能旭哥更加适合点儿),我这里还是解读的C版basic解释器代码。
终于把这个basic解释器主干源码解述完了。其实说来这个解释器实际意义并不大,但是通过阅读源代码我们可以深一步领悟程序语言执行内部机理。我觉得特别值得提的三点:
1、通过prog指针模拟CPU中的eip寄存器,巧妙地借鉴了世界最顶尖级的硬件工程师在处理程序运行问题上的思路。
2、模拟函数调用栈,这个在go_sub函数中得到了淋漓尽致地体现。
3、p_buf就相当于计算机内存,或者说是程序运行空间的text段,26个变量就相当于data段,而我们的模拟栈恰好就是程序中的栈空间。
最后我把主程序的代码贴出来,方便兄弟伙们:
- #include <stdio.h>
- #include <setjmp.h>
- #include <math.h>
- #include <ctype.h>
- #include <stdlib.h>
- #define NUM_LAB 100
- #define LAB_LEN 10
- #define FOR_NEST 25
- #define SUB_NEST 25
- #define PROG_SIZE 10000
- #define DELIMITER 1
- #define VARIABLE 2
- #define NUMBER 3
- #define COMMAND 4
- #define STRING 5
- #define QUOTE 6
- #define PRINT 1
- #define INPUT 2
- #define IF 3
- #define THEN 4
- #define FOR 5
- #define NEXT 6
- #define TO 7
- #define GOTO 8
- #define EOL 9
- #define FINISHED 10
- #define GOSUB 11
- #define RETURN 12
- #define END 13
- char *prog; /* holds expression to be analyzed */
- jmp_buf e_buf; /* hold environment for longjmp() */
- int variables[26]= { /* 26 user variables,A-Z */
- 0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0
- };
- struct commands { /* keyword lookup table */
- char command[20];
- char tok;
- } table[] = { /* command must be entered lowercase */
- "print",PRINT, /* in this table */
- "input",INPUT,
- "if",IF,
- "then",THEN,
- "goto",GOTO,
- "for",FOR,
- "next",NEXT,
- "to",TO,
- "gosub",GOSUB,
- "return",RETURN,
- "end",END,
- NULL,END
- };
- char token[80]; //注意token是数组类型
- char token_type,tok;
- struct label {
- char name [LAB_LEN];
- char *p; /* point to place to go in source */
- };
- struct label label_table[NUM_LAB];
- char *find_label(),*gpop();
- struct for_stack {
- int var; /* counter variable */
- int target; /* target value */
- char *loc;
- } fstack[FOR_NEST]; /* stack for FOR/NEXT loop */
- struct for_stack fpop();
- char *gstack[SUB_NEST]; /* stack for gosub */
- int ftos; /* index to top of FOR stack */
- int gtos; /* index to top of GOSUB */
- void print(),scan_labels(),find_eol(),exec_goto();
- void gosub(),greturn(),gpush(),label_init(),fpush();
- /* Load a program */
- load_program (char *p,char *fname)
- {
- FILE *fp;
- int i=0;
- if (!(fp=fopen(fname,"rb"))) return 0;
- i=0;
- do {
- *p = getc(fp);
- p+&