语法分析课程设计

实验四.语法分析课程设计

一.语法分析的功能语法分析是编译过程的核心部分,它的主要任务是按照和程序语言的语法规则,从由词法分析输出的源程序符号串中识别出各类语法分析成分,同时进行语法检查,为语义分析和代码生成作准备。

二.语法分析的目的语法分析程序以词法分析输出的符号串作为输入,在分析过程中检查这个符号串是否为该程序语言的句子。

三.语法分析的规则参照了课本上P69 TEST规则(1--17)。

(1)<program>::={<declaration_list><statement_list>}

(2)<declaration_list>::=<declaration_list><delaration_stat>|e

(3)<declaration_stat>::=int ID;

(4)<statement_list>::=<statement_list><statement>|e

(5)<statement>::=<if_stat>|<while_stat>|<for_stat>|<read_stat>|<write_stat>|<do_stat>|<compound_stat>|<expression_stat>

(6)<if_stat>::=if(<expression>)<statement>[else<statement>]

(7)<while_stat>::=while(<expression>)<statement>

(8)<for_stat>::=for(<expression>,<expression>,<expression>)<statement>

(9)<write_stat>::=write<expression>

(10)<read_stat>::=read ID

(11)<do_stat>::=do<statement>while<expression>

(12)<compound_stat>::={<statement_list>}

(13)<expression_stat>::=<expression>;|;

(14)<expression>::=ID=<bool_expr>|<bool_expr>|<log_expr>|<log_expr>

(15)<bool_expr>::=<additive_expr>|<additive_expr>(>|<|>=|<=|==
!=)<additive_expr>

(16)<additive_expr>::=<term>{(+|-)|<term>}

(17) <term>::=<factor>{(*|/)<factor>}

(18)<factor>::=(<expression>)|ID|NUM

(19)<log_expr>::=<log_expr>(&&|||)<bool_expr>|!<log_expr>|<bool_expr>

该语法分析是自顶向下的语法分析。

四.实验过程编译好语法分析程序后,将00.t文件保存到电脑D盘中,然后运行分析如下图:

 

 

00.T文件:

do{

if((month==4)||(month==6))

return (30);

else if((month==2)&&(month==1)&&(month!=9))

return (0);

}while(i>=0)

 

01.T文件:

do  do

{   {

if  if

(   (

(   (

ID  month

==  ==

NUM 4

)   )

|   |

|   |

(   (

ID  month

==  ==

NUM 6

)   )

)   )

ID  return

(   (

NUM 30

)   )

;   ;

else   else

if  if

(   (

(   (

ID  month

==  ==

NUM 2

)   )

&   &

&   &

(   (

ID  month

==  ==

NUM 1

)   )

&   &

&   &

(   (

ID  month

!=  !=

NUM 9

)   )

)   )

ID  return

(   (

NUM 0

)   )

;   ;

}   }

while  while

(   (

ID  i

>=  >=

NUM 0

)   )

 

02.T文件:

do  do

{   {

if  if

(   (

(   (

ID  month

==  ==

NUM 4

)   )

|   |

|   |

(   (

ID  month

==  ==

NUM 6

)   )

)   )

ID  return

(   (

NUM 30

)   )

;   ;

else   else

if  if

(   (

(   (

ID  month

==  ==

NUM 2

)   )

&   &

&   &

(   (

ID  month

==  ==

NUM 1

)   )

&   &

&   &

(   (

ID  month

!=  !=

NUM 9

)   )

)   )

ID  return

(   (

NUM 0

)   )

;   ;

}   }

while  while

(   (

ID  i

>=  >=

NUM 0

)   )

五.语法分析程序的源代码:

//TESTscan.c

#include <stdio.h>

#include <ctype.h>

#include <string.h>

//下面定义保留,为简化程序,使用字符指针数组保存所有保留字。

//如果想增加保留字,可继续添加,并修改保留字数目

