算符优先文法的编程实现

来源:互联网 发布:windows 10 superfetch 编辑:程序博客网 时间:2024/05/16 12:19

实验三 算符优先文法的编程实现

一、实验目的

1. 通过本次实验,加深对移进规约分析法中算符优先法的理解;

2. 学习程序设计语言的语法分析器的手工编程方法。

 

二、实验内容

1. 对于任意给定的文法,判断其是否是算符优先文法。

2. 通过语法分析,生成抽象语法树,在此基础上设计并实现一个简单的计算器。

 

三、实验原理

1. 自底向上优先分析方法

也称移进-归约分析,粗略地说它的思想是对输入符号串自左向右进行扫描,并将输入符号逐个移入一个后进先出栈,边移入边分析,一旦栈顶符号串形成某个句型的句柄或可归约串时,就将该产生式的左部非终极符代替相应的右边文法符号串。

2. 算符优先分析

依照算术表达式的四则运算过程来进行语法分析,即这种分析方法要预先规定运算符(确切地说是终结符)之间的优先关系和结合性质,然后借助于这种关系来比较相邻运算符的优先级,以确定句型的“可归约串”来进行归约。

因此,算符优先分析法不是一种规范归约,在整个归约过程中起决定性作用的是相继两个终结符的优先关系。

3. 算符优先文法

首先定义一个任何产生式的右部都不含两个相继(并列)的非终结符的文法为算符文法,即算符优先文法首先应是一个算符文法;其次,还要定义任何两个可能相继出现的终结符a与b (它们之间最多插有一个非终结符)的优先关系。

4. 终结符号间优先关系的确定,用FIRSTVT集和LASTVT集计算。

 FIRSTVT集:

(1) 若有产生式P→a…或P→Qa…,则a∈FIRSTVT(P);

(2) 若a∈FIRSTVT(Q),且产生式P→Q…,则a∈FIRSTVT(P)。

LASTVT集:

(1)    若有产生式P→…a或P→…aQ,则a∈LASTVT(P);

(2)    若a∈LASTVT(Q),且P→…Q,则a∈LASTVT(P)。

 

四、算法思想

1.根据所输入文法规则,求文法中每个非终结符的FIRSTVT集和LASTVT集。

算符描述如下:

/*求 FirstVT 集的算法*/

PROCEDURE insert(P,a);  IF not F[P,a] then    begin   

        F[P,a] = true; //(P,a)进栈   end;   

Procedure FirstVT;  Begin  

for 对每个非终结符 P和终结符 a do     F[P,a] = false  for 对每个形如 P  a…或 P→Qa…的产生式 do  

Insert(P,a)  while stack  非空  begin  

栈顶项出栈,记为(Q,a)  

for  对每条形如 P→Q…的产生式 do           insert(P,a)  end;  end.

 

2.构造算符优先关系表

  算法描述如下:

  for  每个形如 P->X1X2…Xn的产生式  do    for i =1 to n-1 do    begin  

        if Xi和Xi+1都是终结符    then              Xi   =   Xi+1  

        if i<= n-2, Xi和Xi+2 是终结符, 但Xi+1 为非终结符  then          Xi  = Xi+2  

        if Xi为终结符, Xi+1为非终结符

 then                

 for FirstVT 中的每个元素 a 

do                    Xi  <  a   

        if Xi为非终结符, Xi+1为终结符 

then               

for LastVT 中的每个元素 a 

do                    a  >  Xi+1    

 end 

五、具体实现

