编译原理实验之预测分析算法的设计与实现

不要被大段的代码吓到,其实问题很简单,只需照着书上的过程走即可。

实验要求:

输入文法及待分析的输入串,输出其预测分析过程及结果。(基本要求就是:所有字符都只有一个字符组成,不能出现A*等字符,你可自行修改自己的文法后在用下面的代码)

注明:代码分了多个写,主函数是1.cpp代码如下(后期我会再发个链接过来可直接看到源文件,对不太熟悉VS工具的比较有帮助),想看中间结果的话可以将注释解开即可:


#include"head.h"
#include"apart_from.h"
#include"first.h"
#include"follw.h"
#include"table.h"
#include"judge.h"

int main(){
 int i=0,j;
 while((scanf("%s",form[i].formula),form[i].formula[0])!='#'){
  i++;
 }
 sum = i;
 apart();
 
 First();
 Follow();
 printf("非终结符:\n");
 printf("%s\n",ter_symbol);
 printf("终结符:\n");
 printf("%s\n",non_ter);
 
 /*
 printf("first集:\n");
 for(j=0;j<strlen(ter_symbol);j++)
  printf("%s\n",first_set[j]);
 printf("follow集:\n");
 for(j=0;j<strlen(ter_symbol);j++)
  printf("%s\n",follow_set[j]);
 */
 
 getTable();
 //printTable();//输出预测表
 printf("输入串(以‘#’号键结束):\n");
 scanf("%s",inter_symbol);
 while(inter_symbol[strlen(inter_symbol)-1]!='#'){
  printf("输入串没有以‘#’号键结束,请重新输入:\n");
  scanf("%s",inter_symbol);
 }
 printf("步骤       符号栈                 输入串      所用产生式\n");
 printf("----       ------                 ------      ----------\n");
 Judge();
 return 0;
}

 

apart_from.h的代码:

 

void apart(){
 int i,len,k=0,j,l,p;
 for(i=0;i<sum;i++){
  for(j=0;j<k;j++){
   if(ter_symbol[j]==form[i].formula[0])
    break;
  }
  if(j==k)
   ter_symbol[k++] = form[i].formula[0];
 }//非终结符
 ter_symbol[k]='\0';

 k=0;
 for(i=0;i<sum;i++){
  len = strlen(form[i].formula);
  for(j=3;j<len;j++){
   if(form[i].formula[j]=='$')
    break;
   for(l=0;l<strlen(ter_symbol);l++){
    if(form[i].formula[j]==ter_symbol[l])
     break;
   }
   for(p=0;p<k;p++){
    if(form[i].formula[j]==non_ter[p])
     break;
   }
   if(l==strlen(ter_symbol)&&p==k){
    non_ter[k++]=form[i].formula[j];
   }
  }
 }//终结符
 non_ter[k]='\0';
}

head.h的代码:

#include<stdio.h>
#include<string.h>

typedef struct {
 char formula[200];//表达式
}grammerElement;
grammerElement form[200]; //原始文法的产生式集
int sum;

char ter_symbol[200];//非终结符号
char non_ter[200];//终结符号
char inter_symbol[400];//输入符号
char first_set[100][100];//各产生式右部的FIRST集
char follow_set[100][100];//各产生式左部的FOLLOW集
int M[200][200];//分析表

//判断是非终结符
int get_ter(char a){
 for(int i=0;i<strlen(ter_symbol);i++)
  if(ter_symbol[i]==a)
   return i;
 return -1;
}
//判断是终结符
int get_non(char a){
 for(int i=0;i<strlen(non_ter);i++){
  if(non_ter[i]==a)
   return i;
 }
 return -1;
}

//判断将要加入的first集的终结符是否已经存在。
int is_sameFir(int col,int stop,char a){
 for(int i=1;i<stop;i++){
  if(first_set[col][i]==a)
   return 0;
 }
 return 1;
}

//判断将要加入的follow集的终结符是否已经存在。
int is_sameFol(int col,int stop,char a){
 for(int i=1;i<stop;i++){
  if(follow_set[col][i]==a)
   return 0;
 }
 return 1;
}

void printTable(){
 for(int i=0;i<strlen(ter_symbol);i++){
  for(int j=0;j<strlen(non_ter)+1;j++)
   printf("%d ",M[i][j]);
  printf("\n");
 }
}

first.h的代码:

//求一个非终结符的first集
int getFirst(char a,int col){
 int i,j,k=1,l,p;
 for(i=0;i<sum;i++){
  if(form[i].formula[0]==a){
   for(j=0;j<strlen(non_ter);j++){
    if(form[i].formula[3]==non_ter[j])
     break;
   } //判断是否是终结符
   if(j<strlen(non_ter)){
    if(is_sameFir(col,k,form[i].formula[3]))
     first_set[col][k++]=form[i].formula[3];
    continue;
   }//右部首字母是终结符;
   else if(form[i].formula[3]=='$'){
    if(is_sameFir(col,k,'$'))
     first_set[col][k++]='$';
    continue;
   }//右部首字母是kong;
   else if(form[i].formula[3]==a)
    continue;//右部首字母是自己;
   else{//printf("%d 1\n",col);
    for(l=3;l<strlen(form[i].formula);l++){//循环表达式找
      for(j=0;j<strlen(ter_symbol);j++){//printf("%d 2\n",col);
       if(form[i].formula[l]==ter_symbol[j])
        break;
      }//找到非终结符的下标
      if(j==strlen(ter_symbol)){//printf("%d 3\n",col);
       if(is_sameFir(col,k,form[i].formula[l]))
        first_set[col][k++]=form[i].formula[l];
       break;
      }//循环中碰到终结符,结束

      if(first_set[j][0]=='0')
       getFirst(form[i].formula[l],j);//printf("%d 4\n",col);}//first集未求,递归求first集

      for(p=1;p<strlen(first_set[j]);p++){//检查first集有没有空
       if(first_set[j][p]=='$')
        break;
       else if(is_sameFir(col,k,first_set[j][p])) //把非空的加进first集
         first_set[col][k++]=first_set[j][p];//printf("%d 5\n",col);}
      }
      if(p==strlen(first_set[j])){//没有非空的就跳出
       //flag=1;
       break;
      }
    }
    if(l==strlen(form[i].formula)&&is_sameFir(col,k,'$'))
     first_set[col][k++]='$';
   }
  }
 }
 first_set[col][k]='\0';
 first_set[col][0]='1';//标志已经求得first集
 return 0;
}

void First(){
 int i,len_ter=strlen(ter_symbol);
 for(i=0;i<len_ter;i++){
  first_set[i][0]='0';
 }
 for(i=0;i<len_ter;i++){
  if(first_set[i][0]=='0')
   getFirst(ter_symbol[i],i);
 }
}


follow.h的代码:

int getFollow(char a,int col){
 int i,j,len,k=1,p,l,flag;
 if(col==0)
  k=2;
 for(i=0;i<sum;i++){
  len=strlen(form[i].formula);
  
  for(j=3;j<len;j++){
   flag=0;
   if(form[i].formula[j]==a){
    if(j<len-1){//printf("%d %c1\n",col,a);//当前非终结符不是最终字符
     for(p=0;p<strlen(ter_symbol);p++){
      if(form[i].formula[j+1]==ter_symbol[p])
       break;
     }//找到后边非终结符的下标
     if(p==strlen(ter_symbol)){//终结符
      if(is_sameFol(col,k,form[i].formula[j+1]))
       follow_set[col][k++]=form[i].formula[j+1];//printf("%d 2\n",col);
      continue;
     }
     else{//printf("%d 3\n",col);//非终结符
      for(l=1;l<strlen(first_set[p]);l++)
       if(first_set[p][l]=='$')//将来会有漏洞
        {flag=1;}
       else if(is_sameFol(col,k,first_set[p][l])){
        
         follow_set[col][k++]=first_set[p][l];
       }
     }

    }//if/
    if(j==len-1||flag){//if(col==2) return 0;//printf("%d 4 %s %s\n",col,follow_set[0],follow_set[1]);//
    
     p=get_ter(form[i].formula[0]);//找到后边非终结符的下标
     if(a==form[i].formula[0])
     {//printf("%d 4 %s %s\n",col,follow_set[0],follow_set[1]);
      break;}
     if(follow_set[p][0]=='0'){
      getFollow(ter_symbol[p],p);
     //printf("%d %c5\n",col,ter_symbol[p]);
     }
     for(l=1;l<strlen(follow_set[p]);l++){
      if(is_sameFol(col,k,follow_set[p][l]))
       follow_set[col][k++]=follow_set[p][l];
     }
    }
   }
  }
 }
 if(strlen(follow_set[col])>1)
  follow_set[col][0]='1';
 follow_set[col][k]='\0';
 return 0;
}