#define keywordSum  9

char *keyword[keywordSum]={"if","else","for","while","do","int","read","write","real"};

//下面定义纯单分界符,如需要可添加

char singleword[50]="+-*(){};,:&";

//下面定义双分界符的首字符

char doubleword[10]="><=!||";

extern char Scanin[300], Scanout[300]; //用于接收输入输出文件名,TEST_main.c中定义

extern FILE *fin,*fout; //用于指向输入输出文件的指针,TEST_main.c中定义

int TESTscan()//词法分析函数

{

   char ch,token[40]; //ch为每次读入的字符,token用于保存识别出的单词

   int es=0,j,n; //es错误代码,0表示没有错误。j,n为临时变量,控制组合单词时的下标等

   printf("请输入源程序文件名(包括路径):");

   scanf("%s",Scanin);

   printf("请输入词法分析输出文件名(包括路径):");

   scanf("%s",Scanout);

   if((fin=fopen(Scanin,"r"))==NULL) //判断输入文件名是否正确

   {

      printf("/n打开词法分析输入文件出错!/n");

      return(1);//输入文件出错返回错误代码1

   }

   if((fout=fopen(Scanout,"w"))==NULL) //判断输出文件名是否正确

   {

      printf("/n创建词法分析输出文件出错!/n");

      return(2); //输出文件出错返回错误代码2

   }

   ch=getc(fin);

   while(ch!=EOF)

   {

      while(ch==' '||ch=='/n'||ch=='/t')

    ch=getc(fin);

      if(isalpha(ch))   //如果是字母,则进行标识符处理

      {

   token[0]=ch;

   j=1;

   ch=getc(fin);

   while(isalnum(ch))  //如果是字母数字则组合标识符;如果不是则标识符组合结束

   {

   token[j++]=ch;  //组合的标识符保存在token

   ch=getc(fin);  //读下一个字符

   }

   token[j]='/0';  //标识符组合结束

   //查保留字

   n=0;

   while((n<keywordSum) && strcmp(token,keyword[n]))

    n++;

   if(n>=keywordSum)  //不是保留字,输出标识符

   fprintf(fout,"%s/t%s/n","ID",token);  //输出标识符符号

  else//是保留字,输出保留字

   fprintf(fout,"%s/t%s/n",token,token);  //输出保留字符号

   }

   else if(isdigit(ch))//数字处理

   {

   token[0]=ch;

   j=1;

   ch=getc(fin);  //读下一个字符

   while(isdigit(ch))  //如果是数字则组合整数;如果不是则整数组合结束

   {

   token[j++]=ch;  //组合整数保存在token

   ch=getc(fin);  //读下一个字符

   }

   token[j]='/0';  //整数组合结束 

   fprintf(fout,"%s/t%s/n","NUM",token);  //输出整数符号

      }

   else if(strchr(singleword,ch)>0)  //单分符处理

      {

   token[0]=ch;

   token[1]='/0';

   ch=getc(fin);//读下一个符号以便识别下一个单词

   fprintf(fout,"%s/t%s/n",token,token);  //输出单分界符符号

      }

   else if(strchr(doubleword,ch)>0)  //双分界符处理

      {

   token[0]=ch;

   ch=getc(fin);  //读下一个字符判断是否为双分界符

   if(ch=='=')  //如果是=,组合双分界符

   {

   token[1]=ch;token[2]='/0';  //组合双分界符结束

      ch=getc(fin);  //读下一个符号以便识别下一个单词

   }

   else//不是=则为单分界符

   token[1]='/0';

   fprintf(fout,"%s/t%s/n",token,token);  //输出单或双分界符符号

      }

   else if(ch=='/')  //注释处理

      {

   ch=getc(fin);  //读下一个字符

   if(ch=='*')  //如果是*,则开始处理注释

   {  char ch1;

   ch1=getc(fin);  //读下一个字符

   do

   {ch=ch1;ch1=getc(fin);}  //删除注释

   while((ch!='*' || ch1!='/')&&ch1!=EOF);  //直到遇到注释结束符*/或文件尾

   ch=getc(fin);//读下一个符号以便识别下一个单词

   }

   else  //不是*则处理单分界符/

   {

    token[0]='/'; token[1]='/0';

    fprintf(fout,"%s/t%s/n",token,token);  //输出单分界符/

   }

   }

   else//错误处理

   {

   token[0]=ch;token[1]='/0';

   ch=getc(fin);  //读下一个符号以便识别下一个单词

   es=3;  //设置错误代码

   fprintf(fout,"%s/t%s/n","ERROR",token);  //输出错误符号

      }

   }

   fclose(fin);//关闭输入输出文件

   fclose(fout);

   return(es);  //返回主程序

}

 

