回 帖 发 新 帖 刷新版面

主题:关于语法分析器

我编写了一个程序,但是达不到要求,现请各位大大帮帮忙
文法:G[S]:S->aBc|bAB
            A->aAb|b
            B->b|入
自上而下句型分析,判断baabbb是否该文法的句型
希望大家能帮忙交流交流.

回复列表 (共10个回复)

沙发

看看你的程序?

板凳

//程序:自顶向下语法分析器
//文法G[s]:S->aBc|bAB  
//          A->aAb|b    
//          B->b|λ
       

#include<iostream.h>

#include <string.h>

#include <stdlib.h>

#define stack_size 20
#define stackincrement 10

char Vn[3]={'S','A','B'};
char Vt[4]={'a','b','c','#'};

typedef struct {
    char *bottom;
    char *top;
    int size;
}stack;

int Initstack(stack &s)        //初始化栈
{
   s.bottom=(char *)malloc(stack_size*sizeof(char));
   if(!s.bottom) exit(-1);
   s.top=s.bottom;
   s.size=stack_size;
   return(1);
}

int push(stack &s,char e)      //入栈
{
   if(s.top-s.bottom>=s.size){
      s.bottom=(char *)realloc(s.bottom,(stack_size+stackincrement)*sizeof(char));
      if(!s.bottom) exit(-1);
      s.top=s.bottom+s.size;
      s.size+=stackincrement;
   }
   *s.top++=e;
   return(1);
}

int pop(stack &s,char *e)       //出栈
{
   if(s.top==s.bottom) return(0);
   *e=*--s.top;
   return(1);
}

int is_Vt(char Vt[],int n,char a)     //LL分析分法X=Vt的处理情形
{
   int i;
   for(i=0; i<n; i++)
     if(a==Vt[i])
        break;
   if(i==n&&a!=Vt[n-1]) return(0);
   else return(1);
}

int is_Vn(char Vn[],int n,char a)    //LL分析分法X=Vn的处理情形
{
   int i;
   for(i=0; i<n; i++)
     if(a==Vn[i])
        break;
   if(i==n&&a!=Vn[n-1]) return(0);
   else return(1);
}

void main()
{  
   char x,ch;
   int i=0,index=0;
   char st[20];
   stack s;
   cout<<"LL 语法分析分法----自顶向下分析:"<<endl;
   cout<<"文法G[s]:S->aBc|bAB,A->aAb|b,B->b|λ "<<endl;
   cout<<endl;
   cout<<"\t 输入要分析的字符串(length<20,end by '#'):"<<endl;
   cin>>st[0];
   while(st[i]!='#'){
     i++;
     cin>>st[i];
   }  
   Initstack(s);
   push(s,'#');
   push(s,'S');
   ch=st[index];
   index++;
   while(1){
       pop(s,&x);
       if(is_Vn(Vn,3,x)){
          if(x=='S'&&ch=='a'){
             push(s,'c'); push(s,'B'); push(s,'a');    
          }
          if(x=='S'&&ch=='b'){
             push(s,'B'); push(s,'A'); push(s,'b');    
          }
          if(x=='A'&&ch=='a'){
             push(s,'b'); push(s,'A'); push(s,'a');    
          }
          if(x=='A'&&ch=='b'){
             push(s,'b');   
          }
          if(x=='B'&&ch=='b'){
             push(s,'b');
          }
          if(x=='B'&&ch=='c'){
             push(s,'$');  
          }
          if(x=='B'&&ch=='#'){
             push(s,'$');  
          }
       }
       if(is_Vt(Vt,4,x)){
          if(x==ch){
            if(x!='#'){
                ch=st[index];
               index++;
            }
            else{  
                for(int j=0; j<i; j++)
                cout<<st[j];
                cout<<"是G[s]文法的句子!"<<endl;
                break;
              }
          }
          else{
              for(int j=0; j<i; j++)
               cout<<st[j];
               cout<<"不是G[s]文法的句子!"<<endl;
               break;
          }
        }    
      if(x=='$')  continue;
   }
}
如果有人再编写一个出来让我看看就更好啦

