论坛交流
首页办公自动化| 网页制作| 平面设计| 动画制作| 数据库开发| 程序设计| 全部视频教程
应用视频: Windows | Word2007 | Excel2007 | PowerPoint2007 | Dreamweaver 8 | Fireworks 8 | Flash 8 | Photoshop cs | CorelDraw 12
编程视频: C语言视频教程 | HTML | Div+Css布局 | Javascript | Access数据库 | Asp | Sql Server数据库Asp.net  | Flash AS
当前位置 > 文字教程 > C语言程序设计教程
Tag:新手,函数,指针,数据类型,对象,Turbo,入门,运算符,数组,结构,二级,,tc,游戏,试题,问答,编译,视频教程

PL/0语法分析器(递归子程序法)

文章类别:C语言程序设计 | 发表日期:2008-9-24 14:42:49

//程序名: yufashini.cpp
//作者:小万(wbaobao)
//邮箱:wbaobao#zj.com
//QQ:421404493
//创建日期:2004.10
//程序功能:PL/0语言语法分析程序,检测pl/0源程序的语法是否正确
//程序不足之处:语言中对分程序的定义中没有包含常量的定义说明。错误处理能力不是很强。
/*各个符号和产生式说明
对应的函数        产生式             产生式的开始符号集合
void S();程序     S-->F.              p,m,e,k,q,g,n,r,f,.,;,
void F();分程序    F-->B(Y|GY)|G(Y|BY)|Y       p,m,e,k,q,g,n,r,f,.,;,
void B();变量说明部分 pe(,e)*;                 p
void G();过程说明部分 CF;|CF;G                m
void Y();语句     Y-->eaA|kToY|qToY|ge|n(e(,e)*)|r(e(,e)*)|fY(;Y)*j|<空> e,k,q,g,n,r,f,.,;,
void C();过程首部   C-->me;                               m
void A();表达式    A-->(+|-|<空>)N|A(+|-)N                     +,-,e,d,(
void N();项      N-->I|N(*|/)I                              e,d,(
void I();因子     I-->e|d|(A)                                 e,d,(
void X();关系运算符  X-->#|<|>|b                                #,<,>,b
void T();//条件    T-->AXA|lA                                +,-,e,d,(,l
其中终结符的含义均为二元式中的类别码所代表的单词
(+,+);(-,-);(*,*);(/,/);((,();(),));(,,,);(;,;);(.,.);(#,#);(=,=);(>,>);(<,<);(:=,a);(>=,b);
(<=,c);(数字,d);(标识符,e);(begin,f);(call,g);(const,h);(do,i);(end,j);(if,k);(odd,l);
(procedure,m);(read,n);(then,o);(var,p);(while,q);(write,r);
*/
/*测试数据:
(PROCEDURE,m)(P,e)(;,;)
(VAR,p)(D,e)(;,;)
(PROCEDURE,m)(Q,e)(;,;)
(VAR,p)(X,e)(;,;)
(BEGIN,f)
(READ,n)((,()(X,e)(),))(;,;)
(D,e)(:=,a)(X,e)(;,;)
(WHILE,q)(X,e)(<,<)(0,d)
(DO,i)(CALL,g)(P,e)(;,;)
(END,j)(;,;)
(BEGIN,f)
(WRITE,r)((,()(D,e)(),))(;,;)
(CALL,g)(Q,e)(;,;)
(END,j)(;,;)
(BEGIN,f)
(CALL,g)(P,e)(;,;)
(END,j)(.,.)
//请将以上数据存为b.c(上面为词法分析的结果)
*/

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

char token;
char tempword[25];
FILE *op;
int row;

void error(int wnum);
char word();
void S();//程序
void F();//分程序
void B();//变量说明部分
void G();//过程说明部分
void Y();//语句
void C();//过程首部
void A();//表达式
void N();//项
void I();//因子
void X();//关系运算符
void T();//条件


struct infoword
{
    char word[25];
    char type;
    int row;
 int error;
 infoword *next;
 infoword *pre;
};
infoword *head,*cur;
infoword *point;
 

