构建自己的C解释器(1989)

2020-09-18 03:10:21

[清单一]<;a Name=";0170_0013";>;/*用于可能包含变量和函数调用的整数表达式的递归下降解析器。*/#include";setjmp.h";#include";math.h";#include";ctype.h";#include";stdlib.h";#include";string.h";#include";stdio.h";#DEFINE NUM_FUNC100#DEFINE NUM_GLOBAL_VARS 100#DEFINE NUM_LOCAL_VARS 200#DEFINE ID_LEN 31#DEFINE FUNC_CALLES 31#DEFINE PROG_SIZE 10000#DEFINE FOR_NEST 31enum TOK_TYPE{分隔符,标识符,数字,关键字,TEMP,STRING,INT,IF,ELSE,FOR,DO,WHILE,SWITCH,RETURN,EOL,INTED,END};枚举DOUBLE_OPS{LT=1,LE,GT,GE,EQ,NE};/*这些是用于在出现语法错误时调用sntx_err()的常量。如果你愿意,可以再加一些。注意:语法是在似乎没有合适的其他内容时使用的一般性错误消息。*/enum error_msg{SYNTAX,UNBAL_PARENTS,NO_EXP,EQUALS_EXPECTED,NOT_VAR,PARAM_ERR,SEMI_EXPECTED,UNBAL_BRANDES,FUNC_UNDEF,TYPE_EXPECTED,NEST_FUNC,RET_NOCALL,PAREN_EXPECTED,WHILE_EXTEMPED,QUOTE_EXPECTED,NOT_TEMP,TOO_MANY_LVARS};extern char*prog;/*源代码中的当前位置*/extern JMP_BUF_BUF;/*指向程序缓冲区的起始位置*/extern JMP_BUF_BUF;/*保存long jmp()的环境*//*这些结构的数组将保存与全局变量关联的信息。*/extern struct var_type{char var_name[32];枚举VARIABLE_TYPE var_type;intvalue;}global_vars[NUM_GLOBAL_vars];/*这是函数调用堆栈。*/extern struct func_type{char func_name[32];char*loc;/*函数入口点在文件中的位置*/}func_stack[NUM_FUNC];/*关键字表*/extern struct Commands{char command[20];char tok;}table[];/*";标准库";函数在此声明,以便放入后面的内部函数表。*/int call_getche(Void),call_putch(Void);int call_put(Void),print(Void),getnum(Void);Struct intern_func_type{char*f_name;/*函数名*/int(*p)();/*指向函数的指针*/}intern_func[]={";getche";,call_getche,";,call_putch,";put";,call_put,";print";,print,";,getnum,";";,0/*null终止列表*/};外部char Token[80];/*Token的String表示*/extern char Token_type;/*包含Token的类型*/extern char tok;/*Token的内部表示*/extern int ret_value;/*函数返回值*/void eval_exp(int*value),eval_exp1(int*value);void eval_exp2(int*value);void eval_exp3(int*value),eval_exp4(int*value);Void eval_exp5(int*value),atom(int*value);void eval_exp0(int*value);void sntx_err(Int Error),putback(Void);void assign_var(char*var_name,intvalue);int isdelm(Char C),lookup(char*s),isWhite(Char C);int find_var(char*s),get_Token(Void);int Internal_func(char*s);int is_var(char*s);char*find_func(char*name);call(Void);/*进入解析器的入口点。*/void eval_exp(int*value){get_Token();if(!*Token){sntx_err(No_Exp);return;}if(*Token==';;';){*value=0;/*空表达式*/return;}eval_exp0(Value);putback();/*返回上次读取到输入流的Token*/}/*处理赋值表达式*/void eval_exp0(int*value){char temp[ID_LEN];/*保存接收赋值的var名称*/register int temp_tok;if(TOKEN_TYPE==IDENTIFIER){if(is_var(TOKEN)){/*如果是var,查看是否赋值*/strcpy(temp,Token);temp_tok=TOKEN_TYPE;get_Token();IF(*TOKEN==';=';){/*是赋值*/get_Token();eval_exp0(Value);/*get value to assignment*/assign_var(temp,*value);/*赋值*/return;}Else{/*不是赋值*/putback();/*恢复原始Token*/strcpy(Token,Temp);TOKEN_TYPE=TEMP_TOK;}eval_exp1(Value);}/*eval_exp1()使用该数组。因为某些编译器不能初始化函数中的数组,所以它被定义为全局变量。*/char relops[7]={LT,LE,GT,GE,EQ,NE,0};/*处理关系运算符。*/void eval_exp1(int*value){int part_value;register char op;eval_exp2(Value);op=*Token;if(strchr(relops,op)){get_Token();eval_exp2(&;part_value);switch(Op){/*执行关系运算*/case LT:*value=*value<;part_value;Break;case le:*value=*value<;Break;case gt:*value=*value>;part_value;Break;案例GE:*VALUE=*VALUE&>;=PARTIAL_VALUE;BREAK;CASE EQ:*VALUE=*VALUE==PARTIAL_VALUE;BREAK;案例NE:*VALUE=*VALUE!=PARTIAL_VALUE;BREAK;}}。*/void eval_exp2(int*value){register char op;int PARTIAL_VALUE;eval_exp3(VALUE);WHILE((OP=*TOKEN)==';+';||OP==';-';){get_Token();eval_exp3(&;PARTIAL_VALUE);开关(OP){/*加或减*/CASE';-';:*VALUE=*VALUE-PARTIAL_VALUE;Break;CASE';+';:*VALUE=*VALUE+PARTIAL_VALUE;Break;}/*将两个因子相乘或相除。*/void eval_exp3(int*value){register char op;int part_value,t;ev