void Follow(){
 int i;
 for(i=0;i<strlen(ter_symbol);i++){
  follow_set[i][0]='0';
 }
 //follow_set[0][0]='1';
 follow_set[0][1]='#';
 for(i=0;i<strlen(ter_symbol);i++){
 // printf("%s\n",follow_set[0]);
  if(follow_set[i][0]=='0')
   getFollow(ter_symbol[i],i); //printf("%c...............\n",ter_symbol[i]);}
 }
}


judge.h的代码:

int top;
char stack[200];
int x;
void Judge(){
 stack[0]='#';
 stack[1]=form[0].formula[0];
 int flag=1,step=0;
 int i,j,l;
 char print[100];
 top=1;
 x=0;//printf("----       ------                      ------\n");
 printf("  %d        ",step++);
 for(l=0;l<=top;l++)
  printf("%c",stack[l]);
 for(l=0;l<=22-top+x;l++)
  printf(" ");
 for(l=x;l<strlen(inter_symbol);l++)
  printf("%c",inter_symbol[l]);
 printf("\n");
 while(flag){
  if(get_non(stack[top])>=0){
   if(stack[top]==inter_symbol[x]){
    x++;//终结符匹配上
    top--;
    if(step<10)
     printf("  %d        ",step++);
    else
     printf(" %d        ",step++);
    for(l=0;l<=top;l++)
     printf("%c",stack[l]);
    for(l=0;l<=22-top+x;l++)
     printf(" ");
    for(l=x;l<strlen(inter_symbol);l++)
     printf("%c",inter_symbol[l]);
    printf("\n"); 
   }
   else
    break;
  }
  else if(stack[top]=='#'){
   if(stack[top]==inter_symbol[x])
    flag=0;//彻底结束
   else
    break;
  }
  else{
   int col=get_ter(stack[top]);
   int row=get_non(inter_symbol[x]);
   if(inter_symbol[x]=='#')
    row=strlen(non_ter);
    if(M[col][row]>=0){//非终结符
     if(form[M[col][row]].formula[3]=='$'){
      top--;
     }
     else
     {
      for(i=strlen(form[M[col][row]].formula)-1;i>=3;i--){
       stack[top++]=form[M[col][row]].formula[i];
      }
      top--;
     }
     if(step<10)
      printf("  %d        ",step++);
     else
      printf(" %d        ",step++);
     for(l=0;l<=top;l++)
     printf("%c",stack[l]);
     for(l=0;l<=22-top+x;l++)
      printf(" ");
     for(l=x;l<strlen(inter_symbol);l++)
      printf("%c",inter_symbol[l]);
     for(l=0;l<=(11-strlen(inter_symbol));l++)
      printf(" ");
     printf("%s",form[M[col][row]].formula);
     printf("\n");
    }
    else break;
  }
 }
 if(flag){
  printf("输入串无法匹配成功!\n");
 }
 else{
  printf("输入串匹配成功!\n");
 }
}

table.h的代码:

void getTable(){//ter_symbol[200];//非终结符号
               // non_ter[200];//终结符号
 int i,j,k,col,row,flag=0;
 for(i=0;i<strlen(ter_symbol);i++){
  for(j=0;j<strlen(non_ter)+1;j++)
   M[i][j]=-1;
 }
 for(i=0;i<sum;i++){//printf("lalallallalallalallalalla\n");
  flag=0;
  if((row=get_non(form[i].formula[3]))>=0){//printf("%d %d 1\n",row,i);
   col=get_ter(form[i].formula[0]);
   M[col][row]=i;
  }//右部是终结符
  else if((row=get_non(form[i].formula[3]))==-1){//非终结符和空
    //if()
    col=get_ter(form[i].formula[0]);//左部是行坐标
    k=get_ter(form[i].formula[3]);//右部非终结符的下标
    if(k>=0){
     for(j=1;j<strlen(first_set[k]);j++){
      if(first_set[k][j]=='$'){//非终结符的first集有空
       flag=1;
       continue;
      }
      row=get_non(first_set[k][j]);
      M[col][row]=i;
     }
    }
    if(form[i].formula[3]=='$')
    { flag=1;//printf("%c##########################\n",form[i].formula[3]);
    }
    if(flag){//右部为空,或者右部的first集有空
     for(j=1;j<strlen(follow_set[col]);j++){
      if(follow_set[col][j]=='#')
       row=strlen(non_ter);
      else row=get_non(follow_set[col][j]);
      M[col][row]=i;
     }
    }
  }
 }
}


鄙人不才,欢迎找错。
  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值