首页
社区
课程
招聘
[求助]自顶向下预测分析方法c转汇编
发表于: 2007-4-27 09:43 6310

[求助]自顶向下预测分析方法c转汇编

2007-4-27 09:43
6310
编译原理自顶向下预测分析方法c语言版如下。有没有哪位大侠可以转成asm让大家学习下。
#include<stdio.h>
#include<malloc.h>

struct struCH{
  char     ch;
  struct   struCH *next;
}struCH,*temp,*head,*shift,*top,*base;
/*head指向线性链表的头结点,shift指向动态建成的结点
 *top和base分别指向堆栈的顶和底
 */
FILE   *fp;
char     curchar;    /*存放当前待比较的字符*/
char     curtocmp;    /*存放当前栈顶的字符*/
char    ch;
int      right, i,j;
int table[5][9]={      /*存储预测分析表,1为有产生式,0为无*/
      {1,0,0,0,0,1,0,0,0},
      {0,1,1,0,0,0,1,1,1},
      {1,0,0,0,0,1,0,0,0},
      {0,1,1,1,1,0,1,1,1},
      {1,0,0,0,0,1,0,0,0}}; 

void main(int argc,char *argv[]){
  void puch(char ch);
  void pop();
  void doforpush(int t);
  void identify();
  
  int errnum=0, k=0, countchar=0, rownum;
  int m=0;
  int charerr=0;  /*有非法字符时的开关控制量*/
  
  /*******************以只读方式打开文件*********************/
    
  if((fp=fopen(argv[1],"r"))==NULL){
    printf("\n\tCan not open file %s,or not exist it!\n",argv[1]);
    exit(0);     /*文件不存在or打不开时,正常退出程序*/
  }
  else printf("\n\tSuccess open file: %s\n",argv[1]);  /*成功打开文件*/
    
  /******************遍历整个文件检测是否有非法字符********************/
  
  /*如果用while(!feof(fp))语言,将会多出一个字符而难以控制,
   *所以这里采用先计算字符数量再遍历整个文件来检测其否有非法字符*/
  /*[1]计算文件中字符数量*/
  while(!feof(fp)){
    ch=getc(fp);   /*这里只是让指针往前移*/
    countchar++;  /*统计文件中的字符数(包括换行符及文件结束符)*/
  }
  rewind(fp);      /*将fp文件指针重新指向文件头处,以备后面对文件的操作*/
  if(countchar= =0){    /*空文件*/
    printf("\t%s is a blank file!\n",argv[1]); 
    exit(0);      /*正常退出本程序*/
  }  
  /*[2]开始遍历文件*/
  while(k<(countchar-1)){/*加换行符后countchar仍多一个,故减1*/
    ch=getc(fp);    
    if(!(ch= ='('||ch= =')'||ch= ='i'||ch= ='+'||ch= ='-'||ch= ='*'||ch= ='/'||ch= ='#'||ch= ='\n')){ 
      charerr=1;errnum++;/*charerror出错标记,errnum统计出错个数*/
    }
    k++;  
  }
  rewind(fp);      /*将fp文件指针重新指向文件头处,以备后面的建链表操作*/
  if(charerr= =1){  /*文件中有非法字符*/
    printf("\n\t%d Unindentify characters in file %s \n",errnum,argv[1]);
    exit(0);      /*正常退出本程序*/
  }
    
  /*******************非空且无非法字符,则进行识别操作*****************/
  for(rownum=1;m<(countchar-1);rownum++){  /*识别所有行,rownum记录行号*/
    /* 初始变量及堆栈和 */
    right=1;    
    /* '#''E'进栈 */
    base=malloc(sizeof(struCH));   /*初始化堆栈*/
    base->next=NULL;
    base->ch='#';
    temp=malloc(sizeof(struCH));
    temp->next=base;
    temp->ch='E';
    top=temp;                               /*栈顶指针top指向栈顶*/
    
    /*初始存放待识别的表达式的线性链表头*/
    shift=malloc(sizeof(struCH));
    shift->next=NULL;
    head=shift;
    
    /*读取一行形成线性链表*/
    ch=getc(fp);putchar(ch);m++;
    while(ch!='\n'&&m<(countchar)){ /*行末or到文件尾。最后会读取文件结束符*/
      /*读取ch,读取存入链*/
      temp=malloc(sizeof(struCH));
      temp->ch=ch;
      temp->next=NULL;
      shift->next=temp;
      shift=shift->next;
      ch=getc(fp);
      if(m!=(countchar-1)) putchar(ch);  /*不输出最后一次读取的文件结束符*/
      m++;
    }

    head=head->next;    /*消去第一个空头结点,并使head指向非空线性链表头*/
    shift=head;      /*shift指向头结点,以便后面识别操作*/
    putchar('\n');
    identify();      /*开始识别一行*/
    if(!right)         /*错误提示:[文件名] Line [行号]:error expression!*/
      printf("%s  Line %d:\t  error expression!\n",argv[1],rownum);  
    else          /*正确提示:[文件名] Line [行号]:right expression!*/
      printf("%s  Line %d:\t  right expression!\n",argv[1],rownum);  
    putchar('\n');
  }/*end for*/  
  printf("Completed!\n");
  fclose(fp);  /*关闭文件*/
  exit(0);    /*正常退出程序*/
}

