zoukankan      html  css  js  c++  java
  • 消除文法左递归的算法

    存储文法的数据结构

     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("
    ");
     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()) != '
    '){
     34             if('|' == ch){
     35                 str[sp]='';
     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]='';
     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
    ",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
    ",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
    ",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
    ",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,''};
     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,''};
    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("
    -----------------------
    ");
    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("
    ");
    126         }
    127     }
    128     free(g.p);
    129     return 0;
    130 }

    运行结果

    (这里用2代替R',用kong代表空字符)

     

     

  • 相关阅读:
    【java虚拟机】垃圾回收机制详解
    【java虚拟机】分代垃圾回收策略的基础概念
    【java虚拟机】内存分配与回收策略
    【java虚拟机】jvm内存模型
    【转】新说Mysql事务隔离级别
    【转】互联网项目中mysql应该选什么事务隔离级别
    有关PHP的字符串知识
    php的查询数据
    php练习题:投票
    php的数据访问
  • 原文地址:https://www.cnblogs.com/lvyahui/p/4600858.html
Copyright © 2011-2022 走看看