//TESTparse.c

#include<stdio.h>

#include<ctype.h>

#include<conio.h>

#include<string.h>

int TESTparse();

int program();

int compound_stat();

int statement();

int expression_stat();

int expression();

int bool_expr();

int additive_expr();

int term();

int factor();

int if_stat();

int while_stat();

int for_stat();

int write_stat();

int read_stat();

int declaration_stat();

int declaration_list();

int statement_list();

int compound_stat();

char token[20],token1[40];

extern char Scanout[300];

FILE *fp;

int TESTparse()

{

    int es=0;

    if((fp=fopen(Scanout,"r"))==NULL)

    {

       printf("/n打开%s错误!/n",Scanout);

       es=10;

    }

    if(es==0) es=program();

    printf("=====语法分析结果!======/n");

    switch(es)

    {

    case 0:printf("语法分析成功!/n");break;

    case 10:printf("打开文件%S失败!/n",Scanout);break;

    case 1:printf("缺少{!/n");break;

    case 2:printf("缺少}!/n");break;

    case 3:printf("缺少标识符!/n");break;

    case 4:printf("少分号!/n");break;

    case 5:printf("缺少(!/n");break;

    case 6:printf("缺少)!/n");break;

    case 7:printf("缺少操作数!/n");break;

    }

    fclose(fp);

    return(es);

}

int program()

