• SLR,语法分析表的构建


    太累了,感觉不会再爱了。执行了跟编译原理上的一模一样的例子,输出了正确结果

      1 #include <stdio.h>
      2 #include <malloc.h>
      3 #include <string.h>
      4 //这个头文件是为了将语法声明的产生式按照调用顺序来构建调用图,并顺便构建反向调用图。
      5 //从而来构建拓扑排序,并用到将来的分析之中。
      6 typedef struct _decl_hash_table
      7 {
      8     int is_used;//代表是否已经被使用
      9     char* decl_hash_name;//代表名字
     10     int node_index;//代表所代表的节点编号
     11 }decl_hash_table,*pdecl_hash_table;
     12 decl_hash_table decl_hash[100];//暂且定位100,其实我们在使用的过程中只会使用其中的97个,因为这个是一个质数
     13 typedef struct _decl_edge
     14 {
     15     int node_of_dest;
     16     struct _decl_edge* next;
     17 }decl_edge,*pdecl_edge;
     18 typedef struct _phrase
     19 {
     20     pdecl_edge begin_of_phrase;
     21     struct _phrase* next;
     22 }phrase;
     23 typedef struct _decl_node
     24 {
     25     phrase* phrase_link;//作为产生体链表的第一个节点的指针
     26     char* name_of_decl;//这个节点的名称,主要是为了输出使用的
     27 }decl_node,*pdecl_node;
     28 decl_node decl_node_table[100];//假设为100个节点,可以改
     29 int node_index=0;//全局的用来给节点赋予编号的变量,最后的值代表了有多少个文法符号,结束符不算在里面
     30 
     31 int insert_decl_hash(char* name,int input_node_index)
     32 //hash表插入函数,如果满了则返回-1
     33 //注意这里为了节省空间,hash表与节点表的名字域公用了一个字符串指针
     34 {
     35     int name_total;
     36     int counter;
     37     int result;
     38     int name_for_i;
     39     char* new_name;
     40     name_for_i=counter=name_total=result=0;
     41     while(name[name_for_i]!='')
     42     {
     43         name_total=name_total+name[name_for_i];
     44         name_for_i++;
     45     }
     46     new_name=malloc(sizeof(char)*(name_for_i+1));
     47     strcpy(new_name,name);
     48     result=name_total%97;
     49     while(counter<97)
     50     {
     51         if(decl_hash[result].is_used==0)
     52         {
     53             decl_hash[result].is_used=1;
     54             decl_hash[result].decl_hash_name=new_name;
     55             decl_hash[result].node_index=input_node_index;
     56             decl_node_table[input_node_index].name_of_decl=new_name;//公用名字指针
     57             return result;
     58         }
     59         else
     60         {
     61             result=(result+1)%97;
     62             counter++;
     63         }
     64     }
     65     return -1;
     66 }
     67 
     68 int search_decl_hash(char* input_name)
     69 {
     70     int name_total;
     71     int counter;
     72     int result;
     73     int name_for_i;
     74     name_for_i=counter=name_total=result=0;
     75     while(input_name[name_for_i]!='')
     76     {
     77         name_total=name_total+input_name[name_for_i];
     78         name_for_i++;
     79     }
     80     result=name_total%97;
     81     while(counter<97)
     82     {
     83         if(decl_hash[result].is_used==1)
     84         {
     85             if(!strcmp(decl_hash[result].decl_hash_name,input_name))
     86             {
     87                 return decl_hash[result].node_index;
     88             }
     89             else
     90             {
     91                 result=(result+1)%97;
     92                 counter++;
     93             }
     94         }
     95         else
     96         {
     97             return -1;
     98         }
     99     }
    100     return -1;
    101 }
    102 
    103 //以上是与hash表有关的函数
    104 //下面则是与建立邻接表相关的数据结构与函数
    105 void tackle_phrase(char* input_phrase)
    106 //根据输入来建立所有的产生式,用数字来代替名字
    107 //注意生成链表的时候,为了插入方便,我们是逆序的链表,全都建完之后再逆序一遍然后变成正序的
    108 {
    109     int for_i,for_j;
    110     int current_tail_node,current_head_node;
    111     char temp[20];//起临时的名字作用
    112     phrase* temp_phrase;
    113     decl_edge* temp_decl_edge;
    114     for_i=0;
    115     while(input_phrase[for_i]!=':'&&input_phrase[for_i]!=' ')
    116     {
    117         temp[for_i]=input_phrase[for_i];
    118         for_i++;
    119     }//找到头部的名字
    120     temp[for_i]='';
    121     current_head_node=search_decl_hash(temp);
    122     if(current_head_node==-1)//如果这个名字是第一次碰到
    123     {
    124         node_index++;
    125         insert_decl_hash(temp,node_index);
    126         current_head_node=node_index;
    127         decl_node_table[current_head_node].phrase_link=NULL;
    128         printf("%d is the label of %s
    ",node_index,temp);
    129     }//建立名字
    130     temp_phrase=malloc(sizeof(struct _phrase));//临时的产生体
    131     temp_phrase->begin_of_phrase=NULL;
    132     temp_phrase->next=decl_node_table[current_head_node].phrase_link;
    133     decl_node_table[current_head_node].phrase_link=temp_phrase;
    134     //把当前的产生式链接到产生式头的产生式链表中
    135     while(input_phrase[for_i]==' '||input_phrase[for_i]==':')
    136     {
    137         for_i++;
    138     }//找到第一个可以分析的点
    139     while(input_phrase[for_i]!='')
    140     {
    141         while(input_phrase[for_i]==' ')
    142         {
    143             for_i++;
    144         }//找到可以分析的点 
    145         for_j=0;
    146         while(input_phrase[for_i]!=' '&&input_phrase[for_i]!='')
    147         {
    148             temp[for_j]=input_phrase[for_i];
    149             for_i++;
    150             for_j++;
    151         }//再次找到一个名字
    152         temp[for_j]='';
    153         current_tail_node=search_decl_hash(temp);
    154         if(current_tail_node==-1)//如果是新的名字,则加入到hash中,并为他分配一个标号
    155         {
    156             node_index++;
    157             current_tail_node=node_index;
    158             insert_decl_hash(temp,node_index);
    159             decl_node_table[current_tail_node].phrase_link=NULL;
    160             printf("%d is the label of %s
    ",node_index,temp);
    161         }
    162         //为当前的产生式链表增加一个元素
    163         temp_decl_edge=malloc(sizeof(struct _decl_edge));
    164         temp_decl_edge->node_of_dest=current_tail_node;
    165         temp_decl_edge->next=temp_phrase->begin_of_phrase;
    166         temp_phrase->begin_of_phrase=temp_decl_edge;
    167     }
    168 }
    169 
    170 
    171 
    172 void phrase_end(void)//这个函数是为了将终结符加入到符号表中
    173 {
    174     char* end="EOF";
    175     decl_node_table[node_index+1].phrase_link=NULL;
    176     insert_decl_hash(end,node_index+1);
    177 }
    178 
    179 void reverse_phrase(void)
    180 {
    181     int for_i;
    182     phrase* temp_phrase;
    183     pdecl_edge temp_edge,swap_edge,next_edge;
    184     for_i=1;
    185     for(for_i=1;for_i<=node_index;for_i++)
    186     {
    187         temp_phrase=decl_node_table[for_i].phrase_link;
    188         while(temp_phrase!=NULL)
    189         {
    190             temp_edge=temp_phrase->begin_of_phrase;
    191             swap_edge=NULL;
    192             while(temp_edge!=NULL)//由于前面是逆序的链表,现在我们把他转成顺序的链表
    193             {
    194                 next_edge=temp_edge->next;
    195                 temp_edge->next=swap_edge;
    196                 swap_edge=temp_edge;
    197                 temp_edge=next_edge;
    198             }
    199             temp_phrase->begin_of_phrase=swap_edge;
    200             //链表转换完成
    201             temp_phrase=temp_phrase->next;
    202         }//当前节点的所有产生式转换完成
    203     }//所有节点的产生式逆转完成
    204 }

    上面的代码只是为所有的文法符号生成一个标号,并将生成式转化了这些标号。

    下面的代码才是核心的生成语法分析表的步骤,感觉总是有点疑问,特别是有些前提没有证明。

      1 #include "declar_topological.h"
      2 typedef struct _lr_group_node
      3 {
      4     int node_pointer;//代表产生式头
      5     phrase* current_phrase;//代表当前的产生式体
      6     pdecl_edge current_edge;//代表当前期待的语法单元 
      7 }lr_group_node,*plr_group_node;//这里是闭包中的一个项的描述
      8 typedef struct _lr_closure
      9 {
     10     plr_group_node current_group_node;//这个代表一个项 
     11     struct _lr_closure* next;//这个next域将所有的单个项串联起来
     12 }lr_closure,*plr_closure;//这里是一个闭包的结构
     13 plr_closure current_closure[100];//暂且定为100,可以改
     14 int group_index=0;//这里是为了标记群号
     15 typedef struct _transition_node
     16 {
     17     enum
     18     {
     19         shift,//移进
     20         reduce,//规约
     21         error,//报错
     22         accept//接受
     23     }action_type;
     24     union
     25     {
     26         struct 
     27         {
     28             int shift_node;//移进的项集
     29         };
     30         struct
     31         {
     32             int reduce_node;//规约的时候的产生式头
     33             int reduce_length;//规约的时候的产生式体的长度
     34         };
     35     };
     36 }transition_node,*p_transition_node;
     37 typedef struct _token_list
     38 {
     39     struct _token_list* next;
     40     int node_number;
     41 }token_list,*ptoken_list;
     42 ptoken_list list_head=NULL;//节点头
     43 
     44 transition_node* transition_table[400];//这里代表了整个转换表
     45 void extend_group(int in_group_index)//扩展项集的函数
     46 {
     47     plr_closure temp_group,temp_group_end,temp_group_add;
     48     //temp_group是用来遍历所有的项,temp_group_end是用来在遍历过程中表示最后一个项,
     49     //temp_group_add跟前面一个合用,来在项集的末尾增加项
     50     plr_group_node temp_group_node,temp_group_node_add;
     51     //temp_group_node是用来遍历项,temp_group_node_add用来在增加项的过程中使用
     52     phrase* temp_phrase;
     53     //这两个都是用来增加项用的
     54     int graph_node_index;
     55     temp_group=current_closure[in_group_index];//得到当前项集的索引
     56     temp_group_end=temp_group;//这里用来得到当前项集的最后一个项
     57     while(temp_group_end->next!=NULL)
     58     {
     59         temp_group_end=temp_group_end->next;
     60     }//寻找到末尾那个节点
     61     while(temp_group!=NULL)//遍历整个项集,必要的时候扩充项集,即闭包
     62     {
     63         temp_group_node=temp_group->current_group_node;//获得当前项
     64         if(temp_group_node->current_edge!=NULL)//如果右端还有文法符号,则试图去扩展
     65         {
     66             graph_node_index=temp_group_node->current_edge->node_of_dest;//获得当前项所期待的文法符号的索引
     67             if(temp_group_node->node_pointer!=graph_node_index)//如果这个文法符号与当前产生式的文法符号不相同
     68             //相同的时候会造成无限循环,即不停的把这个项添加进当前闭包中,并且无法终止 
     69             //由于我们在扩展闭包的过程中是按照拓扑顺序来添加的,所以可以保证在不重复添加同一节点的情况下
     70             //群的大小是有界的
     71             //在不等的情况下,我们可以扩展群
     72             {
     73                 temp_phrase=decl_node_table[graph_node_index].phrase_link;//获得当前文法符号的第一个产生式 
     74                 while(temp_phrase!=NULL)//遍历产生式
     75                 {
     76                     temp_group_node_add=malloc(sizeof(struct _lr_group_node));
     77                     temp_group_node_add->current_edge=temp_phrase->begin_of_phrase;//设置为开始的那一条边
     78                     temp_group_node_add->current_phrase=temp_phrase;//设置为当前产生式的链表头
     79                     temp_group_node_add->node_pointer=graph_node_index;//设置为产生式的头
     80                     //至此构建了一个项的描述
     81                     //开始添加进项集中,准确的来说是末尾
     82                     temp_group_add=malloc(sizeof(struct _lr_closure));
     83                     temp_group_add->current_group_node=temp_group_node_add;
     84                     temp_group_add->next=NULL;
     85                     temp_group_end->next=temp_group_add;
     86                     temp_group_end=temp_group_add;
     87                     temp_phrase=temp_phrase->next;
     88                 }//把当前项的扩展项都添加进去了
     89             }//同上
     90         }
     91         temp_group=temp_group->next;//处理下一项
     92     }//所有的扩展项都处理完成了 
     93 }//扩展完成
     94 
     95 plr_closure closure_transition(int closure_index,int node_index)
     96 {
     97     plr_closure result_closure,now_closure,temp_closure_add,temp_closure_end,temp_closure;
     98     plr_group_node temp_group_node,temp_group_node_add;
     99     pdecl_edge temp_edge;//尼玛 ,为什么这么多temp啊,老子要转函数式编程
    100     now_closure=current_closure[closure_index];
    101     result_closure=malloc(sizeof(struct _lr_closure));
    102     result_closure->current_group_node=NULL;
    103     result_closure->next=NULL;
    104     temp_closure_end=NULL;
    105     //把这个新的群初始化为空
    106     temp_closure=now_closure;
    107     while(temp_closure!=NULL)
    108     {
    109         temp_group_node=temp_closure->current_group_node;
    110         temp_edge=temp_group_node->current_edge;//注意这里current_edge可能为空,要去判断
    111         if(temp_edge!=NULL)//如果不为空,再去判断是否是希望的节点
    112         {
    113             if(temp_edge->node_of_dest==node_index)
    114             {
    115                 temp_group_node_add=malloc(sizeof(struct _lr_group_node));
    116                 temp_group_node_add->current_edge=temp_edge->next;
    117                 temp_group_node_add->current_phrase=temp_group_node->current_phrase;
    118                 temp_group_node_add->node_pointer=temp_group_node->node_pointer;
    119                 //现在建立好了一个项,准备插入到这个项集里面去
    120                 temp_closure_add=malloc(sizeof(struct _lr_closure));
    121                 temp_closure_add->current_group_node=temp_group_node_add;
    122                 temp_closure_add->next=NULL;//因为是从尾部开始加入的所以就初始化为空
    123                 if(temp_closure_end!=NULL)//这里需要判断当前加入的是不是第一个项,因为要特殊处理
    124                 {
    125                     temp_closure_end->next=temp_closure_add;
    126                     temp_closure_end=temp_closure_add;
    127                 }
    128                 else
    129                 {
    130                     result_closure->current_group_node=temp_group_node_add;
    131                     temp_closure_end=result_closure;
    132                     free(temp_closure_add);
    133                 }
    134             }
    135         }
    136         temp_closure=temp_closure->next;
    137     }//一直遍历整个项链表,有转换的时候就添加
    138     if(result_closure->current_group_node==NULL)
    139     {
    140         free(result_closure);
    141         return NULL;
    142         //额,这里忘了释放内存了,调试完再去释放
    143     }
    144     else
    145     {
    146         return result_closure;
    147     }
    148 }
    149 
    150 
    151 int already_in(plr_closure input_closure)
    152 //遍历整个项集来比较,这个方法比较笨,其实可以插入的时候打表
    153 //也可以利用hash或者其他的数据结构来查询
    154 //这个函数是目前问题最大的函数
    155 {
    156     int for_i;
    157     plr_closure temp_closure,begin_closure;
    158     plr_group_node temp_group_node,org_group_node;
    159     for(for_i=1;for_i<=group_index;for_i++)//遍历整个项集族
    160     {
    161         temp_closure=current_closure[for_i];
    162         begin_closure=input_closure;
    163         //都获得第一个项集的指针,这样我们就可以遍历了
    164         while(begin_closure!=NULL)//遍历整个项集,由于当前尚未扩展,所以用这个短的
    165             //当前比较的都是核心项,这里需要担心的是某个项集的核心项包括了当前项集的核心项
    166             //如果出现这种情况,这里的代码就会出现错误
    167             //当前我们先不考虑这种情况,之后再去修改
    168         {
    169             temp_group_node=temp_closure->current_group_node;
    170             org_group_node=begin_closure->current_group_node;
    171             //由于我们保证了添加项集的时候是按照文法符号的引用序来添加的
    172             //所以直接按照链表,一个一个来比较就行了,如果有一个没有匹配上就不需要再去比较剩下的项了
    173             //只需要匹配下一个项集族
    174             //现在判断是否完全匹配
    175             if(temp_group_node->node_pointer==org_group_node->node_pointer)//如果产生式头相同
    176             {
    177                 if(temp_group_node->current_phrase==org_group_node->current_phrase)//如果产生式的体相同
    178                 {
    179                     if(temp_group_node->current_edge==org_group_node->current_edge)//如果下一个期待的符号相同
    180                     {
    181                         temp_closure=temp_closure->next;
    182                         begin_closure=begin_closure->next;
    183                         continue;//进入下次循环
    184                     }
    185                 }
    186             }
    187             break;//如果这三个不能完全匹配,则跳出当前项集循环判断,进入下一个项集的循环判断
    188         }//当前项集遍历结束
    189         if(begin_closure==NULL)
    190             //如果遍历到了末尾,则说明完全匹配了
    191             //这里我们保证了开始时的temp_closure不是空的,因为我们不会插入一个空群
    192         {
    193             return for_i;//返回群号,说明这个项集已经存在了
    194         }
    195     }
    196     //如果所有的项集都无法匹配
    197     return 0;//返回0,说明这个项集还不存在
    198 }
    199 void output_transition(void)
    200 {
    201 
    202     int for_i,for_j;
    203     transition_node* temp_tran_row;
    204     printf("     ");
    205     for(for_i=1;for_i<=node_index+1;for_i++)
    206     {
    207         printf("%-4s ",decl_node_table[for_i].name_of_decl);
    208     }
    209     printf("
    ");
    210     for(for_i=1;for_i<=group_index;for_i++)
    211     {
    212         temp_tran_row=transition_table[for_i];
    213         printf("%3d  ",for_i);
    214         for(for_j=1;for_j<=node_index+1;for_j++)
    215         {
    216             if(temp_tran_row[for_j].action_type==reduce)
    217             {
    218                 printf("r%2d  ",(temp_tran_row+for_j)->reduce_node);
    219             }
    220             else
    221             {
    222                 if(temp_tran_row[for_j].action_type==shift)
    223                 {
    224                     printf("s%2d  ",(temp_tran_row+for_j)->shift_node);
    225                 }
    226                 else
    227                 {
    228                     if(temp_tran_row[for_j].action_type==accept)
    229                     {
    230                         printf("ac   ");
    231                     }
    232                     else
    233                     {
    234                         printf("err  ");
    235                     }
    236                 }
    237             }
    238         }
    239         printf("
    ");
    240     }
    241 }
    242 
    243 void output_closure(void)
    244 {
    245     int for_i;
    246     int begin;
    247     plr_closure temp_closure;
    248     plr_group_node temp_group_node;
    249     pdecl_edge temp_edge;
    250     phrase* temp_phrase;
    251     for(for_i=1;for_i<=group_index;for_i++)
    252     {
    253         temp_closure=current_closure[for_i];
    254         while(temp_closure!=NULL)
    255         {
    256             temp_group_node=temp_closure->current_group_node;
    257             begin=temp_group_node->node_pointer;
    258             temp_phrase=temp_group_node->current_phrase;
    259             temp_edge=temp_phrase->begin_of_phrase;
    260             printf("%s->",decl_node_table[begin].name_of_decl);
    261             while(temp_edge!=NULL)
    262             {
    263                 if(temp_edge==temp_group_node->current_edge)
    264                 {
    265                     printf(".");
    266                 }
    267                 printf("%s",decl_node_table[temp_edge->node_of_dest].name_of_decl);
    268                 temp_edge=temp_edge->next;
    269             }
    270             if(temp_group_node->current_edge==NULL)
    271             {
    272                 printf(".");
    273             }
    274             printf("
    ");//当前项输出完成
    275             temp_closure=temp_closure->next;
    276         }//当前项集输出完成
    277         printf("closure %d is completed
    ",for_i);
    278     }//所有项集输出完成
    279 }
    280 
    281 
    282 
    283 
    284 
    285 void graph_to_closure(char* begin_name)
    286 {
    287     int begin_node_index;//这个作为原来的开始文法符号的索引
    288     int current_group_index;//这个代表当前正在处理的项集
    289     int for_i,is_in;
    290     pdecl_edge temp_edge;
    291     phrase* temp_phrase;
    292     plr_closure temp_group;
    293     plr_group_node temp_group_node;
    294     transition_node* temp_tran_row;//代表临时的转换行
    295     int recept_group;//当作接收节点
    296     begin_node_index=search_decl_hash(begin_name);//找到开始节点的索引
    297     //开始添加伪节点
    298     temp_edge=malloc(sizeof(struct _decl_edge));
    299     temp_edge->next=NULL;
    300     temp_edge->node_of_dest=begin_node_index;
    301     temp_phrase=malloc(sizeof(struct _phrase));
    302     temp_phrase->begin_of_phrase=temp_edge;
    303     temp_phrase->next=NULL;
    304     decl_node_table[0].phrase_link=temp_phrase;
    305     insert_decl_hash("dumb",0);//插入哑元
    306     //这里添加了伪开始节点
    307     //下面开始建群
    308     temp_group_node=malloc(sizeof(struct _lr_group_node));
    309     temp_group_node->current_edge=temp_edge;
    310     temp_group_node->current_phrase=temp_phrase;
    311     temp_group_node->node_pointer=0;
    312     temp_group=malloc(sizeof(struct _lr_closure));
    313     temp_group->next=NULL;
    314     temp_group->current_group_node=temp_group_node;
    315     group_index++;
    316     current_closure[group_index]=temp_group;//从1开始标号,注意
    317     //现在开始扩展项集
    318     extend_group(group_index);
    319     current_group_index=group_index;
    320     while(current_group_index<=group_index)//一个项集一个项集的处理
    321     {
    322         //现在对每一个文法单元进行尝试,看是否有转移
    323         //如果有转移,看是否生成的项集已经被包括了
    324         temp_tran_row=malloc(sizeof(struct _transition_node)*(node_index+2));
    325         //这里需要考虑最后的终结符号,所以加1,又由于为了表述方便,我们把开始偏移定为1,所以最后是加2
    326         transition_table[current_group_index]=temp_tran_row;
    327         for(for_i=1;for_i<=node_index+1;for_i++)//这里加1是为了考虑终结符号
    328         {
    329             temp_group=NULL;
    330             temp_group=closure_transition(current_group_index,for_i);//调用子函数来进行项集的生成
    331             if(temp_group!=NULL)//如果不是空群,进行移进
    332             {
    333                 is_in=already_in(temp_group);
    334                 if(!is_in)//如果这个项集还没有添加
    335                 {
    336                     group_index++;
    337                     current_closure[group_index]=temp_group;
    338                     temp_tran_row[for_i].action_type=shift;
    339                     temp_tran_row[for_i].shift_node=group_index;
    340                     extend_group(group_index);
    341                 }
    342                 else//如果项集已经添加
    343                 {
    344                     temp_tran_row[for_i].action_type=shift;
    345                     temp_tran_row[for_i].shift_node=is_in;
    346                 }
    347             }
    348             else//如果没有转换,则考虑规约
    349             {
    350                 temp_tran_row[for_i].action_type=error;//首先写为这个,后面再去修改
    351                 //现在开始遍历当前项集,如果当前项集里面存在点在最末尾的项,则按照这个项来规约
    352                 //我们默认当前不会产生归约冲突,即当前的是无二义的lr(0)文法
    353                 temp_group=current_closure[current_group_index];
    354                 while(temp_group!=NULL)//遍历当前项集中所有的项,看是否有可归约项
    355                 {
    356                     temp_group_node=temp_group->current_group_node;
    357                     if(temp_group_node->current_edge==NULL)//如果这个项可以作为一个归约式
    358                     {
    359                         int length_of_phrase;//这个代表产生式体有多少个符号
    360                         temp_phrase=temp_group_node->current_phrase;
    361                         temp_edge=temp_phrase->begin_of_phrase;
    362                         length_of_phrase=0;
    363                         while(temp_edge!=NULL)//获得产生式长度
    364                         {
    365                             length_of_phrase++;
    366                             temp_edge=temp_edge->next;
    367                         }
    368                         temp_tran_row[for_i].reduce_node=temp_group_node->node_pointer;
    369                         temp_tran_row[for_i].reduce_length=length_of_phrase;
    370                         temp_tran_row[for_i].action_type=reduce;
    371                         break;
    372                     }
    373                     temp_group=temp_group->next;
    374                 }
    375                 //如果到最后都没有找到可以规约的项,则保持这个为error
    376             }
    377         }//所有文法符号处理完毕
    378         current_group_index++;//当前项集处理完成,开始处理下一个项集
    379 
    380     }//所有的项集处理完成
    381     //这里再去添加一个接受状态
    382     temp_tran_row=transition_table[(transition_table[1]+begin_node_index)->shift_node];
    383     (temp_tran_row+node_index+1)->action_type=accept;
    384     
    385     //现在把这个调整成为了接受状态,可以输出整个转换表了
    386     //现在开始输出
    387     output_closure();//输出所有的项集
    388     output_transition();//输出转换
    389     
    390 }//所有的完成
    391 void str_to_list(char* input_str)//将输入字符转变为文法单元,然后以链表串接起来
    392 {
    393     char temp[10];
    394     int str_index;
    395     int str_len; 
    396     int node_pointer;
    397     ptoken_list temp_list;
    398     ptoken_list current_list;
    399     str_index=0;
    400     while(input_str[str_index]!='')
    401     {
    402         while(input_str[str_index]==' ')
    403         {
    404             str_index++;
    405         }
    406         str_len=0;
    407         while(input_str[str_index]!=' '&&input_str[str_index]!='')
    408         {
    409             temp[str_len]=input_str[str_index];
    410             str_index++;
    411             str_len++;
    412         }
    413         temp[str_len]='';
    414         node_pointer=search_decl_hash(temp);
    415         temp_list=malloc(sizeof(struct _token_list));
    416         temp_list->node_number=node_pointer;
    417         temp_list->next=NULL;
    418         if(list_head==NULL)
    419         {
    420             list_head=temp_list;
    421             current_list=temp_list;
    422         }
    423         else
    424         {
    425             current_list->next=temp_list;
    426             current_list=temp_list;
    427         }
    428     }
    429     temp_list=malloc(sizeof(struct _token_list));
    430     temp_list->node_number=node_index+1;
    431     current_list->next=temp_list;
    432     temp_list->next=NULL;
    433 }
    434 
    435 
    436 
    437 int get_token(void)//从链表中获得一个文法单元
    438 {
    439     ptoken_list temp_list;
    440     int result_node;
    441     result_node=list_head->node_number;
    442     temp_list=list_head;
    443     list_head=list_head->next;
    444     free(temp_list);
    445     return result_node;
    446 }
    447 void putback(int withdraw)
    448 {
    449     ptoken_list temp_list;
    450     temp_list=malloc(sizeof(struct _token_list));
    451     temp_list->node_number=withdraw;
    452     temp_list->next=list_head;
    453     list_head=temp_list;
    454 }
    455 //现在建立了转换表
    456 void input_recognise(void )
    457 {
    458     int syntax_stack[100];//暂且开这么大
    459     int stack_pointer;
    460     int input_token;
    461     int temp_token;
    462     int reduce_token;//注意这里规约的时候,可能会产生为0的点
    463     int reduce_length;
    464     int for_i;
    465     int end=0;
    466     transition_node* current_tran_node;
    467     stack_pointer=1;
    468     syntax_stack[1]=1;//把最开始的群号放进去
    469     temp_token=-1;//防止出现为0的情况
    470     input_token=-1;
    471     while(1)//一直循环
    472     {
    473         if(input_token==-1)
    474         {
    475             input_token=get_token();
    476         }
    477         current_tran_node=transition_table[syntax_stack[stack_pointer]]+input_token;//获得栈顶节点的转换表
    478         switch((current_tran_node->action_type))//判断转换类型
    479         {
    480         case accept://接受
    481             printf("acc
    ");
    482             input_token=-1;
    483             end=1;//设置结束位
    484             break;
    485         case shift://移入
    486             stack_pointer++;
    487             syntax_stack[stack_pointer]=current_tran_node->shift_node;
    488             printf("shift %d
    ",current_tran_node->shift_node);
    489             input_token=-1;//设置提醒位,提示下次需要读取输入
    490             break;
    491         case error://报错
    492             printf("error
    ");
    493             end=1;//设置结束位
    494             break;
    495         case reduce://如果是规约,那么获得规约长度,然后缩短栈指针,
    496             putback(input_token);//返回这个输入
    497             reduce_length=current_tran_node->reduce_length;
    498             reduce_token=current_tran_node->reduce_node;
    499             stack_pointer=stack_pointer-reduce_length;
    500             printf("reduce ");
    501             for(for_i=1;for_i<=reduce_length;for_i++)
    502             {
    503                 printf("%d ",syntax_stack[stack_pointer+for_i]);
    504             }
    505             printf(" to %d 
    ",reduce_token);
    506             input_token=reduce_token;
    507             break;
    508         default:
    509             printf("we are in trouble
    ");
    510             break;
    511         }
    512         if(end!=0)
    513         {
    514             break;//报错或接受,因此结束
    515         }
    516     }//一直循环
    517 }
    518 
    519 
    520 
    521 
    522         
  • 相关阅读:
    C#过滤重复数据,使用泛型
    office2007:您正试图运行的函数包含有宏或需要宏语言支持的内容。而在安装此软件时,您(或您的管理员)选择了不安装宏或控件的支持功能
    InstallShield高级应用获取本机所有的SQL服务
    结对项目
    ActiveMQ 初学1:ActiveMQ 创建连接对象
    【JVM】jstack和dump线程分析(2)
    【JVM】jstack 查询占用最大资源线程|排查死循环等
    【java多线程】volatile 关键字
    1.zookeeper原理解析数据存储之Zookeeper内存结构
    【数据算法】Java实现二叉树存储以及遍历
  • 原文地址:https://www.cnblogs.com/huangfeidian/p/3172277.html
Copyright © 2020-2023  润新知