LL(1)语法分析<转>

来源:互联网 发布:高考物理满分知乎 编辑:程序博客网 时间:2024/05/18 00:15

   

LL(1)分析法的功能是利用LL(1)控制程序根据显示栈栈顶内容、向前看符号以及Ll(1)分析表,对输入符号串自上而下的分析过程。可通过消除左递归、提取左因子把非LL(1)文法改造成LL(1)文法。在LL( 1) 预测分析程序设计过程中,最重要的两个问题是预测分析表的构造和相关数据结构的设计。而预测分析表的构造首先必须计算文法每个非终结符的FIRST集和FOLLOW集。数据结构和算法实现具体实现如下:
1、数据结构:
数组A实现分析栈,数组B存储剩余分析串;一维数组V1存放文法终结符,一维数组V2存放文法非终结符。将产生式类型定义为结构体变量。
2、算法:
a、首先将‘ # ’压入堆栈中, 将开始符号S 也压入堆栈中,读取第一个输入符号到a.

循环执行b--d:

b、栈顶符号弹出放入X 中,如果X 为终结符号:当X = = a ! =‘ # ’时,表明成功匹配a 符号,然后读取下一个符号到a ,否则出错;当X = = a =‘ # ’时,分析结束,接受句子,跳出循环.

c、如果X ! = a ,进行出错处理.

d、如果X 为非终结符号, 则查分析表M :如果M[ X , a ]为空, 进行出错处理; 如果M [X , a ]=‘X1 X2 X3...Xn’, 则将右部Xn...X2 X1 反序压入堆栈中.

本程序分析的文法:
e//    E -> TG       R(O)

g//   G -> +TG      R(1)

g1//  G -> ε        R(2)

t//    T -> FS        R(3)

s//    S -> *FS      R(4)

s1//  S -> ε         R(5)

f//  F -> (E)       R(6)

f1//  F -> i         R(7)  

g2//  G -> -TG      R(8)

s2//  S -> /FS       R(9)

分析句子:E->TG->FSG->iSG->i/FSG->i/iSG->i/iG->i/i-TG->i/i-FSG->i/i-iSG->i/i-iG->i/i-i

手工构造的预测分析表:


 

 

 http://blog.csdn.net/zhouhuozhi/archive/2009/04/30/4141077.aspx

 


#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<dos.h>

char A[20];/*分析栈*/

char B[20];/*剩余串*/

char v1[20]={'i','+','*','(',')','-','/','#'};/*终结符  */

char v2[20]={'E','G','T','S','F'};/*非终结符   */

 

int j=0,b=0,top=0,l;/*L为输入串长度 */

 

typedef struct type/*产生式类型定义      */

{

       char origin;/*大写字符  */

       char array[5];/*产生式右边字符 */

       int length;/*字符个数      */

}type;

 

type e,t,g,g1,g2,s,s1,s2,f,f1;/*结构体变量  */

type C[10][10];/*预测分析表      */

 

void print()/*输出分析栈  */

{

       int a;/*指针*/

       for(a=0;a<=top+1;a++)

              printf("%c",A[a]);

       printf("\t\t");

}/*print*/

 

void print1()/*输出剩余串*/

{

       int j;

       for(j=0;j<b;j++)/*输出对齐符*/

              printf(" ");

       for(j=b;j<=l;j++)

              printf("%c",B[j]);

       printf("\t\t\t");

}/*print1*/

 

void main()

