vlambda博客
学习文章列表

辣鸡用C语言实现解释器(二)

文件读入方式

使用fgets函数。


函数功能为从指定的流中读取<span 数据,每次读取一行。其原型为:<span  str 所指向的字符串内。当读取<span



值得一提的是,如果是读到换行符停止后,str所指向字符串倒数第二个字符为‘\n’,最后一个字符为‘\0'。


read_file函数中实现文件的逐行读入以及简单的“分拣”:   

#include"yzs.h"
int read_file(char *filename){ FILE *fp; fp=fopen(filename,"r"); if(fp==NULL) {// printf("不能读取文件\n"); return NO; }
//创建缓冲区buffer char *buffer=NULL; buffer=(char*)malloc(sizeof(char)*100); if(!buffer) {// printf("缓冲区创建失败"); return NO; }// else printf("缓冲区预备\n") ;
//对文件进行操作 // printf("开始读取…\n"); while(!feof(fp)) { if(!fgets(buffer,100,fp)) break; operate_buffer(buffer); if(buffer[0]=='/'&&buffer[1]=='/') goto here; if(buffer[0]=='\n') break;// int if(buffer[0]=='i'&&buffer[1]=='n'&&buffer[2]=='t') { read_int(buffer); } // float else if(buffer[0]=='f'&&buffer[1]=='l'&&buffer[2]=='o'&&buffer[3]=='a'&&buffer[4]=='t') { read_float(buffer); } // string else if(buffer[0]=='s'&&buffer[1]=='t'&&buffer[2]=='r'&&buffer[3]=='i'&&buffer[4]=='n'&&buffer[5]=='g') { read_string(buffer); } // 条件语句 else if(buffer[0]=='i'&&buffer[1]=='f'&&buffer[2]==' '&&strchr(buffer,'{')) { if_func(buffer,fp); } // 循环语句 else if(buffer[0]=='f'&&buffer[1]=='o'&&buffer[2]=='r') { change_buffer(buffer,fp); } // 函数 read else if(strchr(buffer,'r')&&strchr(buffer,'e')&&strchr(buffer,'a')&&strchr(buffer,'d')&&strchr(buffer,'(')&&(!strchr(buffer,','))) { func_read(buffer); } else if(strstr(buffer,"else")&&flag_for==0) { } else if(strstr(buffer,"else")&&flag_for==1) { while(1) { fgets(buffer,100,fp); if(strchr(buffer,'}')) break; } }// 函数print else if(strchr(buffer,'p')&&strchr(buffer,'r')&&strchr(buffer,'i')&&strchr(buffer,'n')&&strchr(buffer,'t')&&strchr(buffer,'(')) { func_print(buffer); } else if(strstr(buffer,"func")) { save_func(buffer,fp); } else if((!strstr(buffer,"assign"))&&strchr(buffer,')')&&strchr(buffer,'(')&&(!strstr(buffer,"read"))) { use_func(buffer); } else if(strchr(buffer,'}')) { }// 赋值语句 else if(!strchr(buffer,'}')) { operate(buffer); } here:; } // printf("读取完成\n"); // 读取变量值验证// visit(); if(fclose(fp)) { printf("无法关闭文件\n"); return NO; } free(buffer); return OK; }


operate_buffer函数原型为:

void operate_buffer(char *buffer);

用于删去开头的空格。



变量定义要求

变量名:  字母数字或$组成,不能以数字开头,最多 32 字符,如 Dian2020,$1 都是合法变量名。


变量定义:  

int a,b,c; float d,e; string f; int arri[16];

       定义后数值类型默认值 0,字符串默认值“”(空串)。 

变量类型有 int 整数,float 浮点数,string 字符串。

变量不存在作用域,一旦定义全局有效。


 变量类型 变量名 1[,变量名 2][,变量名 3]…[,变量名 n]; 数组定义:

 数组为固定长度,下标从 0 开始,默认值同变量类型默认值。 




HASH-变量储存


在头文件中,我们使用hash函数在变量名和代表变量的数值之间进行映射。鉴于文件中涉及的变量少,懒惰的我直接从网上嫖了一个hash函并且没有考虑变量重名的情况。为此我表示忏悔,承诺在下一篇发之前好好学习hash函数的操作之后写总结。


我嫖的函数是这样的(HASHSIZE定义为101):

int hash(char *s){    int h=0;    for(;*s;s++) h=*s+h*31;    return h%HASHSIZE;


变量结构体定义为:

struct variable{ char name[33];  // type=1(int),type=2(float),type=3(string)  // type=11(int array),type=22(float array)  int type;   float x_f;  int x_i;  char *str_head;  int *array_i;  float *array_f;};


其中,char name[33]用于存放变量名,主要是为了debug时方便查看比如变量“重名”(不同变量hash值相同)的情况。


同样鉴于涉及变量不多,我们设置全局变量:

struct variable var[101]



语句处理


对于文件中变量定义式:

int a,b,c[10];

*buffer中,int是进入read_int进行变量定义的标志。对于定义非数组,只需让该变量的type=1即可;对于数组,需要type=11的同时给int数组头指针array_i分配大小为数组下标的空间。



read_int:

void read_int(char *buffer){ int poi; // 只存在一个变量  if(!strchr(buffer,','))  { if(!strchr(buffer,'[')) {// 非数组int poi=write_name(strchr(buffer,' ')+1,strchr(buffer,';')-1); write_type_int(poi); } else {// int数组  poi=write_name(strchr(buffer,' ')+1,strchr(buffer,'[')-1);// write_type_int(poi); creat_array_int(strchr(buffer,'[')+1,strchr(buffer,']')-1,poi); }  } else { char *begin=NULL; char *end=NULL; begin=strchr(buffer,' '); end=strchr(buffer,',');
do { poi=write_name(begin+1,end-1); write_type_int(poi); // 找下一个, *end='#'; begin=end;
if(!strchr(buffer,',')) { end=strchr(buffer,';'); poi=write_name(begin+1,end-1); write_type_int(poi); break; } else end=strchr(buffer,','); }while(1); }}


write_name函数用于将变量名写入变量结构体中,同时返回变量hash值。

write_type_int函数用于初始化变量的type。

create_array_int用于初始化数组。


float的实现与int相同,而实现string只需将字符串初始化为空串即可,不必赘述。





THE END

下次变量赋值操作!!!

话说大家有啥时间管理大法教教我呗!我最近好颓废,鬼畜区快被我看穿了。

欢迎大家批评指正!!!优化代码啊或者错误啥的。