3 楼

我是以前看的编译原理,现在有点模糊了!
有时间我看看,我们可以qq联系!
我资料里有.

4 楼

我想用C++做语法分析器,但我不会用C++,能否教一下
劳驾了

5 楼

看了你的程序,整个思想采用顺势的结构,但其中有些地方逻辑错误,如在最后的main 循环里的判断流程有点错误。。如果采用并发的思想,先对文法:G[S]:S->aBc|bAB
            A->aAb|b
            B->b|入
进行优化,将A->aAb|b改为A->aa*b*b|b,然后弄个缓存,意思就是如baabbb
先进b,进入s->b,进a后启动A判断,A->a,进a,缩a为A->aa*,知道,判断完A的P判断,如果成立则进行S的缩进,s->aA,再进行B的p判断。如果行进行s的P判断
  意思就是将S的p判断分解为A和B的P判断,如果中间A和B哪个错误。则结束,不为文法。如果最后S的P判断总体成立,就是“#”
则文法成立。

6 楼

大虾多多,偶才知道,自己如风中灰尘.偶很想学,刚刚楼上那位大虾的一段猫字,犹如天书般的印在偶滴心中,试在令在下佩服佩服,如愿收小弟为徒,终生报答.联系QQ107726888  

7 楼

顶一下!!

在认真学习。。。

8 楼

我认真看了一下代码,发现作者为栈分配了空间,在结束后却没有释放。 :)

你的数组char Vn[3]={'S','A','B'}; 应该是表示非终结符吧,
而数组char Vt[4]={'a','b','c','#'};应该是终结符吧。  -- 我是个菜鸟

如果出栈的字符是‘B’,而读取的字符是‘a’, 那么这时应该是要出错的,而程序中是没有考虑的。

对于yingyuan大哥的分析,我就看懂了“如果最后S的P判断总体成立,就是“#””...
为什么可以优化将A->aAb|b改为A->aa*b*b|b,这里的*是表示什么意思?

:)

9 楼

要对递归下降的语法分析有个概念。在这个驱动程序中,主要要构造LL(1)语法分析表。把递归转化为非递归 ,然后维护一张表格。借鉴动态规划上的算法。你写的只是一个驱动,用来匹配的。对语法分析主要是是了解它的构造。
  而对于LL(1)预测分析表的构造 主要是为每个非终结符构造FIRST和FOLLOW集合。了解这两个算法很重要,在语言的具体实现中,主要是一些字符串的处理。
下面 简单的说说关于FIRST和FOLLOW的构造问题。
首先对构造FIRST集合 ,我们有下列的算法。
for all non-terminals A do set FIRST(A) = { }
while there are changes to any FIRST(A) do
   for each production A->X1X2...Xn do  
    k = 1,continue = true
    while continue = true and k <= n do
      add FIRST(Xk)-{e} to FIRST(A)
       if e is not in FIRST(Xk)
        continue  = false
        k = k + 1  
    if continue = true then add e to FIRST(A)
  这个算法基本上可以构造一段程序了 。
再其次给出构造FOLLOW集合的算法
    set FOLLOW(start-symbol) = {$} // $ 是终结符号。
      for any non-terminals != start-symbol set FOLLOW(A) = {}
     for any production A->X1X2...Xn do
      if Xi is a nonterminal add FIRST(Xi+1Xi+2..Xn)-{e} to FOLLOW(Xi)
       ifF e is in FIRST(Xi+1Xi+2..Xn) then
          add FOLLOW(A) to FOLLOW(Xi)
        // 结束

希望对你有一定的作用。

10 楼

还要再说一点,对构造LL(1)分析表 先要做的是消去左递归和回朔(提取左因子) 这两个算法我觉得还是比较复杂的。主要需要一定的数学功底
  祝你好运!

我来回复

您尚未登录,请登录后再回复。点此登录或注册