2009年8月12日星期三

[回收贴]编写简单的语言解释器

说明:注意哦,是回收贴,把这段时间的一些实验的想法和代码贴过来。
都仍只是不成熟的内容,问题会比较多,而且缺少很多东西,如错误处理之类。
贴过来是觉得这些东西还是有点实用价值的。
因为代码中"<"和">"没有处理,所以#include部分在显示上有问题。
恩...我K&R风格的缩进也没显示出来。

Part1
编写简单的语言解释器
09-7-19

是想只记录构想要点的,不过仍是多了些无用的词句。不想在文字而非内容上耗时间。嗯,想到自己写文字为邮件是纯笔记的时候,是快快完成内容为先的啦。或者就把记事本里留的直接贴上,那个没有是专门去写的感觉。

语言用C,目地是纯实验,仅此很个人的。之前有试写了片段,不过若要完整的开始,还是先有份文档为好。
有三个方向,一个是GWBASIC兼容的,再适当扩展简单的代码风格。一个是基于lisp式表达式处理的,是处理type,value car,cdr式结构的,因为需要对list进行处理,不过如果从纯函数的角度说也不一定有必要。前面的那个就直接基于文本解析了,不按照编译原理先对完整的代码做词法和句法的分析,虽然有效率和编译时错误的缺陷,但我想会是仍能满足简单的运行要求。还有一个方向就是基于命令的如bat,sh,是语言本身就十分简单实用的实现。

BAS
由行构成,以换行或":"分割,行第一项为行号(纯数字只在换行后的行首,这次按Label处理,增加L语句)可省略,接着为语句名称,写为变量名的形式,对后续参数的处理由语句名称决定
变量简单地用链表储存,不hash或btree了。每项是字符串到值,值有类型和数据两部分。(之前第三类是全视为字符串,这里不是,有至少整数实数二进制字符串三类。)
先来流程控制部分。
LISP,先解析填充为树状结构,然后执行。两者之间可适当封装一下。
简单是原则哦。


lisp5.c

前缀表达式计算实验
ee.zsy按照BSD协议发布
缺陷
缺少错误处理
使用方法参见bat文件
lisp5.exe用TCC默认参数编译
09.07.12

BG
PLAN
简单的LISP解释器
//BAS解释器
TODO
逐步实现更多特性
从直接处理文本改为先转换为语法树
NEXT
改进getnum为getitem+isnum


#include
#include
#include
#include

char *exp;

int main(int argc, char** argv){
double eval();
//~ printf("argc %d\n",argc);
char ins[255];
gets(ins);
exp=ins;
printf("%s\n",exp);
//exp="(/ (+ 32 12) (* 1 4))";
printf("RST %g\n",eval());
return 0;
}

double getitem(){
double eval(),getnum();
if(*exp=='('){
printf("eval %s\n",exp);
return eval();
}else{
//printf("num %s\n",exp);
return getnum();
}
}

double getnum(){
int i=0;
char ts[10]={0,0,0,0,0,0,0,0,0,0};
printf("getnum %s\n",exp);
//~ for(i=0;isdigit(exp[i]);i++);
while(isdigit(exp[i]) || exp[i]=='.'){
i++;
}

printf("LEN %d\n",i);
strncpy(ts,exp,i);
printf("STR %s\n",ts);
printf("NUM %g\n",atof(ts));
exp+=i;
return atof(ts);
}

double eval(){
double p[5];
double result;
exp++;
switch(*exp){
case '+':
exp+=2;
p[0]=getitem();
exp+=1;
p[1]=getitem();
exp+=1;
printf("=%g+%g\n",p[0],p[1]);
result=p[0]+p[1];
break;
case '-':
exp+=2;
p[0]=getitem();
exp+=1;
p[1]=getitem();
exp+=1;
printf("=%g-%g\n",p[0],p[1]);
result=p[0]-p[1];
break;
case '*':
exp+=2;
p[0]=getitem();
exp+=1;
p[1]=getitem();
exp+=1;
printf("=%g*%g\n",p[0],p[1]);
result=p[0]*p[1];
break;
case '/':
exp+=2;
p[0]=getitem();
exp+=1;
p[1]=getitem();
exp+=1;
printf("=%g/%g\n",p[0],p[1]);
result=p[0]/p[1];
break;
default:
exit(1);
break;
}
return result;
}