{

    int es=0;

    fscanf(fp,"%s%s/n",token,token1);

    printf("%s%s/n",token,token1);

    if(strcmp(token,"{"))

    {es=1;

    return(es);

    }

    fscanf(fp,"%s%s/n",&token,&token1);

    printf("%s%s/n",token,token1);

    es=declaration_list();

    if(es>0)return(es);

    es=statement_list();

    if(es>0)return(es);

    if(strcmp(token,"}"))

    {

       es=2;

       return(es);

    }

    return(es);

}

 int declaration_list()

 {

     int es=0;

     while(strcmp(token,"int")==0)

     {

            es=declaration_stat();

            if(es>0)return(es);

        }

        return(es);

     }

 int declaration_stat()

     {

        int es=0;

        fscanf(fp,"%s%s/n",&token,&token1);

        printf("%s%s/n",token,token1);

        if(strcmp(token,"ID"))return(es=3);

        fscanf(fp,"%s%s/n",&token,&token1);

        printf("%s%s/n",token,token1);

        if(strcmp(token,";"))return(es=4);

        fscanf(fp,"%s%s/n",&token,&token1);

        printf("%s%s/n",token,token1);

        return(es);

     }

     int statement_list()

     {

        int es=0;

        while(strcmp(token,"}"))

        {

            es=statement();

            if(es>0)return(es);

        }

        return(es);

     }

     int statement()

     {

     int es=0;

     if(es==0 && strcmp(token,"if")==0) es=if_stat();

     if(es==0 && strcmp(token,"while")==0) es=while_stat();

     if(es==0 && strcmp(token,"for")==0) es=for_stat();

     if(es==0 && strcmp(token,"read")==0) es=read_stat();

     if(es==0 && strcmp(token,"write")==0) es=write_stat();

     if(es==0 && strcmp(token,"{")==0) es=compound_stat();

     if(es==0 && strcmp(token,"ID")==0 || strcmp(token,"NUM")==0 || strcmp(token,"(")==0) es=expression_stat();

     return(es);

     }

     int if_stat(){

        int es=0;

        fscanf(fp,"%s%s/n",&token,&token1);

        printf("%s%s/n",token,token1);

            if(strcmp(token,"("))return(es=5);

            fscanf(fp,"%s%s/n",&token,&token1);

            printf("%s%s/n",token,token1);

               es=expression();

            if(es>0)return(es);

            if(strcmp(token,")"))return(es=6);

            fscanf(fp,"%s%s/n",&token,token1);

            printf("%s%s/n",token,token1);

               es=statement();

            if(es>0)return(es);

            if(strcmp(token,"else")==0)

            {

            fscanf(fp,"%s%s/n",&token,token1);

            printf("%s%s/n",token,token1);

               es=statement();

            if(es>0)return(es);

            }

            return(es);

     }

     int while_stat()

     {

        int es=0;

        fscanf(fp,"%s%s/n",&token,token1);

        printf("%s%s/n",token,token1);

            if(strcmp(token,"("))return(es=5);

        fscanf(fp,"%s%s/n",&token,token1);

        printf("%s%s/n",token,token1);

            es=expression();

        if(es>0)return(es);

        if(strcmp(token,")"))return(es=6);

        fscanf(fp,"%s%s/n",&token,token1);

        printf("%s%s/n",token,token1);

            es=statement();

        return(es);

     }

     int for_stat()

     {

        int es=0;

        fscanf(fp,"%s%s/n",&token,token1);

        printf("%s%s/n",token,token1);

             if(strcmp(token,"("))return(es=5);

        fscanf(fp,"%s%s/n",&token,token1);

        printf("%s%s/n",token,token1);

            es=expression();

        if(es>0)return(es);

        if(strcmp(token,";")) return(es=4);

        fscanf(fp,"%s%s/n",&token,token1);

        printf("%s%s/n",token,token1);

            es=expression();

        if(es>0)return(es);

        if(strcmp(token,";"))return(es=4);

        fscanf(fp,"%s%s/n",&token,token1);

        printf("%s%s/n",token,token1);

            es=expression();

        if(es>0)return(es);

        if(strcmp(token,")"))return(es=6);

        fscanf(fp,"%s%s/n",&token,token1);

        printf("%s%s/n",token,token1);

            es=statement();

        return(es);

     }

     int write_stat()

     {

        int es=0;

        fscanf(fp,"%s%s/n",&token,token1);

        printf("%s%s/n",token,token1);

            es=expression();

        if(es>0)return(es);

        if(strcmp(token,";"))return(es=4);

        fscanf(fp,"%s%s/n",&token,token1);

        printf("%s%s/n",token,token1);

            return(es);

     }

     int read_stat()

     {

        int es=0;

        fscanf(fp,"%s%s/n",&token,token1);

        printf("%s%s/n",token,token1);

            if(strcmp(token,"ID"))return(es=3);

        fscanf(fp,"%s%s/n",&token,token1);

        printf("%s%s/n",token,token1);

            if(strcmp(token,";")) return(es=4);

        fscanf(fp,"%s%s/n",&token,token1);

        printf("%s%s/n",token,token1);

            return(es);

     }

     int compound_stat(){

        int es=0;

        fscanf(fp,"%s%s/n",&token,token1);

        printf("%s%s/n",token,token1);

            es=statement_list();

        return(es);

     }

     int expression_stat()

     {

        int es=0;

        if(strcmp(token,";")==0)

        {

        fscanf(fp,"%s%s/n",&token,token1);

        printf("%s%s/n",token,token1);

            return(es);

        }

        es=expression();

        if(es>0)return(es);

        if(es==0 && strcmp(token,";")==0)

        {

        fscanf(fp,"%s%s/n",&token,token1);

        printf("%s%s/n",token,token1);

            return(es);

        }else

        {

            es=4;

            return(es);

        }

     }

     int expression()

     {

        int es=0,fileadd;

        char token2[20],token3[40];

        if(strcmp(token,"ID")==0)

        {

            fileadd=ftell(fp);

            fscanf(fp,"%s%s/n",&token2,token3);

            printf("%s%s/n",token2,token3);

               if(strcmp(token2,"=")==0)

               {

                   fscanf(fp,"%s%s/n",&token,token1);

                    printf("%s%s/n",token,token1);

                      es=bool_expr();

                   if(es>0)return(es);

               }else

               {

                   fseek(fp,fileadd,0);

                    printf("%s%s/n",token,token1);

                      es=bool_expr();

                   if(es>0)return(es);

               }

        }else es=bool_expr();

        return(es);

     }

     int bool_expr()

     {

        int es=0;

        es=additive_expr();

        if(es>0)return(es);

        if(strcmp(token,">")==0 || strcmp(token,">=")==0 || strcmp(token,"<")==0 || strcmp(token,"<=")==0 || strcmp(token,"==")==0 || strcmp(token,"!=")==0)

        {

            fscanf(fp,"%s%s/n",&token,token1);

            printf("%s%s/n",token,token1);

               es=additive_expr();

            if(es>0)return(es);

        }

        return(es);

     }

 int additive_expr()

 {

     int es=0;

     es=additive_expr();

     if(es>0)return(es);

     while(strcmp(token,"+")==0 || strcmp(token,"-")==0)

     {

        fscanf(fp,"%s%s/n",&token,token1);

        printf("%s%s/n",token,token1);

            es=term();

        if(es>0)return(es);

     }

     return(es);

 }

  int term()

  {

      int es=0;

      es=factor();

      if(es>0)return(es);

      while(strcmp(token,"*")==0 || strcmp(token,"/")==0)

      {

         fscanf(fp,"%s%s/n",&token,token1);

         printf("%s%s/n",token,token1);

             es=factor();

         if(es>0)return(es);

      }

      return(es);

  }

  int factor()

  {

      int es=0;

      if(strcmp(token,"(")==0)

      {

         fscanf(fp,"%s%s/n",&token,token1);

         printf("%s%s/n",token,token1);

             es=expression();

         if(strcmp(token,")"))return(es=6);

         fscanf(fp,"%s%s/n",&token,token1);

         printf("%s%s/n",token,token1);

      }else

      {

         if(strcmp(token,"ID")==0 || strcmp(token,"NUM")==0)

         {

             fscanf(fp,"%s%s/n",&token,token1);

             printf("%s%s/n",token,token1);

             return(es);

         }else

         {

             es=7;

             return(es);

         }

      }

      return(es);

  }

 

//TESTmain.c

#include<stdio.h>

#include<ctype.h>

extern int TESTscan();

extern int TESTparse();

char Scanin[300],Scanout[300];

FILE *fin,*fout;

void main(){

    int es=0;

    es=TESTscan();

    if(es>0) printf("词法分析有错,编译停止!");

    else printf("词法分析成功!/n");

    if(es==0)

    {

       es=TESTscan();

       if(es==0) printf("语法分析成功!/n");

       else printf("语法分析错误!/n");

    }

}

 

六.实验心得

   鉴于上一次实验,在这一次实验中,少走了很多弯路,除了在输入代码时输入错误,其它就没什么问题了.只是觉得对语法分析的认识还是觉得有点模糊,不过这次实验让我更加认识到学习编译原理的重要性,还需继续努力。

 

 

 

 

                 注:为本人拟定,有错误,请勿COPY,仅供参考,谢谢合作

 

 

 
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值