scau编译原理综合性实验

一、题目要求

题目

选择部分C语言的语法成分,设计其词法分析程序、语法语义分析程序。

要求

设计并实现一个一遍扫描的词法语法语义分析程序,将部分C语言的语法成分(包含赋值语句、if语句、while循环语句)翻译成三地址代码,要求有一定的出错提示和错误恢复功能。

二、源码 

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

#define BUFFSIZE 5000
char prog[BUFFSIZE],token[8];
char ch,ch1;
int syn,p,q,m,n,sum,i=1,k=0,kk,flag=0;
char *rwtab[32]={"main","break","case","char","define","continue","default",
                 "do","double","else","what","extern","float","for","goto","if",
                 "int","long","stack","return","short","fopen","sizeof",
				 "static","struct","switch","typedef","enum","unsigned","void","fclose","while"};

int main()  /*主函数*/
{
  void scaner();
  int lrparser();
  FILE *fp;
  if((fp=fopen("test.txt","r"))==NULL)
    { printf("无法打开文件!\n");
      exit(1);
    }
  p=0;
  while(!feof(fp))
    {  prog[p++]=fgetc(fp);
       if(p>=5000)
       {  printf("缓冲区容量不够!\n");
          exit(1);
           }
    }/*把文件test中的内容存入数组prog中*/
  fclose(fp);
  printf("%s\n",prog);
  p=0;
printf("输出词法分析结果:\n");
	do
	{
		scaner();
		switch(syn)
		{
		case 34:printf("(%d,%d),",syn,sum);break;
		case -1:printf("error,");break;
		default:printf("(%d,%s),",syn,token);
		}
	}while(syn!=0);
	p=0;
	printf("\n语法语义的分析开始:\n");
  scaner();
  lrparser();
  system("pause");
  return 0;
}