getput.bat

getput.exe

后来随即尝试添加了cond语句(有嵌套的问题),并加入lisp中atom/list的处理,还没法编译。

3bas1.c

#include
#include
#include
#include
#define DebugPrint(SS) printf("%d:%s\n",__LINE__,SS);
int main(int argc, char** argv){
int LoadFile();
DebugPrint("main");
LoadFile();
return 0;
}

int LoadFile(){
DebugPrint("loadfile");
FILE *fp;
char *ss;
int fl;
fp = fopen("do2.c","r");
fseek(fp,0l,SEEK_END);
fl=ftell(fp);
fseek(fp,0l,SEEK_SET);
DebugPrint("as");
printf("LEN %2db\n",fl);
ss=(char*)malloc(fl+1);
int i;
for(i=0;i<=fl;i++) ss[i]='\0'; //~ ss[5]='\0'; //~ ss[0]='s'; //~ ss[1]='\0'; printf("%s\n",ss); //printf("%d",i); //~ int i; char ts[256]; for(i=0;i<=255;i++) ts[i]='\0'; //~ strcpy(ts,"bbbbbb"); //~ puts(fgets(ts,255,fp)); strcat(ss,ts); while(fgets(ts,256,fp) != NULL){ strcat(ss,ts); //~ puts("aa"); } //~ for(i=0;fgets(s,256,fp)!=NULL;i++){ //~ DebugPrint("cs"); //~ printf("%2d]",i+1); //~ puts(s); //~ strcat(ss,s); //~ puts(ss); //~ } fclose(fp); DebugPrint("bs"); printf("%s\n",ss); return 0; }

之后添加了

int main(int argc, char** argv)
int LoadSource(char* sn)
int NextStatement()//获取行并执行
int GetItemValue()
int GetItemLen(int start)
struct VarNode {
char *name;
char *value;
struct VarNode *next=NULL;
} VarNode0;//链表,可用代码在下面会有
char* GetVar(const char *name)
int SetVar(const char *name,const char *value)
char* NewStr(const char *Str)//malloc一个字符串的副本


Part2
BAS.txt

语句
[行号] 语句 参数
流程
label
goto
if then [else ]
//on goto

do
end
break,continue
for to stepnext
while:wend

命令
let =
表达式
运算符
数 +-*/
关系运算
字符串
]支持运算符和函数

变量储存
变量名,字符串
数组 支持数组语法 d(i,j)
转为字符串名处理 如 d_2_1
$运算符如 $abc
取字符串变量abc对应值为变量名的对应值
或单独建立类型名为引用
变量名是[a-zA-Z._0-9],凡是分隔符前不能被识别为数字的

def <>=<> 是扫描时定义,label


BAS表达式解析.txt

bas
目标 轻便

表达式计算 部分

记号
整数 digit
实数 digit|.|eE
//strtod能识别的部分,double
//能转换为整数就转换,运算都作实数
//或strtol
字符串 ""之间的
变量名 取得类型和值 alnum |$|%
之后有()则可能是
内置函数 运算
数组 查找
用户函数(或FN 开头) 查找并运算


操作符 长度>=1 可以前后有空格,或省略
优先级

针对double类型的
类型不符合则出错 类型错误
表达式(由高到低,优先处理):

括号表达式
数(leading 0 for octal, 0x for hex, else decimal),变量
一元 -
* /
+ -
= <>
> < <= >=
(* and + are also used for boolean AND and boolean OR)
Boolean expressions evaluate to 0 for false and 1 for true

对字符串类
& 合并
其他函数 返回值为数或字符串

