- 论坛徽章:
- 3
|
又为查找匹配的右方括号建立了"cache",可是这几乎没用,因为在我的解释器里,只有第一次遇到该循环(就是遇到左中括号)的时候因*p==0才不得不找到所匹配的右中括号,以便找到下一个执行点,而这种情况少见。一般时候都是靠右边括号来判断是否跳出循环,而回到该循环体的首部是借助左边括号入栈,所以很快。
但我还是给出了这个"cache",
编译可以定义USE_MATCH_TABLE宏以便加入这个结构,也可以定义cache深度MAX_DEPTH(我并不希望它无限,虽然可以办到,但那样反而不好,不定义则默认为2)
例如
gcc -DUSE_MATCH_TABLE -DMAX_DEPTH=1 bf.c -o bf -O2
- /*bf.c*/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- char s[30000]={0};
- char code[100000];
- int len = 0;
- int stack[100];
- int stack_len=0;
- #ifndef DEBUG
- #define DEBUG 0
- #endif
- #ifdef USE_MATCH_TABLE
- #if (!defined(MAX_DEPTH)) || MAX_DEPTH<=0
- #define MAX_DEPTH 2
- #endif
- typedef struct _match_des_t{
- int left_offset;
- int right_offset;
- struct _match_des_t* next;
- }match_des_t;
- typedef struct {
- int depth;
- match_des_t* first;
- } match_table_t;
- match_table_t match_table[256]={{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0},{.depth=0}
- };
- static inline int search_match(int left)
- {
- int i;
- match_des_t* pmatch_des;
- match_table_t* pmatch_table=&match_table[left&0xff];
- if(pmatch_table->depth==0)
- return 0;
- for(i=0,pmatch_des=pmatch_table->first;i<pmatch_table->depth;i++) {
- if(pmatch_des->left_offset==left)
- return pmatch_des->right_offset;
- pmatch_des=pmatch_des->next;
- }
- return 0;
- }
- static inline void add_match(int left,int right)
- {
- match_des_t* pmatch_des;
- match_table_t* pmatch_table=&match_table[left&0xff];
- switch(pmatch_table->depth) {
- case 0:
- pmatch_table->first=malloc(sizeof(match_des_t));
- if(pmatch_table->first==NULL) {
- fprintf(stderr,"%s:%d\n",__FILE__,__LINE__);
- exit(6);
- }
- pmatch_table->first->left_offset=left;
- pmatch_table->first->right_offset=right;
- pmatch_table->depth=1;
- break;
- case MAX_DEPTH:
- pmatch_table->first->left_offset=left;
- pmatch_table->first->right_offset=right;
- break;
- default:
- pmatch_des = pmatch_table->first;
- pmatch_table->first=malloc(sizeof(match_des_t));
- if(pmatch_table->first==NULL) {
- fprintf(stderr,"%s:%d\n",__FILE__,__LINE__);
- exit(6);
- }
- pmatch_table->first->left_offset=left;
- pmatch_table->first->right_offset=right;
- pmatch_table->first->next=pmatch_des;
- pmatch_table->depth++;
- break;
- }
- }
- #endif
- int main(int argc,char**argv)
- {
- char c;
- int i,j,k,left_flag,left_offset,x=0;
- int x1,x2,x3,x4;
- int m,n;
- FILE* f;
- char* p=s+10000;
- if(argc==2) {
- f=fopen(argv[1],"r");
- if(f==NULL) {
- perror("fopen");
- return 1;
- }
- len=fread(code,1,sizeof(code),f);
- if(len==0&&len==sizeof(code)) {
- return 4;
- }
- } else return 2;
- /*optimization*/
- /*We can prove that n is never greater than m.So we can use the same memory*/
- for(m=0,n=0,c=0,j=0,left_flag=0;m<len;m++) {
- switch(code[m]) {
- case '+':
- switch (j) {
- case 1:
- code[n++]='>';
- break;
- case -1:
- code[n++]='<';
- break;
- case 0:
- break;
- default:
- code[n++]='p';
- code[n++]=j;
- break;
- }
- j=0;
- c++;
- break;
- case '-':
- switch (j) {
- case 1:
- code[n++]='>';
- break;
- case -1:
- code[n++]='<';
- break;
- case 0:
- break;
- default:
- code[n++]='p';
- code[n++]=j;
- break;
- }
- j=0;
- c--;
- break;
- case '>':
- switch (c) {
- case ((char)1):
- code[n++]='+';
- break;
- case ((char)(-1)):
- code[n++]='-';
- break;
- case ((char)0):
- break;
- default:
- code[n++]='a';
- code[n++]=c;
- break;
- }
- c=0;
- j++;
- if(j==0x7f) {
- code[n++]='p';
- code[n++]=0x7f;
- j=0;
- }
- break;
- case '<':
- switch (c) {
- case ((char)1):
- code[n++]='+';
- break;
- case ((char)(-1)):
- code[n++]='-';
- break;
- case ((char)0):
- break;
- default:
- code[n++]='a';
- code[n++]=c;
- break;
- }
- c=0;
- j--;
- if(j==-128) {
- code[n++]='p';
- code[n++]=-128;
- j=0;
- }
- break;
- case '.':
- case ',':
- case '[':
- switch (c) {
- case ((char)1):
- code[n++]='+';
- break;
- case ((char)(-1)):
- code[n++]='-';
- break;
- case ((char)0):
- break;
- default:
- code[n++]='a';
- code[n++]=c;
- break;
- }
- c=0;
- switch (j) {
- case 1:
- code[n++]='>';
- break;
- case -1:
- code[n++]='<';
- break;
- case 0:
- break;
- default:
- code[n++]='p';
- code[n++]=j;
- break;
- }
- j=0;
- code[n++]=code[m];
- if(code[m]=='[') {
- left_flag=1;
- left_offset=n;
- }
- break;
- case ']':
- switch (c) {
- case ((char)1):
- code[n++]='+';
- break;
- case ((char)(-1)):
- code[n++]='-';
- break;
- case ((char)0):
- break;
- default:
- code[n++]='a';
- code[n++]=c;
- break;
- }
- c=0;
- switch (j) {
- case 1:
- code[n++]='>';
- break;
- case -1:
- code[n++]='<';
- break;
- case 0:
- break;
- default:
- code[n++]='p';
- code[n++]=j;
- break;
- }
- j=0;
- if(n-1>=0&&n-2>=0&&code[n-2]=='['&&(code[n-1]=='+'||code[n-2]=='-')) {
- code[n-2]='0';
- n--;
- } else {
- code[n++]=code[m];
- if(left_flag) {
- for(i=left_offset,x1=x2=x3=0,x4=n+1;i<n;i++) {
- switch(code[i]) {
- case '+':
- if(x2==0) {
- if(x3) {
- i=n;
- break;
- }
- x3=1;
- break;
- }
- code[x4++] = 0x80|(x2&0x7f);
- code[x4++] = 1;
- break;
- case '-':
- if(x2==0) {
- if(x3) {
- i=n;
- break;
- }
- x3=-1;
- break;
- }
- code[x4++] = 0x80|(x2&0x7f);
- code[x4++] = -1;
- break;
- case 'a':
- if(x2==0)
- i=n;//quit
- code[x4++] = 0x80|(x2&0x7f);
- if(code[i+1]==(char)0x80) {
- i=n;//quit
- break;
- }
- code[x4++] = code[i+1];
- i++;
- break;
- case 'p':
- x2+=(unsigned char)code[i++];
- if(x2>63||x2<-64) {
- i=n;//quit
- }
- break;
- case '<':
- x2--;
- if(x2>63||x2<-64) {
- i=n;//quit
- }
- break;
- case '>':
- x2++;
- if(x2>63||x2<-64) {
- i=n;//quit
- }
- break;
- case ']':
- if(!x3||x2) {
- break;/***It can not be optimized******/
- }
- if(x3==-1) {
- memcpy(&code[left_offset-1],&code[n+1],x4-n-1);
- code[x4-n-1+left_offset-1]='0';
- n=x4-n-1+left_offset-1+1;
- /***Then, i must be greater than n*******/
- } else {
- for(x1=left_offset-1,x2=n+1;x2<x4;x1+=2,x2+=2) {
- code[x1]=code[x2];
- code[x1+1]=-code[x2+1];
- }
- code[x4-n-1+left_offset-1]='0';
- n=x4-n-1+left_offset-1+1;
- /***Then, i must be greater than n*******/
- }
- break;
- /*
- case '[':
- case '.':
- case ',':*/
- default:
- i=n;//quit
- break;
- }/*swtich(code[i])*/
- }/*for(i=left_offset,x1=x2=x3=x4=0;i<n;i++)*/
- } else {
- }
- }
- left_flag=0;
- break;
- default:
- break;
- }/*switch(code[m])*/
- }/*for(m=0,n=0,c=0,j=0,left_flag=0;m<len;m++)*/
- len=n;
- setbuf(stdout,NULL);
- #if DEBUG>2
- for(i=0;i<len;i++)
- putchar(code[i]);
- return 0;
- #endif
- i=0;
- while(i<len) {
- switch(code[i]) {
- case '0':
- *p=0;
- break;
- case 'a':
- i++;
- *p+=(signed char)code[i];
- break;
- case 'p':
- i++;
- p+=(signed char)code[i];
- break;
- case '+':
- (*p)++;
- break;
- case '-':
- (*p)--;
- break;
- case '>':
- p++;
- break;
- case '<':
- p--;
- break;
- case '.':
- putchar((int)(*p));
- //printf("put:%hd\n",*p);
- break;
- case ',':
- *p=getchar();
- break;
- case '[':
- if(*p) {
- stack[stack_len++]=i;
- } else {
- #ifdef USE_MATCH_TABLE
- if(x1=search_match(i)) {
- i=x1;
- break;
- }
- #endif
- for(k=i,j=0;k<len;k++) {
- //if(code[k]=='a'||code[k]=='p'||code[k]&0x80) {
- /**replaced by*****/
- if((unsigned char)code[k]>=(unsigned char)'a') {
- k++;
- continue;
- }
- code[k]=='['&&j++;
- code[k]==']'&&j--;
- if(j==0)break;
- }
- if(j==0) {
- #ifdef USE_MATCH_TABLE
- add_match(i,k);
- #endif
- i=k;
- }
- else {
- fprintf(stderr,"%s:%d\n",__FILE__,__LINE__);
- return 3;
- }
- }
- break;
- case ']':
- if(*p) {
- i=stack[stack_len - 1];
- #if DEBUG>0
- if(code[i] != '[') {
- fprintf(stderr,"%s:%d\n",__FILE__,__LINE__);
- return 0;
- }
- #endif
- } else {
- stack_len--;
- }
- break;
- default:
- #if DEBUG>1
- if(code[i]&0x80)break;
- #endif
- p[(signed char)(code[i]&(code[i]&0x40?0xff:0x7f))]+=*p*((signed char)code[i+1]);
- i++;
- break;
- }
- i++;
- //x++;
- //printf("%d : i=%d\n",x,i);
- }
- return 0;
- }
复制代码
[ 本帖最后由 cjaizss 于 2008-6-10 13:13 编辑 ] |
|