/*入栈函数*/
void push(char ch){
  temp=malloc(sizeof(struCH));
  temp->ch=ch;
  temp->next=top;
  top=temp;
}

/*出栈函数*/
void pop(void){
  curtocmp=top->ch;
  if(top->ch!='#')
    top=top->next;
}

/*根据数组下标计算的值找对应的产生式,并入栈*/
void doforpush(int t){
  switch(t){
    case 0:push('A');push('T');break;
    case 5:push('A');push('T');break;
    case 11:push('A');push('T');push('+');break;
    case 12:push('A');push('T');push('-');break;
    case 20:push('B');push('F');break;
    case 25:push('B');push('F');break;
    case 33:push('B');push('F');push('*');break;
    case 34:push('B');push('F');push('/');break;
    case 40:push('i');break;
    case 45:push(')');push('E');push('(');
  }
}

/*根据curchar,curtocmp转为数字以判断是否有产生式*/
void changchartoint()
{
  switch(curtocmp)         /*非终结符:栈顶*/
  {
    case 'A':i=1;break;
    case 'B':i=3;break;
    case 'E':i=0;break;
    case 'T':i=2;break;
    case 'F':i=4;
  }
  switch(curchar)    /*终结符:待识别的表达式中*/
  {
    case 'i':j=0;break;
    case '+':j=1;break;
    case '-':j=2;break;
    case '*':j=3;break;
    case '/':j=4;break;
    case '(':j=5;break;
    case ')':j=6;break;
    case '#':j=7;
  }
}

/*识别算法函数*/
void identify()
{
  int t;
  for(;;)
  {
    pop();           /*读取栈顶的字符存curtocmp中*/
    curchar=shift->ch;      /*读取链中的一个字符存curchar*/
    printf("\t%c-->%c\n",curchar,curtocmp);    
    if(curtocmp=='#' && curchar=='#')      break;
    if(curtocmp=='A'||curtocmp=='B'||curtocmp=='E'||curtocmp=='T'||curtocmp=='F'){
      if(curtocmp!='#'){    /*[1]未到栈底时,匹配字符*/
        changchartoint();
        if(table[i][j]){       /*[1.1]有产生式*/
          t=10*i+j;      /*计算产生式在数组中的位置*/
          doforpush(t);    /*找对应t的产生式,并入栈*/
          continue;
        }
        else{         /*[1.2]没有产生式*/
          right=0;         /*出错*/
          break;
        }
      }
      else{           /*[2]到栈底,当前比较字符为'#'*/
        if(curtocmp!=curchar){ /*输入行中最后一字符非'#'*/
          right=0;        /*出错*/
          break;
        }
        else
          break;           /*正确*/
      }
    }
    else{  /*若当前字符为终结符*/
      if(curtocmp!=curchar){
        right=0;   /*出错*/
        break;
      }
      else{
        shift=shift->next;  /*读取下一个字符*/
        continue;
      }
    }
  }/*end for*/
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
2
纯算法的东西,看汇编会累死人的
2007-4-28 09:12
0
雪    币: 260
活跃值: (162)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
编译器设置一下,中间生成汇编文件即可,一个大的算法手工转换会累死人的
2007-4-28 11:01
0
雪    币: 217
活跃值: (99)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
这东西手工转成汇编没意义.
即使是微软的VC编译器也不会用汇编写成的.
2007-4-28 11:10
0
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
5
两条路:
[1] 利用VC编译器,进入调试状态,如果VC6的话,直接ALT+8,就可以看汇编代码了
[2] 利用VC编译器生成个*.exe,用OD看

如果是我,两条都不走
2007-4-28 22:10
0
雪    币: 2134
活跃值: (14)
能力值: (RANK:170 )
在线值:
发帖
回帖
粉丝
6
[QUOTE=北极星2003;302716]两条路:
[1] 利用VC编译器,进入调试状态,如果VC6的话,直接ALT+8,就可以看汇编代码了
[2] 利用VC编译器生成个*.exe,用OD看

如果是我,两条都不走[/QUOTE]

原因是什么,我觉得vc优化的还好啊
2007-4-28 22:45
0
雪    币: 207
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
谢谢了!我决定自己写个算了。带窗口界面的。应该可以提高下汇编的水平把
2007-4-30 12:32
0
游客
登录 | 注册 方可回帖
返回
//