void filltable(char *str,char t)
{
 //infoword newnode;
 int i=0;
 infoword *newnode=new infoword;
 strcpy(newnode->word,str);
 newnode->type=t; //putchar('q');
 newnode->row=row;
 newnode->error=i;
 newnode->pre=NULL;
 newnode->next=NULL;
 if(head==NULL)
 {
  point=head=newnode;//初始化point和head指针
  cur=newnode;//初始化cur指针
 }
 else
 {
  newnode->pre=cur;
  cur->next=newnode;
  cur=newnode;
 }

}
char find(char *str)
{
    infoword *tempp;//puts(str);
 tempp=head;
 while(tempp&&strcmp((tempp->word),str))tempp=tempp->next;
 if(tempp==NULL)return NULL;
 else return tempp->type;
}
int compare(char *str,char t)
{
 char a;
 a=find(str);
 if(a)
  if(a==t)
   return 1;//类型为要求类型
  error(44);//找到但不是要求类型
  error(42);//未找到
  return 0;
}
 


char word()//return a char
{
 //FILE *op;
 //op=fopen("b.c","r");

 char tempc;
 char tempx;
 char tempw[25];
 int i=0,j=0;
 while(!feof(op))
 {
      tempc=fgetc(op);
   strcpy(tempword,"");
   if(tempc==10)
   {
    row++;
    //printf("%d\n",row);
   }
   
  
   if(tempc==',')
   {
    tempx=fgetc(op);
             tempc=fgetc(op);
    if(tempc==')')
    {
     //putchar(tempx);
     if(tempx=='e')
     {
     
      fseek(op,-4l,1);//putchar(fgetc(op));fseek(op,-1l,1);//去掉逗号
      do
      {    
       tempw[i]=fgetc(op);//逆向输入
       i++;
       fseek(op,-2l,1);//putchar(fgetc(op));fseek(op,-1l,1);     
      }while(fgetc(op)!='(');//判定这个单词结束的标志
      
      for(j=0;i>0;i--)
      {
       tempword[j]=tempw[i-1];//再次顺序输入到tempword
       j++;
       fseek(op,1l,1);
      }
      tempword[j]='\0';
      //puts(tempword);
      fseek(op,3l,1);//putchar(fgetc(op));fseek(op,-1l,1);
     }
     return tempx;

     //putchar(tempc);
           //putchar('\n');
    }
    fseek(op,-2l,1);

   }
 

 }
 return NULL;
 
}

 