void scaner()
{
  for(n=0;n<8;n++) token[n]=NULL;
  m=0;
  sum=0;
  ch=prog[p];
  while(ch==' '||ch=='\n')
  { p++;
    ch=prog[p];
      }/*读下一个字符*/

  if((ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z'))
  { while((ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z')||(ch>='0'&&ch<='9'))
    { token[m]=ch;
      m++;p++;
      ch=prog[p];
        }

  token[m++]='\0';
  syn=33;
  for(n=0;n<32;n++)
     if(strcmp(token,rwtab[n])==0)
     { syn=n+1;
       break;
         }
  }/*判断输入字符是否为标识符或者关键字的情况*/

  else
      if(ch>='0'&&ch<='9')
      { while(ch>='0'&&ch<='9')
        { sum=sum*10+ch-'0';
          p++;
          ch=prog[p];
            }
        syn=34;
    }/*判断输入字符是否为整型常数的情况*/

  else
      switch(ch)
      {
       case '<':token[m]=ch;
                p++;
                ch=prog[p];
                if(ch=='>')
                { syn=42;
                  m++;
                  token[m]=ch;
                  p++;
                }/*出现<>的情况*/
                else if(ch=='=')
                { syn=43;
                  m++;
                  token[m]=ch;
                  p++;
                }/*出现<=的情况*/
                else
                { syn=41;}
                break;

       case '>':token[m]=ch;
                p++;
                ch=prog[p];
                if(ch=='=')
                { syn=45;
                  m++;
                  token[m]=ch;
                  p++;
                }/*出现>=的情况*/
                else
                {syn=44;}
                break;

       case ':':token[m]=ch;
                p++;
                ch=prog[p];
                if(ch=='=')
                { syn=40;
                  m++;
                  token[m]=ch;
                  p++;
                }/*出现:=的情况*/
                else
                {syn=39;}
                break;

       case '/':token[m]=ch;
                p++;
                ch=prog[p];
                if(ch=='*')
                { syn=51;
                  q=0;
                  m++;
                  token[m]=ch;
                  p++;
                  q=p+1;
                  while(prog[p]!='*'||prog[q]!='/')
                  {p++;q++;}
                    }/*出现注释'/*'的情况*/
                else
                {syn=38;}
                break;

       case '*':token[m]=ch;
                p++;
                ch=prog[p];
                if(ch=='/')
                { syn=52;
                  m++;
                  token[m]=ch;
                  p++;
                }
                else
                {syn=37;}
                break;

       case '+':syn=35;token[0]=ch;p++;break;
       case '-':syn=36;token[0]=ch;p++;break;
       case '=':syn=46;token[0]=ch;p++;break;
       case ';':syn=47;token[0]=ch;p++;break;
       case '(':syn=48;token[0]=ch;p++;break;
       case ')':syn=49;token[0]=ch;p++;break;
       case '%':syn=50;token[0]=ch;p++;break;
       case '{':syn=53;token[0]=ch;p++;break;
       case '}':syn=54;token[0]=ch;p++;break;
       case ',':syn=55;token[0]=ch;p++;break;
       case '#':syn=0;token[0]=ch;p++;break;
       default:syn=-1;
          }

}

void emit(char *result,char *ag1,char *op,char *ag2)
{
    printf("(%d) %s=%s%s%s\n",i,result,ag1,op,ag2);
    i++;
    return;
}

char *newtemp(void)
{
    char *p;
    char m[8];
    p=(char *)malloc(8);
    k++;
    itoa(k,m,10);
    strcpy(p+1,m);
    p[0]='t';
    return(p);
}

int lrparser()
{   int yucu();
    int schain=0;
    kk=0;
    if(syn!=1)
	{
	printf("缺main错误!!\n");
    flag++;
	}
    scaner();
    if(syn!=48)
	{
    printf("main后缺(括号!!\n");
    flag++;
	}
    else scaner();
    if(syn!=49)
	{
    printf("main后缺)括号!!\n");
    flag++;
	}
    else scaner();
    if(syn!=53)
	{
	printf("main后缺{括号!!\n");
    flag++;
	}
    else scaner();
      schain=yucu();
      if(syn==54)
      { scaner();
        if(syn==0&&kk==0&&flag==0)/*kk是用来记录其他错误的标识*/
        printf("语法与语义分析结束。分析结果为:success\n");
		else
			printf("程序存在着%d个错误\n",flag);
      }
      else
      {if(kk!=1)
       printf("缺}错误!!");
       kk=1;
      }
   return(schain);
}

int yucu()
{
  int statement();
  int schain=0;
  schain=statement();
  while(syn==47)
  { scaner();
    schain=statement();
      }
  return(schain);
}

int statement()
{
    char *expression();
    char tt[8],eplace[8];
    int schain=0;
    switch(syn)
    { case 33:

             strcpy(tt,token);
             scaner();
             if(syn==46)
               { scaner();
                 strcpy(eplace,expression());
                 emit(tt,eplace," "," ");
                 schain=0;
               }
             else{printf("赋值号=错误!!");kk=1;}
      return(schain);
      break;
    }
}

char *expression(void)
{ char *term();
  char *tp,*ep2,*eplace,*tt;
  tp=(char *)malloc(12);
  ep2=(char *)malloc(12);
  eplace=(char *)malloc(12);
  tt=(char *)malloc(12);
  strcpy(eplace,term());
  while(syn==35||(syn==36))
  {   strcpy(tt,token);
      scaner();
      strcpy(ep2,term());
      strcpy(tp,newtemp());
      emit(tp,eplace,tt,ep2);
      strcpy(eplace,tp);
      }
  return(eplace);
}

char *term(void)
{
  char *factor();
  char *tp,*ep2,*eplace,*tt;
  tp=(char *)malloc(12);
  ep2=(char *)malloc(12);
  eplace=(char *)malloc(12);
  tt=(char *)malloc(12);
  strcpy(eplace,factor());
  while(syn==37||(syn==38))
  {   strcpy(tt,token);
      scaner();
      strcpy(ep2,factor());
      strcpy(tp,newtemp());
      emit(tp,eplace,tt,ep2);
      strcpy(eplace,tp);
      }
  return(eplace);
}

char *factor(void)
{
    char *fplace;
    fplace=(char *)malloc(12);
    strcpy(fplace," ");

    if(syn==33)
    {
       strcpy(fplace,token);
       scaner();
    }
    else if(syn==34)
    {
       itoa(sum,fplace,10);
       scaner();
    }
    else if(syn==48)
     {
         scaner();
        fplace=expression();
        if(syn==49)
        scaner();
        else{printf("缺‘)’错误!!\n");kk=1;flag++;}
     }

     else{printf("表达式错误!!\n");kk=1;flag++;}
     return(fplace);
}















评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值