编译原理(预测分析法)

时间:2021-12-26 03:53:40

 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<windows.h>
#define MAXSIZE  100
typedef struct //定义顺序栈
{
 int data[MAXSIZE];
 int top;//栈顶指针
}SeqStack;
SeqStack *s;//定义一个指向顺序栈的指针变量
void Scaner();//词法分析扫描函数
void abc(); //词法分析扫描函数
int IsRetainLetters(char *ch);//判断是否为保留字
char GetCh(FILE *fp);//读取文件中的字符,每次只读取一个字符
void Analyse();//LL1预测分析主程序
int digit;//数字变量
FILE *fpin;//用于操作输入文件
char ch = ' ';//用于存放字符
char temp[10];//用做中间变量存放字符
int  main()
{
 printf(" 编译正在进行....../n");
    Analyse();
 printf(" 执行结束!!/n");
 return 0;
}
int Analyse_Table[10][30]=
{
 { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
 { 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0},
 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,10,10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,10, 0},
 { 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2},
 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,11,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,11, 0},
 { 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 2, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2},
 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,12,13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0} ,
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
} ;//定义预测分析表
void Init_Stack()
{
 s=new SeqStack;
 if(!s)
 {
  printf("内存分配不足");
  exit(1);
 }
 else
 {
  s->top=-1;
 }
}
int Push(int x)
{
 if(s->top==MAXSIZE-1)
 {
  printf("栈满,不能入栈!/n");
  return 0;
 }
 else
 {
  s->top++;
  s->data[s->top]=x;
  return 1;
 }
}
int Pop()
{
 int x;
 if(s->top==-1)
 {
  printf("栈空,不能出栈");
  return 0;
 }
 else
 {
  x=s->data[s->top];
  s->top--;
  return x;
 }
}
void Push_Stack(int a, int b)
{
 switch(Analyse_Table[a][b])
 {
 case  1: Push(6); Push(101); Push(1);    break;   
 case  2:                                 break;         
 case  3: Push(102); Push(103); Push(26); break;  
 case  4: Push(105); Push(106); Push(13); break; 
 case  5: Push(105); Push(106); Push(14); break; 
 case  6: Push(107); Push(108); Push(15); break;
 case  7: Push(107); Push(108); Push(16); break;
 case  8: Push(102); Push(103);           break;  
 case  9: Push(104); Push(18); Push(10);  break; 
 case 10: Push(105); Push(106);           break;
 case 11: Push(107); Push(108);           break;  
 case 12: Push(10);                       break;       
 case 13: Push(11);                       break;       
 }
}
int i,k;
void Scaner()//词法分析扫描函数
{
    fpin=fopen("in.txt","rb");//以只读的形式打开该文件
  if(fpin==NULL)
  {
   printf("文件不能打开或新建,请重新调试!/n");
   exit (0);
  }
  i=0;
  while(i++<6) temp[i]='/0'; //初始化temp数组
  i=0;
  if (ch ==' ' ) ch=GetCh(fpin);
        if(ch==EOF)//文件结束
  {
   fclose(fpin);
   return ;
  }
}
void abc()
{
  while(ch == ' ' || ch == 9 || ch == 10 || ch == 13 ) ch=GetCh(fpin);
  if(ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z')
  {
   k=0;
   while(ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >='0' && ch <= '9')
   {//读取的是字母
    temp[k++]=ch;
    ch=GetCh(fpin);
   }
   digit=IsRetainLetters(temp);
   while(i++<10) temp[i]='/0'; i=0;
  }
  else if(ch >= '0' && ch <= '9')
  {//是数字
   k=0;
   while(ch >= '0' && ch <= '9')
   {
    temp[k++]=ch;
    ch=GetCh(fpin);
   }
   digit=11;
   i=0;
   while(i++<10) temp[i]='/0';
   i=0;
   if(ch==EOF)
   {
    fclose(fpin);
    return;
   }
  }
  else if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch==':'||ch==':='||ch=='<'||ch=='<>'
   ||ch=='<='||ch=='>'||ch=='>='||ch=='='||ch==';'||ch=='('||ch==')'||ch=='#')
  {//为其他字符
   switch(ch)
   {
   case '+':  digit=13;break;
   case '-':  digit=14;break;
   case '*':  digit=15;break;
   case '/':  digit=16;break;
   case ':':  digit=17;break;
   case '=':  digit=18;break;
      case '<':  digit=20;break;
   case '<>': digit=21;break;
   case '<=': digit=22;break;
   case '>':  digit=23;break;
   case '>=': digit=24;break;
   case ':=': digit=25;break;
   case ';':  digit=26;break;
   case '(':  digit=27;break;
   case ')':  digit=28;break;
   case '#':  digit=0; break;
   default:
    break;
   }
   ch=GetCh(fpin);  
  }
  else if(ch==EOF)
  {
   fclose(fpin);
   return ;
  }
  else MessageBox(NULL,"有非法字符","ERROR",0);
}
void Analyse()
{
 int temp;
    Init_Stack();
 Push(0);   //界符入栈(#)
 Push(100);   //开始符号S入栈
 Scaner();
 abc();
 while(1)
 {
  temp=Pop();
  
  if(temp>0&&temp<100) //temp是终结符
  {
   if(digit==temp) //匹配
   {
    abc();
   }
   else 
   {
    MessageBox(NULL,"error","error",0);
    return ;
   }
  }
  else if(temp>=100||temp==0) //temp是非终结符或'#'
  {
   if(temp==0) //temp=='#'
   {
    if(digit==temp)  //匹配
    {
     MessageBox(NULL,"success","分析成功",0);
     //Beep(100,1000);
     return;
    }
    else  
    {
     MessageBox(NULL,"error","error",0);
     return ;
    }
   }
   else 
   {
    if(Analyse_Table[temp-100][digit])
    {
     Push_Stack(temp-100, digit);
    }
    else
    {
     
     MessageBox(NULL,"error","error",0);
     return ;
    }
   }
  }
  else
  {
   MessageBox(NULL,"ERROR","ERROR",0);
   return ;
  }
 }
}
//判断是否为保留字
int IsRetainLetters(char *ch)
{
 int flag=1;
 int i=0;
 char *keyword[6]={"begin","if","then","while","do","end"};
 while(i<6)
 {
  if(strcmp(ch,keyword[i])==0)
  {
   
   break;
  }
  flag++;
  i++;
 }
 if(flag>=7)
  return 10;
 else
 return flag;
}
//读取文件中的字符
char GetCh(FILE *fp)
{
 char ch;
 if(!feof(fp))
  ch=fgetc(fp);//从fp所指向的文件的当前位置每次读取一个字符
 return ch;
}