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]!='\0') 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]!='\0') 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]='\0'; 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\n",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]!='\0') 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]!='\0') 147 { 148 temp[for_j]=input_phrase[for_i]; 149 for_i++; 150 for_j++; 151 }//再次找到一个名字 152 temp[for_j]='\0'; 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\n",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("\n"); 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("\n"); 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("\n");//当前项输出完成 275 temp_closure=temp_closure->next; 276 }//当前项集输出完成 277 printf("closure %d is completed\n",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]!='\0') 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]!='\0') 408 { 409 temp[str_len]=input_str[str_index]; 410 str_index++; 411 str_len++; 412 } 413 temp[str_len]='\0'; 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\n"); 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\n",current_tran_node->shift_node); 489 input_token=-1;//设置提醒位,提示下次需要读取输入 490 break; 491 case error://报错 492 printf("error\n"); 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 \n",reduce_token); 506 input_token=reduce_token; 507 break; 508 default: 509 printf("we are in trouble\n"); 510 break; 511 } 512 if(end!=0) 513 { 514 break;//报错或接受,因此结束 515 } 516 }//一直循环 517 } 518 519 520 521 522