void error(int wnum)
{
 if(wnum==4)printf("错误(%d):var,procedure后应为标志符\n",row);
 else if(wnum==5)printf("错误(%d):漏掉了','或';'\n",row);
 else if(wnum==6)printf("错误(%d):过程说明后的符号不正确(应是语句的开始符,或过程的定义符)\n",row);
 else if(wnum==7)printf("错误(%d):应是语句开始符\n",row);
 else if(wnum==8)printf("错误(%d):程序体内语句部分的后跟符不正确\n",row);
 else if(wnum==9)printf("错误(%d):程序结尾丢了句号'.'\n",row);
 else if(wnum==10)printf("错误(%d):语句之间丢了分号';'\n",row);
 else if(wnum==11)printf("错误(%d):标志符未说明\n",row);
 else if(wnum==12)printf("错误(%d):赋值语句中,赋值号左部标志符属性应是变量\n",row);
 else if(wnum==13)printf("错误(%d):赋值号左部标志符后应是赋值号':='\n",row);
 else if(wnum==14)printf("错误(%d):call应为标志符\n",row);
 else if(wnum==15)printf("错误(%d):call后标志符属性应为过程\n",row);
 else if(wnum==16)printf("错误(%d):条件语句中丢了'then'\n",row);
 else if(wnum==17)printf("错误(%d):丢了'end'或';'\n",row);
 else if(wnum==18)printf("'错误(%d):while'型循环语句中丢了'do'\n",row);
 else if(wnum==19)printf("错误(%d):语句后的符号不正确\n",row);
 else if(wnum==20)printf("错误(%d):应为关系运算符\n",row);
 else if(wnum==21)printf("错误(%d):表达式内标志符属性不能是过程\n",row);
 else if(wnum==22)printf("错误(%d):表达式中漏掉右括号')'\n",row);
 else if(wnum==23)printf("错误(%d):因子后的非法符号\n",row);
 else if(wnum==24)printf("错误(%d):表达式的开始符号不能是此符 号\n",row);
 else if(wnum==31)printf("错误(%d):数越界\n",row);
 else if(wnum==32)printf("错误(%d):read语句括号中的标志符不是变量\n",row);

 else if(wnum==1)printf("错误(%d):wwww\n",row);
 else if(wnum==2)printf("错误(%d):\n",row);
 else if(wnum==33)printf("错误(%d):应该为赋值号\n",row);
 else if(wnum==34)printf("错误(%d):读语句缺少左括号\n",row);
 else if(wnum==35)printf("错误(%d):程序的开始符号出错\n",row);
 else if(wnum==36)printf("错误(%d):read语句括号中缺少标志符\n",row);
 else if(wnum==37)printf("错误(%d):read语句漏掉左括号'('\n",row);
 else if(wnum==38)printf("错误(%d):write语句括号中缺少表达式\n",row);
 else if(wnum==39)printf("错误(%d):write语句漏掉左括号'('\n",row);
 else if(wnum==40)printf("错误(%d):关系运算符出错\n",row);
 else if(wnum==41)printf("错误(%d):条件开始子集错误\n",row);
 else if(wnum==42)printf("错误(%d):标志符未定义\n",row);
 else if(wnum==43)printf("错误(%d):标志符已定义\n",row);
 else if(wnum==44)printf("错误(%d):标志符属性不复合要求\n",row);
 else if(wnum==45)printf("错误(%d):分程序后应跟分号\n",row);
 else if(wnum==36)printf("错误(%d):程序意外结束,无法继续编译\n",row);


}
/*约定每一个产生式结束时都得取出下一个字符*/
void S()//程序
{
 //输入符号为结束标志,输出提示信息,退出程序
 if(token=='.')
 {
  printf("analyse over!\n\n");
  exit(0);
 }

 //当输入符号不属于开始符号集时,转到错误处理//下面句判定条件有错误
 if(token!='p'&&token!='m'&&token!='e'&&token!='k'&&token!='q'&&token!='g'&&token!='n'&&token!='r'&&token!='f'&&token!='.'&&token!=';'&&token!='j')
 {
  error(35);int stemprow=0;
  stemprow=row;
  token=word();/*程序的开始符号出错,处理方式:判定后跟符是否为S的开始符,直到取得一个可以是语句或变量说明部分或过程说明部分的开始符*/
  while(stemprow==row)
  {
   token=word();
  }
  //token=word();putchar(token);
  S();
 }
   else
 {  
  F();
  if(token=='.')
  {
   printf("analyse over!\n");
  }
  else
  {
   error(9);//putchar('m');//缺少程序的结束符
   //fputchar(token);
  }
 }
}
void F()//分程序
{
 int ftemprow=0;
 ftemprow=row;
     if(token=='m')
  {
   G();
   //token=word();
   if(token=='p')
   {
    B();//putchar('y');
    Y();
   }
   else
   {
    Y();
   }
  }
 else if(token=='p')
  {
   B();
   //token=word();
   if(token=='m')
   {
    G();
    Y();
   }
   else
   {//putchar('y');
    Y();
   }
  }
 else if(token=='e'||token=='k'||token=='q'||token=='g'||token=='n'||token=='r'||token=='f'||token!='.'||token!=';'||token!='j')

 {
  Y();
 }
 else
 {
  error(1);//putchar('y');
  while(ftemprow==row)
   token=word();
  F();
 }
}
void B()//变量说明部分
{
 int temprow=0;
 temprow=row;
 if(token!='p') //当输入符号不等于p时,转到错误处理
 {  //putchar(token);
  error(1);//变量说明部分的要害字应该是‘var’
  while(temprow==row)
   token=word();
 }
 else
 {
  token=word();
 
     if(token!='e')//判定是否在同行
  {
      error(4);
     while(temprow==row)
       token=word();
  }
     else
  {
   if(find(tempword))
   {
    error(43);//标志符已定义
    //putchar('b');
   }
   else
   {
    filltable(tempword,'p');//putchar('t');
   }
       token=word();
  
         if(token!=';'&&token!=',')
   {
          error(5);//putchar('x');//变量结束符应该是分号//检查该行是否结束是则缺少分号不是则缺少逗号
           while(temprow==row)//行未结束则继续取词
          token=word();
   }
        else
     {
             while(token==',')//当
    {
              token=word(); //putchar('x');
              if(token!='e')
     {
               error(4);//判定该行是否结束是则报错结束符应该是分号,不是报错应该为标志符
         while(temprow==row)
      token=word();
     }
               else
      {  
       if(find(tempword))
       {
                  error(43);//标志符已定义
                   //putchar('b');
       }
                 else
        {
                    filltable(tempword,'p');//putchar('t');
        }
                 token=word();//继续取数
      }
    }
          if(token!=';'&&temprow==row)//还要判定是否同行
    {
          error(17);//结束符不正确
    }
          else
    {
               token=word();
    }
     }
  }
 }
}
void G()//过程说明部分
{
 //putchar('y');
 int gtemprow=0;
 gtemprow=row;
 if(token!='m')
 {
  //putchar('y');
  error(1);//putchar('y');//过程说明符应该为procedure
  while(gtemprow==row)
   token=word();
 }
 else
 {
  //putchar('y');
  //token=word();
  C(); //putchar('x');
  F(); //putchar('x');
  if(token!=';')
  {
   error(45);//putchar('x');//the end shoud be ';' 只报错不作处理
  }
   token=word();//继续取单词
     if(token=='m')//是'm'就说明是另一个过程的开始
     {
      //token=word();
      G();
     }
 }
}
void Y()//语句
{
 int ytemprow=0;
if(token=='e'||token=='k'||token=='q'||token=='g'||token=='n'||token=='r'||token=='f'||token!='.'||token!=';'||token!='j')
{  
 if(token=='e')//赋值语句
 { 
  compare(tempword,'p');
  ytemprow=0;
  ytemprow=row;
        token=word();//putchar('x');
  if(token!='a')
  {
            error(33);//putchar('y');//应该为赋值号
   while(ytemprow==row)
    token=word();
   ytemprow=0;//putchar(token);
  }
  else
  {
   token=word();//putchar('w');putchar(token);//continue to get the next alpha
   A();//putchar('z');//Call A
   //putchar('x');putchar(token);//token=word();
  }
 }
 if(token=='k')//条件语句
 {
  token=word();
  T();
  if(token!='o')
  {
   error(16);//条件语句缺少"then"报错不作处理
  }
       if(token=='e'||token=='k'||token=='q'||token=='g'||token=='n'||token=='r'||token=='f'||token!='.'||token!=';'||token!='j')
   Y();//这样处理是因为可能刚刚已经取到了语句的开始符号
    else
    {
     token=word();
     Y();
    }
 }
 if(token=='q')//当型循环
 {
  token=word();//putchar('y');
        T();//putchar('y');
  if(token!='i')
  {
   error(18);//putchar('y');//当型循环语句缺少"do"报错不作处理
   //putchar(token);
  
           if(token=='e'||token=='k'||token=='q'||token=='g'||token=='n'||token=='r'||token=='f'||token!='.'||token!=';'||token!='j')
     {
      //putchar(token);
      Y();//这样处理是因为可能刚刚已经取到了语句的开始符号
     }
     else
     {
      //putchar(token);
      token=word();//putchar('y');
      Y();//putchar('y');
     }
  }
    else
    {
     token=word ();
     Y();
    }
 }
 if(token=='g')//过程调用语句
 {
  ytemprow=0;
  ytemprow=row;
  token=word();
  if(token!='e')
  {
   error(14);//过程调用语句后面应该是标志符
   while(ytemprow==row)
    token=word();//除去同一行的多余字符
   Y();//token=word();
  }
  else
  {
   compare(tempword,'m');
   token=word();//putchar(token);putchar('y'); //在此还需要判定标志符是否具有过程属性,查表
  }

 }
 if(token=='n')//读语句
 {
  ytemprow=0;
  ytemprow=row;
  token=word(); //putchar('x');
  if(token!='(')
  {
   error(34);//读语句缺少左括号,判定是否是标志符
   while(ytemprow==row)
    token=word();
   //token=word();
   ytemprow=0;//putchar(token);
   Y();//调用语句处理函数是因为这是读语句出错也就是在语句处理中,它的前面的函数S,F,B,G均不会出现在读语句之后
  }
        else
  {
   token=word();
   if(token!='e')
   {
    error(36);//read语句括号中缺少标志符,//
   while(ytemprow==row)
    token=word();
   Y();
   ytemprow=0;//在此检查后跟符是否为括号,
   
   }
   else
   { //read语句括号中的标志符不是变量
    compare(tempword,'p');//检查属性
    token=word();
   
       if(token!=')')//判定是否是同行
    {
        while(token!=')'&&ytemprow==row)//检查行是否结束
     {
              //contr++;//用作控制循环,改成判定是否是同行
            if(token!=',')
      {
             error(5);//变量之间应该用逗号分隔
              while(ytemprow==row)
                  token=word();
                 Y();
                 ytemprow=0;//putchar('x');
      }
            else
      {
         token=word();
         if(token!='e')
      {
          error(36); //判定同行是否是结束,是就报错结束符是右括号
          while(ytemprow==row)
                    token=word();
                   Y();
                   ytemprow=0;//putchar('x');
      }
         else
      {
       compare(tempword,'p');
          token=word();
      }
             
                             //if(contr>20)//缺少右括号//改成判定是否是同行
                             //{
                             // error(1);
                             // break;
      }                 //}
     }//while
                    if(token!=')')
     {
      error(22);
                        token=word();
     }
     else
     {
      token=word();
     }
   }
   else
   token=word();
  }//else
  }
 }
 if(token=='r')//写语句//处理方式与读语句一致
 {
  ytemprow=0;
  ytemprow=row;
  token=word();
  if(token!='(')
  {
   error(39);   
   while(ytemprow==row)
    token=word();
   //token=word();
   ytemprow=0;
   Y();
  }
  else
  {
   token=word();//int contr=0;
   if(token!='e'&&token!='d'&&token!='(')
   {
    error(38);
    while(ytemprow==row)
        token=word();
        //token=word();
        ytemprow=0;Y();
   }
   else
   {
    //compare(tempword,'p');
    A();
    //token=word();
    if(token!=')')
    {
     while(token!=')'&&ytemprow==row)
     {
             if(token!=',')
      {
              error(5);   
              while(ytemprow==row)
                      token=word();
                   
                    ytemprow=0;Y();
      }
            else
      {
               token=word();
               if(token!='e'&&token!='d'&&token!='(')
         {
                error(38);   
                  while(ytemprow==row)
                             token=word();
                           //putchar(token);
                           ytemprow=0;Y();
         }
              else
        {
         //compare(tempword,'p');
         A();
                  //token=word();
        }
      }
     }  //while 
     if(token!=')')
     {
      error(22);//缺少右括号
      token=word();
     }
     else
     {
      token=word();
     }
    }
    else
    {
     token=word();//结束后再取下一个字符
    }
   }
   
  }

 }
 if(token=='f')//复合语句
 {
  token=word();//putchar('y');
  Y();
     if(token!='j'&&token!=';')//判定是正确还是错误
   {
              error(17);//putchar('x');
   }
      else
   {
       while(token!='j')
    {
        if(token!=';')
     {
      //putchar('x');
         error(10);//putchar('y');putchar(token);putchar('x');//缺少分号
               if(token=='e'||token=='k'||token=='q'||token=='g'||token=='n'||token=='r'||token=='f'||token!='.'||token!=';'||token!='j')
            Y();
            else
      {
            token=word();
                 if(token=='e'||token=='k'||token=='q'||token=='g'||token=='n'||token=='r'||token=='f'||token!='.'||token!=';'||token!='j')
             Y();
                      
      }
     }
    token=word();
    Y();
   }//while
   if(token!='j')
   {
    error(17);//putchar('x');//缺少end
   }
   else
   {
    token=word();
   }
  }

 }
 if(token=='.')
 {
  if(word()!=NULL)
  {
   error(46);//程序意外结束,无法继续编译
   exit(0);
  }
 }
}
}
void C()//过程首部
{
 int gtemprow=0;
 gtemprow=row;
 if(token!='m')
 {
  error(1);//过程说明符应该为procedure
  while(gtemprow==row)
   token=word();
  F();
 }
 else
 {
  token=word();//putchar('y');
  if(token!='e')
  {
   error(4);//应该接标志符
   while(gtemprow==row)
        token=word();
   F();
  }
  else
  {
     if(find(tempword))
   {
    error(43);//标志符已定义
    //putchar('x');
   }
   else
   {
    filltable(tempword,'m');//putchar('c');
   }
   token=word();
   if(token!=';')
   {
    error(17);//结束符应该为分号
   }
   else
   {
   token=word();
   }
  }
 }

}
void A()//表达式
{
 int atemprow=0;
 atemprow=row;
 if(token=='+'||token=='-')
 {
  token=word();//假如开始字符是‘+’或‘-’则取下一个字符
 }
//putchar(token);
 N();//putchar(token);
 while(atemprow==row&&(token=='+'||token=='-'))//并且是同行
 {
  token=word();
  N();
 }
}
void N()//项
{
 int ntemprow=0;
 ntemprow=row;
 if(token!='e'&&token!='d'&&token!='(')
 {
  error(7);
  while(ntemprow==row&&token!='+'&&token!='-'&&token!=','&&token!='i'&&token!='o')
   token=word();//将整个项去掉
 }
 else
 {
  I();
  while(token=='*'||token=='/')
  {
   token=word();
   I();
  }

 }
}
void I()//因子
{
 int itemprow=0;
 itemprow=row;
 
 if(token!='e'&&token!='d'&&token!='(')
 {
  error(7);//开始符出错
  while(itemprow==row&&token!='+'&&token!='-'&&token!=','&&token!='i'&&token!='o'&&token!='*'&&token!='/')
  token=word();

 }
 else
 {
  if(token=='e')
  {
   compare(tempword,'p');
   token=word();
  }
  if(token=='d')
   token=word();
  if(token=='(')
  {
         token=word();
   A();
   if(token!=')')
   {
    error(22);//缺少右括号
   }
   else
   {
    token=word();
   }
  }
  
 }
}
void X()//关系运算符
{
 if(token!='#'&&token!='<'&&token!='>'&&token!='b'&&token!='c')
 {
  error(40);//关系运算符出错
  if(token!='+'&&token!='-'&&token!='e'&&token!='d'&&token!='(')//防止已经取得了下一个标志符的开始符
  token=word();
 }
 else
 {
  token=word();
 }
}
void T()//条件
{
 int ttemprow=0;
 ttemprow=row;
 if(token!='+'&&token!='-'&&token!='e'&&token!='d'&&token!='('&&token!='l')
 {
  error(41);//条件开始子集错误
  while(token!='i'&&token!='o')
  {
   token=word();
   if(ttemprow!=row)
    break;
  }
 }
 else
 {
  if(token=='l')
  {
   A();
  }
  else
  {//putchar('y');putchar(token);
   A();//putchar('y');
   X();//putchar('y');putchar(token);
   A();
  }
 }
}


 void main()
{
 op=fopen("b.c","r");
 token=word();
 S();
 fclose(op);
 getchar();
 exit(0);
 
}


/*程序中有许多不足之处,请各位指教*/
/*程序在VC6.0下编译通过*/

上一篇:{实例}不用图形库函数的仿windows画图程序 人气:6241
下一篇:{实例}JOSEPH环 人气:5493
视频教程列表
文章教程搜索
 
C语言程序设计推荐教程
C语言程序设计热门教程
看全部视频教程
购买方式/价格
购买视频教程: 咨询客服
tel:15972130058