解析函数为递归函数
被提供待解析的表达式
单独的片段
一个起始位
解析返回一个变量结构

流程
记号->变量->函数->常量
操作符

变量结构由链表储存
{
char *name
value
*}
*next
}

value emum type %{int
double
char

基本的常数运算

basexpr2.c
数值表达式

#include
#include
#include
#include
//~ #include
float expr();
float expr0();
float expr1();
float expr2();
float expr3();
float expr4();
float expr5();
float expr6();
char *e;
float expro=0;

double sin(double i){
return i+1;
}

float expr(){
char* o;
int i=expro,j;
expro=0;
do{
o=e;
expro=expr4();
}while(o!=e);
j=expro;
expro=i;
return j;
//~ return expr4();
}

float expr4(){
float o=expr3();
while(isspace(*e))e++;
if(!strncmp(e,"<=",2)){ e+=2; return o<=expr3(); }else if(!strncmp(e,">=",2)){
e+=2;
return o>=expr3();
}else
if(*e=='<'){ e++; return or,4:r->l
}else
if(*e=='>'){
e++;
return o>expr3();
}else{
return o;
}
}

float expr3(){
float o=expr2();
while(isspace(*e))e++;
if(*e=='='){
e++;
return o==expr2();
}else
if(!strncmp(e,"<>",2)){
e+=2;
return o!=expr2();
}else{
return o;
}
}

float expr2(){

float o=expr1();
while(isspace(*e))e++;
if(*e=='+'){
e++;
return o+expr1();//strtod(e,&endp);
}else
if(*e=='-'){
e++;
return o-expr1();//strtod(e,&endp);
}else{
return o;
}
}

float expr1(){
float o=expr0();
while(isspace(*e))e++;
if(*e=='*'){
e++;
return o*expr0();
}else
if(*e=='/'){
e++;
return o/expr0();
}else{
return o;
}
}

float expr0(void){
//~ char *endp;
//~ float o=strtod(e,&e);
while(isspace(*e))e++;
if(*e=='('){
e++;
float o=expr();
e++;
return o;
}else
if(isalpha(*e)){
if(!strncmp(e,"sin(",4)){
e+=4;
//~ return sin(expr());
//~ e++;
float o=expr();
e++;
return sin(o);
}
}else{
/* o=strtod(e,&e);//printf("%d\n",o);
* //~ e=endp;
* //~ else
*
* if(*e==')'){
* e++;printf("%d\n",o);
* return expr2(e);
* }else{
*
* return o;
* }
*/ if(expro!=0){float o=expro;expro=0;return o;}
else{return strtod(e,&e);}

//~ return strtod(e,&e);
}
}

int main(int argc, char** argv){
e="4+<5"; i="expr();">

basstrexpr.c
字符串表达式

#include
#include
#include
#include

char *e;
char* getstr();
char* strexpr1();

char* strexpr1(){
char* o=getstr();
while(isspace(*e))e++;
if(*e=='&'){
e++;
while(isspace(*e))e++;
char* p=strexpr1();
char* q=strcat(strcpy(malloc(strlen(o)+strlen(p)+1),o),p);
free(o);free(p);
return q;
}else{
return o;
}
}

char* getstr(){
while(isspace(*e))e++;
//not necessary
//~ if(*e=='('){
//~ e++;
//~ char* o=strexpr1();
//~ e++;
//~ return o;
//~ }else
if(*e=='\"'){
int i;
e++;
i=strchr(e,'\"')-e;
//~ printf("%d\n",i);
char* p;
p=strncpy(malloc(i+1),e,i);
p[i]='\0';
e+=i+1;
//~ if(p[i-2]!="\0"){
//~ p[i-2]="\0";
//~ }
//~ printf("%d\n%d\n%s\n",i,strlen(p),p);
return p;
}else
if(!strncmp(e,"left(",5)){
e+=5;
char* o=strexpr1();
e++; // ,
int i=strtod(e,&e);
e++; // )
char *p=strncpy(malloc(i+1),o,i);
p[i]='\0';
free(o);
return p;
}
}

int main(int argc, char** argv){
e="left(\"ABcdefg\"&\"CD\",9)&\"EF\"";
printf("e]%s\n",e);
char* i=strexpr1();
printf("]%s\n",i);
printf("]%s\n",e);
free(i);
return 0;
}


basvarnum.c
变量-数字部分

#include
#include
#include
#include
struct num* findnum(char*name);
float getnum(char *name);
int putnum(char *name,float value);

struct num{
char*n;
float v;
struct num *next;
} lne;//list num start
struct num* lns=⪇
//~ struct num ;
//~ lns.v=0.0;
//~ lns.next=NULL;
struct num* findnum(char*name){
struct num* i;
for(i=lns;(i->next)!=NULL;i=i->next){
if(strcmp(i->n,name)==0){
return i;
}
}
printf("not found %s\n",name);
return NULL;
}

float getnum(char *name){
struct num* o=findnum(name);
if(o!=NULL){
return o->v;
}
return 0;
}
int putnum(char *name,float value){
struct num* o;
o=findnum(name);
if(o!=NULL){//exist
o->v=value;
return 0;
}else{//new
o=malloc(sizeof(struct num));
o->n=name;
o->v=value;
o->next=lns;
lns=o;}
return 0;
}

int main(int argc, char** argv){
lne.n="test";
lne.v=123456;
lne.next=NULL;
putnum("a",1);
putnum("b",2);
putnum("c",3);
putnum("b",980);
//~ printf("%g\n",lns->v);
//~ lns=lns->next;
//~ printf("%g\n",lns->v);
//~ lns=lns->next;
//~ printf("%g\n",lns->v);
//~ lns=lns->next;
//~ printf("%g\n",lns->v);
//~ lns=lns->next;
//~ printf("%g\n",lns->v);
//~ findnum("b");
struct num* o=findnum("a");
if(o!=NULL){
printf("%g\n",o->v);
}

printf("%g\n",getnum("b"));
return 0;
}



Part3
变量存放.txt

以链表为基础name->value
局部变量用局部链
或加前缀
或允许同名并针对块语句处理

isitem(",")
=" "*," "*
e++

设计文档与草图
和编码过程

内置函数
数学函数num->num
字符串str->str
str->num
len
val
num->str
str/str$

合并为函数,也可match ,用
if(!strncmp(e,"while",5)){
e+=5;
}
while(isspace(*e))e++;

或建立单独的词法分析函数


对于模块先理,有规划和散开简单的尝试,再补充技术要点,使能初步运行,再补完和修改
有步骤和完成效率,补完类似代码时,目标相对非模糊

往专业化的痕迹

bas转c
添加如字符串库


块语句
设置execline标志判断块内是否执行(或passline)
某变量为记录块的嵌套层数
如果要层可嵌套,则块的首尾语句都要处理,不受标志影响
上层块设定不执行块内语句(不包含结构语句),内层则不做判断,直到上层的结束时恢复标志
块内可有局部变量

对解释while/wend块,若在执行状态则wend处跳回while之前,否则继续执行之后的语句

label table建立(常量)

basexpr3.c
上部分的代码合并并添加新特性

#include
#include
#include
#include
//~ #include

char* getstr();
char* strexpr1();


//================================================================================================
struct num* findnum(char*name);
float getnum(char *name);
int putnum(char *name,float value);

struct num{
char*n;
float v;
struct num *next;
} lne;//list num start
struct num* lns=⪇
//~ struct num ;
//~ lns.v=0.0;
//~ lns.next=NULL;
struct num* findnum(char*name){
struct num* i;
for(i=lns;(i->next)!=NULL;i=i->next){
if(strcmp(i->n,name)==0){
return i;
}
}
printf("not found %s\n",name);
return NULL;
}

float getnum(char *name){
struct num* o=findnum(name);
if(o!=NULL){
return o->v;
}
return 0;
}
int putnum(char *name,float value){
struct num* o;
o=findnum(name);
if(o!=NULL){//exist
o->v=value;
return 0;
}else{//new
o=malloc(sizeof(struct num));
o->n=name;
o->v=value;
o->next=lns;
lns=o;}
return 0;
}

//~ int main(int argc, char** argv){
//~ lne.n="test";
//~ lne.v=123456;
//~ lne.next=NULL;
//~ putnum("a",1);
//~ putnum("b",2);
//~ putnum("c",3);
//~ putnum("b",980);

//~ struct num* o=findnum("a");
//~ if(o!=NULL){
//~ printf("%g\n",o->v);
//~ }

//~ printf("%g\n",getnum("b"));
//~ return 0;
//~ }
//============================================================================

float expr();
float expr0();
float expr1();
float expr2();
float expr3();
float expr4();
float expr5();
float expr6();
char *e;
float expro=0;

double sin(double i){
return i+1;
}

float expr(){
char* o;
int i=expro,j;
expro=0;
do{
o=e;
expro=expr4();
}while(o!=e);
j=expro;
expro=i;
return j;
//~ return expr4();
}

float expr4(){
float o=expr3();
while(isspace(*e))e++;
if(!strncmp(e,"<=",2)){ e+=2; return o<=expr3(); }else if(!strncmp(e,">=",2)){
e+=2;
return o>=expr3();
}else
if(*e=='<'){ e++; return or,4:r->l
}else
if(*e=='>'){
e++;
return o>expr3();
}else{
return o;
}
}

float expr3(){
float o=expr2();
while(isspace(*e))e++;
if(*e=='='){
e++;
return o==expr2();
}else
if(!strncmp(e,"<>",2)){
e+=2;
return o!=expr2();
}else{
return o;
}
}

float expr2(){

float o=expr1();
while(isspace(*e))e++;
if(*e=='+'){
e++;
return o+expr1();//strtod(e,&endp);
}else
if(*e=='-'){
e++;
return o-expr1();//strtod(e,&endp);
}else{
return o;
}
}

float expr1(){
float o=expr0();
while(isspace(*e))e++;
if(*e=='*'){
e++;
return o*expr0();
}else
if(*e=='/'){
e++;
return o/expr0();
}else{
return o;
}
}

float expr0(void){
//~ char *endp;
//~ float o=strtod(e,&e);
while(isspace(*e))e++;
if(*e=='('){
e++;
float o=expr();
e++;
return o;
}else
if(isalpha(*e)){
if(!strncmp(e,"sin(",4)){
e+=4;
//~ return sin(expr());
//~ e++;
float o=expr();
e++;
return sin(o);
}else
if(!strncmp(e,"len(",4)){
e+=4;
//~ return sin(expr());
//~ e++;
char* o=strexpr1();
e++;
int i=strlen(o);
free(o);
return i;
}else{//getvar
char* p=e;
while(isalnum(*e)){
e++;
}
//~ puts(e);
//~ printf("%d\n",e-p);
int i=e-p;
p=strncpy(malloc(i+1),p,i);
p[i]='\0';
puts(p);
float l=getnum(p);
free(p);
return l;
}
}else{
/* o=strtod(e,&e);//printf("%d\n",o);
* //~ e=endp;
* //~ else
*
* if(*e==')'){
* e++;printf("%d\n",o);
* return expr2(e);
* }else{
*
* return o;
* }
*/ if(expro!=0){float o=expro;expro=0;return o;}
else{return strtod(e,&e);}

//~ return strtod(e,&e);
}
}

//=====================================================================================
//~ char *e;
//~ char* getstr();
//~ char* strexpr1();

char* strexpr1(){
char* o=getstr();
while(isspace(*e))e++;
if(*e=='&'){
e++;
while(isspace(*e))e++;
char* p=strexpr1();
char* q=strcat(strcpy(malloc(strlen(o)+strlen(p)+1),o),p);
free(o);free(p);
return q;
}else{
return o;
}
}

char* getstr(){
while(isspace(*e))e++;
//not necessary
//~ if(*e=='('){
//~ e++;
//~ char* o=strexpr1();
//~ e++;
//~ return o;
//~ }else
if(*e=='\"'){
int i;
e++;
i=strchr(e,'\"')-e;
//~ printf("%d\n",i);
char* p;
p=strncpy(malloc(i+1),e,i);
p[i]='\0';
e+=i+1;
//~ if(p[i-2]!="\0"){
//~ p[i-2]="\0";
//~ }
//~ printf("%d\n%d\n%s\n",i,strlen(p),p);
return p;
}else
if(!strncmp(e,"left(",5)){
e+=5;
char* o=strexpr1();
e++; // ,
int i=strtod(e,&e);
e++; // )
char *p=strncpy(malloc(i+1),o,i);
p[i]='\0';
free(o);
return p;
}
}

//~ int main(int argc, char** argv){
//~ e="left(\"ABcdefg\"&\"CD\",9)&\"EF\"";
//~ printf("e]%s\n",e);
//~ char* i=strexpr1();
//~ printf("]%s\n",i);
//~ printf("]%s\n",e);
//~ free(i);
//~ return 0;
//~ }
//========================================================================================

int main(int argc, char** argv){
putnum("a",1);
putnum("b",2);
putnum("cde",3);
e="len(\"asf\")+1";
float i=expr();
printf("%g",i);
return 0;
}


baslineexper.c
按行解析

#include
#include
#include
#include

char *e=
//"0 goto 30 \n"
//"5 print a\n"
"10 while 1\n"
"pause\n"
"while 1\n"
"print in\n"
"pause f\n"
"wend\n"
"wend\n"
//"20 goto 25\n"
"25 end\n"
"30 print 3\n";

char* pe;
char *s[256];//存放指针的数组,不用存行号了
char **ps;//指针 指向 指,数组(类型为指针)的元素

int main(int argc, char** argv){
pe=e;
ps=s;
int ln;
e--;
int passline=0;//跳过执行块内语句,非零为块的条件不成立时
do{
e++;
ln=strtol(e,&e,10);//pass line num
printf("e>\n===\n%s===\n",e);

while(isspace(*e))e++;
if(!strncmp(e,"while",5)){
//e+=5;
puts("[while]");
*ps++=e;
e+=5;
int i=strtod(e,&e);
if(passline==0){
passline=(i==0);
}else passline++;
printf("i='%d'\t%d\n",i,passline);
//~ push(ln);
if(ps==s+10)exit(5);
}else
if(!strncmp(e,"wend",4)){
e+=4;
puts("[wend]");
//~ int i=strtod(e,&e);
//~ printf("i='%d'\n",i);
printf("i\t%d\n",passline);
//~ pop(ln);
//~ //goto ln
if(passline==0){e=*--ps;}
else {--ps;passline--;}

printf("i\t%d\n",passline);
}else

if(passline)continue;
else

if(!strncmp(e,"print",5)){
e+=5;
puts("[print]");
while(isspace(*e))e++;
//

}else

if(!strncmp(e,"pause",5)){
e+=5;
puts("[pause]");


}else

if(!strncmp(e,"goto",4)){
e+=4;
puts("goto");
int i=strtod(e,&e);
printf("i='%d'\n",i);
e=pe-1;
do{
e++;
if(i==strtol(e,&e,10))break;
}while(e=strchr(e,'\n'));



//~ push(ln)
}else

if(!strncmp(e,"for",3)){
e+=3;
puts("[for]");
//~ int i=strtod(e,&e);
//~ printf("i='%d'\n",i);
//~ push(ln)
}else
if(!strncmp(e,"next",4)){
e+=4;
puts("[next]");
//~ int i=strtod(e,&e);
//~ printf("i='%d'\n",i);
//~ pop(ln);
//goto ln
}else
if(!strncmp(e,"end",3)){
e+=3;
puts("[end]");
exit(0);
}
//block,gosub,let,def,data,dim
//else
//if//to
//nextline
}while(e=strchr(e,'\n'));

puts("prog end");

return 0;
}


这个,我编辑器的框好小啊,纯写文字还好,一贴代码自己已经晕了。强调一下,我没考虑错误处理,贴的都是能编译的代码。自己这样一行行写的也是好耗时间的,自己还是不熟练啊。特别是把构想的细处实现的时候,还只有找个安静的地方一人想想才有些进展啊。

补充一下,目前的代码是把数,字符串,数组,变量分开处理的,包括解析和变量存放,比较简单的。另一种是变量是引用一个值,而值是有类型的,可以被处理函数获取。而不同于上面的觉得遇到的应该是什么类型。
表达式解析,除了用专用的词法与句法分析工具,可以递归解析。或从左到右,用两个stack存放元素和操作符。根据操作符的优先级,来进行运算。需要注意stack的长度,避免溢出或动态管理。目前觉得这样可能比递归会更好处理元素类型(?)。
现在是按照纯文本,没有编译加虚拟机,为跨平台考虑。可以解释器与虚拟机分离,使客户端轻便,但不要影响描述性脚本数据的易编辑。

Part4
上面实验代码就这样吧,不行再修改,以后重写时会用到。bas的解释器没写完,暂时停工了,在等打算好下一步的规划。
再贴一点上面已包含的小片段吧。还有一些参考资料。小片段的内容还思路很明了的感觉啊。

K&R
http://cis.csuohio.edu/~somos/ddsbasic.c
http://www.personal.leeds.ac.uk/~bgy1mm/Minibasic/MiniBasicHome.html
WxBasic PDF
FreeBasic chm
http://www.nicholson.com/rhn/basic/
编译原理
编程语言概念/原理

注意需要引用的库,K&R关于库的部分相当粗略。

int GetFileLen(){
FILE *fp;
int fl;
//FILE *fopen(char *name, char *mode);
fp = fopen("do2.c","r");
fseek(fp,0l,SEEK_END);
fl=ftell(fp);
//printf("%d",i);
fclose(fp);
return fl;
}


#include
#include
#include
#include

int main(int argc, char** argv){
char* e="assd+sdfdf";
char* p=e;
while(isalnum(*e)){
e++;
}
puts(e);
printf("%d\n",e-p);
int i=e-p;
p=strncpy(malloc(i+1),p,i);
p[i]='\0';
puts(p);
//free(p);
return 0;
}


...


回收贴了,东西杂乱了一点。
已经成了我不喜欢的形态了。
而且没语法高亮好不习惯,不如直接备份文件了,不过这里好自己附些评论。
对于耗时的事情,定计划长期行为,还是会有效过些。
当然也要预定好目的和结果。

补一下有关日期(会发现是纯粹在写着娱乐啊,日期是最后修改日期)

开贴 090812
today 090813
exp.exe 090709
lisp.c 090712
lisp7.c 0907113
3bas2.c 090720
复件 basexpr.c 090723
复件 basvarnum.c 090731
basexpr2.c 090729
basexpr3.c 090801
BAS.txt 090720
BAS表达式解析.txt 090723
basexpr.c 090727
basexpr2.c 090729
basstrexpr.c 090731
basvarnum.c 090731
basexpr3.c 090801
复件 baslineexper.c 090807
baslineexper.c 090811
变量存放.txt 090811

对这些日期,我承认,我只是想证明一下自己的存在感。
我这段期间里上cnbeta和acfun(我也是东方爱好者哦,还没狂热)也比较多,估计会有同好者看见啊。

====顺便写点,也回收了
说一下前面那贴翻译,目前没计划推动说要就翻译全文,仅凭喜好一点点做了。看来没翻译全部完成的可能,不过不至于是看自己无聊时间到什么地步才做的翻译。

我在自聊?

====
091029
The C++ Programming Language,Special Edition 里把简单的表达式计算作为示例,有很好的代码(相比我的那些就...),即使用C改写也是很容易的。

没有评论: