消除文法左递归的算法
存储文法的数据结构
1 typedef struct P{ 2 char key; // 产生式左部 3 char * value [16]; // 产生式右部 4 int count; // 几组规则 5 }P; 6 typedef struct G{ 7 char * vn ; // 非终结符集合 8 char * vt ; // 终结符集合 9 P p[16]; // 产生式 10 char start; // 开始符号 11 int pcount ; 12 }G;
文法G由多条产生式组成,出现在产生式左部的非终结符,会指向一个P文法数组,每一个数组元素对应一个程式的右部,这样的结构显然是对文法进行了压缩的
算法过程
1、 扫描文法,先将间接做递归转换成直接左递归
2、 借助如下公式,消除直接左递归
对形如这样的程式
A->Aα1|Aα2|Aα3| Aαn|..|ρ1|ρ2|….| ρn
转换成如下形式
A->ρ1A'|ρ2A'|ρ3A'
A'->α1A'|α2A'|....|ε
输入
1 3 2 2 S Qc|c 3 2 Q Rb|b 4 2 R Sa|a
完整算法
1 #include <stdio.h> 2 #include <malloc.h> 3 #include <string.h> 4 5 typedef struct P{ 6 char key; // 产生式左部 7 char * value [16]; // 产生式右部 8 int count; // 几组规则 9 }P; 10 typedef struct G{ 11 char * vn ; // 非终结符集合 12 char * vt ; // 终结符集合 13 P p[16]; // 产生式 14 char start; // 开始符号 15 int pcount ; 16 }G; 17 18 int main(){ 19 int i,n; 20 freopen("xczdg.in","r",stdin); 21 printf("Plese input P count :"); 22 scanf("%d",&n); 23 printf("\n"); 24 G g; 25 g.pcount = n; 26 //g.p = (P *)malloc(sizeof(P)*n); 27 for(i=0;i<n;i++){ 28 scanf("%d%*c",&g.p[i].count); 29 g.p[i].key = getchar(); 30 getchar(); 31 char ch,str[255]; 32 int sp = 0,c=0; 33 while((ch = getchar()) != '\n'){ 34 if('|' == ch){ 35 str[sp]='\0'; 36 g.p[i].value[c] = (char *) malloc(sizeof(char)*255); 37 strcpy(g.p[i].value[c],str); 38 sp = 0; 39 c++; 40 } 41 else{ 42 str[sp] = ch; 43 sp++; 44 } 45 } 46 str[sp]='\0'; 47 g.p[i].value[c] = (char *) malloc(sizeof(char)*255); 48 strcpy(g.p[i].value[c],str); 49 50 printf("%c=>%s|%s\n",g.p[i].key,g.p[i].value[0],g.p[i].value[1]); 51 } 52 53 for(i=0;i<n;i++){ 54 int j = 0; 55 for(;j<i;j++){ 56 // 将间接左递归转换成直接左递归 57 // 扫描Ai的开始符号,一定要是非终结符 58 int k; 59 for(k=0;k<g.p[i].count;k++){ 60 char i_start = g.p[i].value[k][0]; 61 //printf("%c\n",start); 62 if(i_start==g.p[j].key){ 63 // 满足 Ai->Ajr 64 char tmp[255]; 65 char fiel[255]; 66 strcpy(fiel,&g.p[i].value[k][1]); 67 68 strcpy(tmp,g.p[j].value[0]); 69 strcpy(g.p[i].value[k],strcat(tmp,fiel)); 70 printf("%d %s\n",k,g.p[i].value[k]); 71 int m; 72 for(m=1;m<g.p[j].count;m++){ 73 strcpy(tmp,g.p[j].value[m]); 74 g.p[i].value[g.p[i].count] = (char *) malloc(sizeof(char)*255); 75 strcpy(g.p[i].value[g.p[i].count],strcat(tmp,fiel)); 76 printf("%d %s\n",g.p[i].count,g.p[i].value[g.p[i].count]); 77 g.p[i].count++; 78 79 } 80 } 81 82 } 83 } 84 // 消除直接左递归 85 // 扫描Pi.key 为产生式右部的所有产生式 86 for(j=0;j<g.p[i].count;j++){ 87 char * pivj = g.p[i].value[j]; 88 if(g.p[i].key == pivj[0]){ 89 // 存在直接左递归 90 int m; 91 for(m=0;m<g.p[i].count;m++){ 92 if(m!=j){ 93 // A->ρ1A'|ρ2A'|ρ3A' ρρσσαα 94 char aci[2] = {g.p[i].key-32,'\0'}; 95 strcat(g.p[i].value[m],aci); // 这里A'直接已A的ASCII码值减32表示 96 }else{ 97 // A'->α1A'|α2A'|....|ε 98 g.p[g.pcount].key = g.p[i].key-32; 99 g.p[g.pcount].value[0] = (char *) malloc(sizeof(char)*255); 100 strcpy(g.p[g.pcount].value[0],&pivj[1]); 101 char aci[2] = {g.p[g.pcount].key,'\0'}; 102 strcat(g.p[g.pcount].value[0],aci); 103 g.p[g.pcount].value[1] = (char *) malloc(sizeof(char)*255); 104 strcpy(g.p[g.pcount].value[1],"kong"); 105 g.p[g.pcount].count = 2; 106 g.p[i].value[j] = NULL; 107 g.pcount++; 108 } 109 } 110 break; 111 } 112 } 113 114 } 115 116 printf("\n-----------------------\n"); 117 // 打印文法 118 for(i=0;i<g.pcount;i++){ 119 if(g.p[i].key){ 120 if(g.p[i].key) printf("%c=>",g.p[i].key); 121 int j; 122 for(j=0;j<g.p[i].count;j++){ 123 if(g.p[i].value[j]) printf("%s ",g.p[i].value[j]); 124 } 125 printf("\n"); 126 } 127 } 128 free(g.p); 129 return 0; 130 }
运行结果
(这里用2代替R',用kong代表空字符)