{

       int m,n,k=0,flag=0,finish=0;

       char ch,x;

       type cha;/*用来接受C[m][n]*/

       /*把文法产生式赋值结构体*/

       e.origin='E';

       strcpy(e.array,"TG");

       e.length=2;

      

       t.origin='T';

       strcpy(t.array,"FS");

       t.length=2;

      

       g.origin='G';

       strcpy(g.array,"+TG");

       g.length=3;

      

       g1.origin='G';

       g1.array[0]='^';

       g1.length=1;

 

       g2.origin='G';

       strcpy(g2.array,"-TG");

       g2.length=3;

   

       s.origin='S';

       strcpy(s.array,"*FS");

       s.length=3;

      

       s1.origin='S';

       s1.array[0]='^';

       s1.length=1;

      

       s2.origin='S';

       strcpy(s2.array,"/FS");

       s2.length=3;

      

       f.origin='F';

       strcpy(f.array,"(E)");

       f.length=3;

      

       f1.origin='F';

       f1.array[0]='i';

       f1.length=1;

 

       for(m=0;m<=4;m++)/*初始化分析表*/

              for(n=0;n<=7;n++)

                     C[m][n].origin='N';/*全部赋为空*/

   /*填充分析表*/

   C[0][0]=e;C[0][3]=e;

   C[1][1]=g;C[1][4]=g1;C[1][7]=g1;C[1][5]=g2;

   C[2][0]=t;C[2][3]=t;

   C[3][1]=s1;C[3][2]=s;C[3][4]=C[3][5]=C[3][7]=s1;C[3][6]=s2;

   C[4][0]=f1;C[4][3]=f;

   printf("提示:本程序只能对由'i','+','*','(',')'构成的以'#'结束的字符串进行分析,\n");

   printf("请输入要分析的字符串:");

   do/*读入分析串*/

   {

          scanf("%c",&ch);

          if ((ch!='i') &&(ch!='+') &&(ch!='*')&&(ch!='(')&&(ch!=')')&&(ch!='#')&&(ch!='-')&&(ch!='/'))

          {

                 printf("输入串中有非法字符\n");

                 exit(1);

          }

          B[j]=ch;

          j++;

   }while(ch!='#');

  

   l=j;/*分析串长度*/

   ch=B[0];/*当前分析字符*/

   A[top]='#'; A[++top]='E';/*'#','E'进栈*/

 

   printf("步骤\t\t分析栈 \t\t剩余字符 \t\t所用产生式 \n");

   do

   {

         x=A[top--];/*x为当前栈顶字符*/

      printf("%d",k++);

      printf("\t\t");

     

         for(j=0;j<=7;j++)/*判断是否为终结符*/

                if(x==v1[j])

                {

                       flag=1;

                       break;

                }

                if(flag==1)/*如果是终结符*/

                {

                       if(x=='#')

                       {

                              finish=1;/*结束标记*/

                              printf("acc!\n");/*接受 */

                              getchar();

                              getchar();

                              exit(1);

                       }/*if*/

                       if(x==ch)

                       {

                              print();

                              print1();

                              printf("%c匹配\n",ch);

                              ch=B[++b];/*下一个输入字符*/

                              flag=0;/*恢复标记*/

                       }/*if*/

                       else/*出错处理*/

                       {

                              print();

                              print1();

                              printf("%c出错\n",ch);/*输出出错终结符*/

                              exit(1);

                       }/*else*/

                }/*if*/

                else/*非终结符处理*/

                {

                       for(j=0;j<=4;j++)

                            if(x==v2[j])

                            {

                                   m=j;/*行号*/

                                   break;

                            }

                       for(j=0;j<=7;j++)

                            if(ch==v1[j])

                            {

                                   n=j;/*列号*/

                                   break;

                            }

                       cha=C[m][n];

                       if(cha.origin!='N')/*判断是否为空*/

                       {

                            print();

                            print1();

                            printf("%c->",cha.origin);/*输出产生式*/

                            for(j=0;j<cha.length;j++)

                                   printf("%c",cha.array[j]);

                            printf("\n");

                            for(j=(cha.length-1);j >=0;j--)/*产生式逆序入栈*/

                                   A[++top]=cha.array[j];

                            if(A[top]=='^')/*为空则不进栈*/

                                   top--;

                     }/*if*/

                     else/*出错处理*/

                     {

                            print();

                            print1();

                            printf("%c出错\n",x);/*输出出错非终结符*/

                            exit(1);

                     }/*else*/

              }/*else*/

   }while(finish==0);

}/*main*/