#include <stdio.h>#include <stdlib.h>char data[20][20];                    //算符优先关系char s[100];                          //模拟符号栈s char lable[20];                       //文法终极符集char input[100];                      //文法输入符号串char string[20][10];                  //用于输入串的分析int k;                                          char a;  int j;                                               char q;                                              int r;                                //文法规则个数int r1; int m,n,N;                              //转化后文法规则个数char st[10][30];                      //用来存储文法规则char first[10][10];                   //文法非终结符FIRSTVT集char last[10][10];                    //文法非终结符LASTVT集int fflag[10]={0};                    //标志第i个非终结符的FIRSTVT集是否已求出int lflag[10]={0};                   //标志第i个非终结符的LASTVT集是否已求出int zhongjie(char c);                //判断字符c是否是终极符int xiabiao(char c);                 //求字符c在算符优先关系表中的下标void out(int j,int k,char *s);       //打印s栈void firstvt(char c);                //求非终结符c的FIRSTVT集void lastvt(char c);                 //求非终结符c的LASTVT集void table();                        //创建文法优先关系表int main(){int i,j,k=0;    printf("请输入文法规则数:");scanf("%d",&r);printf("请输入文法规则:\n");for(i=0;i<r;i++){scanf("%s",st[i]);    //存储文法规则,初始化FIRSTVT集和LASTVT集*/   first[i][0]=0;            //first[i][0]和last[i][0]分别表示st[i][0]非终极符的FIRSTVT集和LASTVT集中元素的个数last[i][0]=0;}for(i=0;i<r;i++)                           //判断文法是否合法{for(j=0;st[i][j]!='\0';j++){if(st[i][0]<'A'||st[i][0]>'Z'){printf("不是算符文法!\n");    exit(-1);}if(st[i][j]>='A'&&st[i][j]<='Z'){    if(st[i][j+1]>='A'&&st[i][j+1]<='Z'){printf("不是算符文法!\n");        exit(-1);}}}}    for(i=0;i<r;i++){for(j=0;st[i][j]!='\0';j++){if((st[i][j]<'A'||st[i][j]>'Z')&&st[i][j]!='-'&&st[i][j]!='>'&&st[i][j]!='|')lable[k++]=st[i][j];}}lable[k]='#';lable[k+1]='\0';  table();printf("每个非终结符的FIRSTVT集为:\n");    //输出每个非终结符的FIRSTVT集for(i=0;i<r;i++){printf("%c: ",st[i][0]);for(j=0;j<first[i][0];j++){printf("%c ",first[i][j+1]);}printf("\n");}printf("每个非终结符的LASTVT集为:\n");    //输出每个非终结符的LASTVT集for(i=0;i<r;i++){printf("%c: ",st[i][0]);for(j=0;j<last[i][0];j++){printf("%c ",last[i][j+1]);}printf("\n");}printf("算符优先分析表如下:\n");for(i=0;lable[i]!='\0';i++)                     printf("\t%c",lable[i]);printf("\n");                                   for(i=0;i<k+1;i++){printf("%c\t",lable[i]);for(j=0;j<k+1;j++){printf("%c\t",data[i][j]);}printf("\n");}for(i=0;i<k+1;i++){for(j=0;j<k+1;j++){if(data[i][j]=='>'&&data[j][i]!='<'&&data[j][i]!='\0') break;else if(data[i][j]=='<'&&data[j][i]!='>'&&data[j][i]!='\0') break;else if(data[i][j]=='='&&data[j][i]!='='&&data[j][i]!='\0') break;}}if(i==(k+1)&&j==(k+1)) printf("该文法是算符优先文法。\n"); else     printf("该文法不是算符优先文法。\n");  return 0;}void table(){char text[20][10];int i,j,k,t,l,x=0,y=0;int m,n;x=0;for(i=0;i<r;i++){firstvt(st[i][0]);lastvt(st[i][0]);}for(i=0;i<r;i++){text[x][y]=st[i][0];y++;for(j=1;st[i][j]!='\0';j++){if(st[i][j]=='|'){text[x][y]='\0';x++;y=0;text[x][y]=st[i][0];y++;text[x][y++]='-';text[x][y++]='>';}else{text[x][y]=st[i][j];y++;}}text[x][y]='\0';x++;y=0;}r1=x;printf("转化后的文法为:\n");for(i=0;i<x;i++)                      {printf("%s\n",text[i]);}for(i=0;i<x;i++)                        {string[i][0]=text[i][0];for(j=3,l=1;text[i][j]!='\0';j++,l++)string[i][l]=text[i][j];string[i][l]='\0';}for(i=0;i<x;i++){for(j=1;text[i][j+1]!='\0';j++){if(zhongjie(text[i][j])&&zhongjie(text[i][j+1])){m=xiabiao(text[i][j]);n=xiabiao(text[i][j+1]);data[m][n]='=';}if(text[i][j+2]!='\0'&&zhongjie(text[i][j])&&zhongjie(text[i][j+2])&&!zhongjie(text[i][j+1])){m=xiabiao(text[i][j]);n=xiabiao(text[i][j+2]);data[m][n]='=';}if(zhongjie(text[i][j])&&!zhongjie(text[i][j+1])){for(k=0;k<r;k++){if(st[k][0]==text[i][j+1])break;}m=xiabiao(text[i][j]);for(t=0;t<first[k][0];t++){n=xiabiao(first[k][t+1]);data[m][n]='<';}}if(!zhongjie(text[i][j])&&zhongjie(text[i][j+1])){for(k=0;k<r;k++){if(st[k][0]==text[i][j])break;}n=xiabiao(text[i][j+1]);for(t=0;t<last[k][0];t++){m=xiabiao(last[k][t+1]);data[m][n]='>';}}}}m=xiabiao('#');for(t=0;t<first[0][0];t++){n=xiabiao(first[0][t+1]);data[m][n]='<';}n=xiabiao('#');for(t=0;t<last[0][0];t++){m=xiabiao(last[0][t+1]);data[m][n]='>';}data[n][n]='=';}void firstvt(char c)   {int i,j,k,m,n;for(i=0;i<r;i++){if(st[i][0]==c)break;}if(fflag[i]==0){n=first[i][0]+1;m=0;do{if(m==2||st[i][m]=='|'){if(zhongjie(st[i][m+1])){first[i][n]=st[i][m+1];n++;}else{if(zhongjie(st[i][m+2])){first[i][n]=st[i][m+2];n++;}if(st[i][m+1]!=c){firstvt(st[i][m+1]);for(j=0;j<r;j++){if(st[j][0]==st[i][m+1])break;}for(k=0;k<first[j][0];k++){int t;for(t=0;t<n;t++){if(first[i][t]==first[j][k+1])break;}if(t==n){first[i][n]=first[j][k+1];n++;}}}}}m++;}while(st[i][m]!='\0');first[i][n]='\0';first[i][0]=--n;fflag[i]=1;}}void lastvt(char c){int i,j,k,m,n;for(i=0;i<r;i++){if(st[i][0]==c)break;}if(lflag[i]==0){n=last[i][0]+1;m=0;do{if(st[i][m+1]=='\0'||st[i][m+1]=='|'){if(zhongjie(st[i][m])){last[i][n]=st[i][m];n++;}else{if(zhongjie(st[i][m-1])){last[i][n]=st[i][m-1];n++;}if(st[i][m]!=c){lastvt(st[i][m]);for(j=0;j<r;j++){if(st[j][0]==st[i][m])break;}for(k=0;k<last[j][0];k++){int t;for(t=0;t<n;t++){if(last[i][t]==last[j][k+1])break;}if(t==n){last[i][n]=last[j][k+1];n++;}}}}}m++;}while(st[i][m]!='\0');last[i][n]='\0';last[i][0]=--n;lflag[i]=1;}}void out(int j,int k,char *s){int n=0;int i;for(i=j;i<=k;i++){printf("%c",s[i]);n++;}for(;n<15;n++){printf(" ");}}int xiabiao(char c) //求字符c在算符优先关系表中的下标{int i;for(i=0;lable[i]!='\0';i++){if(c==lable[i])return i;}return -1;}int zhongjie(char c)//判断字符c是否是终极符{int i;for(i=0;lable[i]!='\0';i++){if(c==lable[i])return 1;}return 0;}

六、测试与运行情况

1.输入测试样例1:


运行结果:




阅读全文
0 0
原创粉丝点击