上个版本测试的时候,只用了两个非常简单的测试用例,所以好多情况有问题却没有测试出来

bug1:在生成diff_matrix的时候,循环变量少循环了一次,导致最后一个节点在如果无法与其他点合并的情况下,程序不会给他生成一个群标号。

修改:把循环变量那里加上等于号

bug2:在遍历群的时候,程序是以碰到空指针为结束的,但是在malloc内存的时候,系统并不为这个内存初始化为0,而是0xcd,所以以是不是空指针来判断边界是不可行的,会造成错误,导致读取了而外的信息。

修改:在遍历群的时候,直接以群的数目来做条件测试

bug3:在nfa转dfa的时候,如果某一个dfa节点在某一个字母上的转换导致了目标位图temp_nfa_set的第一个字节为空的情况下,在插入hash的过程中,直接调用strcpy程序会导致只复制第一个字节即结束字符,而忽略后面的那几个字节。从而导致在之后的查表中找不到这个位图。

修改:在hash复制名字的时候,用一个循环,直接一个字节一个字节的复制过去,这样就不会出现前面所说的情况了。

bug4:在re转nfa的时候,对于or的处理,如果or之前有操作符,在弹出该操作符的时候,会忘记为他生成token_node,导致后面的步骤都出现错误。这个问题出现的原因,是当时忘记写了。。。。。

修改:把忘记写的代码加上去。

bug5:在判断两个节点是否在dfa最小化的时候合并调用了is_diff,但是这里可能会出现无限递归的情况,例如节点1在a上到节点2,而节点2在a上到节点1。如果这时利用is_diff(1,2),会导致无限递归。

修改:每次调用is_diff(a,b)的时候,调用之前都在矩阵里面把这两个点所在的位置修改为2,2的意思是正在考虑。如果后面的调用查看到了标记为2的矩阵节点,则这次判断放弃,直接进入下次判断。如果is_diff返回了1,则把这个2修改为1,如果为0,则修改为0。

bug6:在re生成nfa的时候,自做聪明的采取了非标准的转换策略,后来证明有非常大的错误。例如(a|b)*|abc,如果按照我的那个生成策略生成的nfa图,会接受aabc这种情况。。。

修改 :把re转nfa全都按照课本来做了。

目前我自己发现的就有这么多bug,欢迎大家测试

  1. #include "nfa_to_dfa.h"
  2. int* dfa_diff_matrix;
  3.  
  4. int mini_dfa_number;//这个是最小化的 dfa表的索引
  5. typedef struct _min_dfa_node
  6. {
  7. pdfa_edge begin;
  8. int is_end;//记录是否是接受节点
  9. }min_dfa_node,*pmin_dfa_node;
  10. min_dfa_node mini_dfa_table[];//设定为100,其实也可以malloc一下,因为我们已经知道了有多少个节点了
  11. //为了偷懒,算了
  12. is_diff(int input_a,int input_b)//判断两个点是不是等价的程序,注意我们传参数的时候默认a比b大
  13. {
  14. int destination_a,destination_b;//临时的转换目标地址,注意目标地址与矩阵索引是相差1的,注意啊
  15. pdfa_edge temp_edge;//遍历邻接表
  16. char label_traverse;//用来遍历符号表
  17.  
  18. int for_i;
  19. for(for_i=;for_i<alpha_size;for_i++)
  20. {
  21. label_traverse=mini_alpha_set[for_i];
  22. temp_edge=current_dfa_table[input_a+].begin;
  23. while((temp_edge!=NULL)&&(temp_edge->label!=label_traverse))
  24. {
  25. temp_edge=temp_edge->next;
  26. }
  27. if(temp_edge==NULL)
  28. {
  29. destination_a=;
  30. }
  31. else
  32. {
  33. destination_a=temp_edge->dest_dfa_index;
  34. }//获得a的转换目标
  35. temp_edge=current_dfa_table[input_b+].begin;
  36. while((temp_edge!=NULL)&&(temp_edge->label!=label_traverse))
  37. {
  38. temp_edge=temp_edge->next;
  39. }
  40. if(temp_edge==NULL)
  41. {
  42. destination_b=;
  43. }
  44. else
  45. {
  46. destination_b=temp_edge->dest_dfa_index;
  47. }//获得b的转换目标
  48. if(destination_a==destination_b)
  49. {
  50. //目标相同,则无法判断,轮到下一次
  51. }
  52. else
  53. {
  54. if(destination_a*destination_b==)
  55. {
  56. //如果刚好一个为0,说明可以判断
  57. return ;
  58. }
  59. else
  60. {
  61. //因为目标地址的索引与矩阵地址的索引是相差1的,所以我们要这样做
  62. destination_a--;
  63. destination_b--;
  64. if( destination_a>destination_b)//按大小来分
  65. {
  66. if(dfa_diff_matrix[dfa_node_number*(destination_a)+(destination_b)]!=)
  67. //这里是为了防止重复依赖导致的无限递归调用
  68. {
  69. if(dfa_diff_matrix[dfa_node_number*(destination_a)+(destination_b)]!=)//如果当前无法判别
  70. {
  71. dfa_diff_matrix[dfa_node_number*(destination_a)+(destination_b)]=;
  72. if(is_diff(destination_a,destination_b))//如果可以判别
  73. {
  74. dfa_diff_matrix[dfa_node_number*(destination_a)+(destination_b)]=;
  75. return ;
  76. }
  77. else
  78. {
  79. dfa_diff_matrix[dfa_node_number*(destination_a)+(destination_b)]=;
  80. }
  81. }
  82. else
  83. {
  84. return ;
  85. }
  86. }
  87. }
  88. else//如果b比a大
  89. {
  90. if(dfa_diff_matrix[dfa_node_number*(destination_b)+(destination_a)]!=)
  91. {
  92. if(dfa_diff_matrix[dfa_node_number*(destination_b)+(destination_a)]!=)//如果当前无法判别
  93. {
  94. dfa_diff_matrix[dfa_node_number*(destination_b)+(destination_a)]=;
  95. if(is_diff(destination_b,destination_a))//如果可以判别
  96. {
  97. dfa_diff_matrix[dfa_node_number*(destination_b)+(destination_a)]=;
  98. return ;
  99. }
  100. else
  101. {
  102. dfa_diff_matrix[dfa_node_number*(destination_b)+(destination_a)]=;
  103. }
  104. }
  105. else
  106. {
  107. return ;
  108. }
  109. }
  110. }
  111. }
  112. }
  113. }
  114. return ;//如果所有的输入都轮完了,说明当前无法比较。。。
  115. }
  116. void diff_matrix(void)
  117. {
  118. int already_diff_number;//这个是用来判断有多少个点已经经过了等价性测试
  119. int for_i,for_j;
  120. dfa_diff_matrix=malloc(sizeof(int)*dfa_node_number*dfa_node_number);//分配这个节点
  121. for(for_i=;for_i<dfa_node_number;for_i++)
  122. {
  123. for(for_j=;for_j<dfa_node_number;for_j++)
  124. {
  125. dfa_diff_matrix[(for_i)*dfa_node_number+for_j]=;
  126. }
  127. }
  128. for(for_i=;for_i<dfa_node_number;for_i++)
  129. {
  130. for(for_j=;for_j<for_i;for_j++)//这里首先根据是否是接受节点来初始化矩阵
  131. {
  132. if(current_dfa_table[for_i+].is_end!=current_dfa_table[for_j+].is_end)
  133. {
  134. dfa_diff_matrix[(for_i)*dfa_node_number+for_j]=;
  135. }
  136. }
  137. }
  138. do{
  139. already_diff_number=;
  140. for(for_i=;for_i<dfa_node_number;for_i++)
  141. {
  142. for(for_j=;for_j<for_i;for_j++)
  143. {
  144. if(dfa_diff_matrix[(for_i)*dfa_node_number+for_j]!=)
  145. {
  146. dfa_diff_matrix[(for_i)*dfa_node_number+for_j]=;
  147. //做这个标记是为了防止递归调用,表明当前正在考虑的节点有哪些,不要再去试图考虑这些节点对
  148. if(is_diff(for_i,for_j)==)
  149. {
  150. dfa_diff_matrix[(for_i)*dfa_node_number+for_j]=;
  151. already_diff_number++;
  152. }
  153. else
  154. {
  155. dfa_diff_matrix[(for_i)*dfa_node_number+for_j]=;
  156. }
  157. }
  158. }
  159. }
  160. }while(already_diff_number!=);//如果本趟处理没有找到新的可分节点,就结束
  161.  
  162. for(for_i=;for_i<dfa_node_number;for_i++)
  163. {
  164. for(for_j=;for_j<dfa_node_number;for_j++)
  165. {
  166. printf("%d ",dfa_diff_matrix[(for_i)*dfa_node_number+for_j]);
  167. }
  168. printf("\n");
  169. }
  170. }
  171. void minimize_dfa_matrix(void)//在已经构建好了dfa_diff_matrix后,开始群聚,并建图
  172. {
  173. //现在开始群聚
  174. int* already_in_group;//用来记录哪些点已经在群里面了
  175. int* temp_group;
  176. int* before_min_access;//这里来标注哪些节点已经通过了最简化dfa的转换
  177. int group_number=;//注意群号由0开始
  178. int* index_of_group;
  179. pdfa_edge temp_edge;//这个是用来重新建立最小化dfa的临时边
  180. pdfa_edge temp_add_edge;//这个是用来往最小dfa里面增加边的临时边
  181. int dest_group_number;//这个是在增加边的时候的目标编号
  182. int **group_set;
  183. int for_i,for_j;
  184. group_set=malloc(sizeof(int)*dfa_node_number);
  185. already_in_group=malloc(sizeof(int)*dfa_node_number);
  186. for(for_i=;for_i<dfa_node_number;for_i++)
  187. {
  188. already_in_group[for_i]=;
  189. *(group_set+for_i)=NULL;
  190. }
  191. for(for_i=;for_i<dfa_node_number;for_i++)//聚集
  192. {
  193. if(already_in_group[for_i]==)
  194. {
  195. already_in_group[for_i]=;
  196. temp_group=malloc(sizeof(int)*dfa_node_number);
  197. *(group_set+group_number++)=temp_group;
  198. for(for_j=;for_j<dfa_node_number;for_j++)
  199. {
  200. temp_group[for_j]=;
  201. }//注意这里也需要考虑加减1的问题
  202. temp_group[for_i]=;
  203. for(for_j=for_i+;for_j<dfa_node_number;for_j++)
  204. {
  205. if(!dfa_diff_matrix[(for_j)*dfa_node_number+for_i])
  206. {
  207. temp_group[for_j]=;
  208. already_in_group[for_j]=;
  209. }
  210. }
  211. }
  212. }//现在已经完全都聚集为一团了
  213. mini_dfa_number=group_number;
  214. //现在再将节点和群的关系反转
  215. index_of_group=malloc(sizeof(int)*dfa_node_number);
  216. //这里又需要注意加减1的关系,由于这里dfa节点是从1标号的,而我们在index_of_group是从0标号的,要注意
  217. for(for_i=;for_i<dfa_node_number;for_i++)
  218. {
  219. index_of_group[for_i]=;
  220. }
  221. for_i=;
  222. while(for_i<group_number)//前面开了一个索引数组,现在来赋值,这样就可以直接得到某个节点所在的群号
  223. {
  224. for(for_j=;for_j<dfa_node_number;for_j++)
  225. {
  226. if(*(*(group_set+for_i)+for_j)==)
  227. {
  228. index_of_group[for_j]=for_i;
  229. }
  230. }
  231. for_i++;
  232. }//现在关系已经翻转了
  233. //下一步就是利用这个点与群的关系来新建立一个dfa图
  234. //这里的群号就是节点的编号,由于每个群里面的节点都是等价的,所以只需要找一个节点就行了
  235. for(for_i=;for_i<=group_number;for_i++)//这里的for_i是用来表示最小dfa图的标号,所以从1开始
  236. {
  237. //对每一个群进行遍历
  238. mini_dfa_table[for_i].begin=NULL;
  239. mini_dfa_table[for_i].is_end=;
  240. for_j=;
  241. while(*(*(group_set+for_i-)+for_j)!=)//由于group是从0开始标号的,所以要减去1
  242. {
  243. for_j++;
  244. }//找到这个群里面一个节点,注意加减一问题,少犯错误啊,1号节点存储在0号位置上
  245. if(current_dfa_table[for_j+].is_end)//标记为结束节点
  246. {
  247. mini_dfa_table[for_i].is_end=;
  248. }
  249. temp_edge=current_dfa_table[for_j+].begin;
  250. while(temp_edge!=NULL)//重新建设邻接表
  251. {
  252. temp_add_edge=malloc(sizeof(struct _dfa_edge));
  253. temp_add_edge->label=temp_edge->label;
  254. temp_add_edge->next=mini_dfa_table[for_i].begin;
  255. dest_group_number=index_of_group[temp_edge->dest_dfa_index-]+;//特别要注意这里的加一和减一
  256. //由于temp_edge->dest_dfa_node是从1开始标号的,而index_of_group是从0开始标号的,所以我们要减一
  257. //同样,又由于最后的最简化dfa的图是从1开始标号的,所以我们要加1;
  258. temp_add_edge->dest_dfa_index=dest_group_number;
  259. mini_dfa_table[for_i].begin=temp_add_edge;
  260. temp_edge=temp_edge->next;
  261. }
  262. //本群的邻接表构建完成
  263. }//所有群的邻接表构建完成
  264. }
  265. void show_mini_dfa(void)//输出图
  266. {
  267. int for_i;
  268. pdfa_edge temp_dfa_edge;
  269. number_of_end_dfa=;
  270. for(for_i=;for_i<=mini_dfa_number;for_i++)
  271. {
  272. if(mini_dfa_table[for_i].is_end==)
  273. {
  274. printf("this node is an destination node ,index is %d\n",for_i);
  275. }
  276. temp_dfa_edge=mini_dfa_table[for_i].begin;
  277. while(temp_dfa_edge!=NULL)
  278. {
  279. printf("there is an dfa edge from %d to %d with label %c\n",for_i,temp_dfa_edge->dest_dfa_index,temp_dfa_edge->label);
  280. temp_dfa_edge=temp_dfa_edge->next;
  281. }
  282. }
  283. printf("the minimized dfa is completed\n");
  284. }

dfa最小化,修正了上个版本的一些错误。的更多相关文章

  1. 编译原理中DFA最小化

    关于编译原理最小化的操作,专业术语请移步至:http://www.360doc.com/content/18/0601/21/11962419_758841916.shtml 这里只是记录一下个人的理 ...

  2. DFA 最小化

    NDFA.εNDFA 确定化的细节这里就不总结了,这里说一说DFA最小化的算法. 关于DFA最小化,

  3. 第九次作业——DFA最小化,语法分析初步

    老师:MissDu 提交作业 1.将DFA最小化:教材P65 第9题 答: 2.构造以下文法相应的最小的DFA S→ 0A|1B A→ 1S|1 B→0S|0 3.自上而下语法分析,回溯产生的原因是 ...

  4. DFA最小化,语法分析初步

    1.将DFA最小化:教材P65 第9题 2.构造以下文法相应的最小的DFA S→ 0A|1B A→ 1S|1 B→0S|0 语言:(01 | 10)*(01 | 10) 自动机图: DFA状态转换矩阵 ...

  5. 编译原理之DFA最小化,语法分析初步

    1.将DFA最小化: 状态转换图: 识别语言:b*ac*(da)*bb* 2.构造以下文法相应的最小的DFA S→ 0A|1B A→ 1S|1 B→0S|0 (1)正规式: S -> 0(1S+ ...

  6. 第九次作业 DFA最小化,语法分析初步

    1.将DFA最小化:教材P65 第9题 Ⅰ {1,2,3,4,5} {6,7} {1,2}b={1,2,3,4,5} 3,4}b={5} {6,7} Ⅱ {1,2}{3,4}{5} {6,7} 2.构 ...

  7. 作业九——DFA最小化

    1.将DFA最小化:教材P65 第9题 I {1, 2, 3, 4, 5} {6, 7} {1, 2}b->{1, 2, 3, 4, 5} {3, 4}b->{6, 7} {5}b-> ...

  8. 编译原理:DFA最小化,语法分析初步

    1.将DFA最小化:教材P65 第9题   解析: 2.构造以下文法相应的最小的DFA S→ 0A|1B A→ 1S|1 B→0S|0 解析: S→ 0A|1B →S → 0(1S|1)|1(0S|0 ...

  9. 第九次-DFA最小化,语法分析初步

    1.将DFA最小化:教材P65 第9题 2.构造以下文法相应的最小的DFA S→ 0A|1B A→ 1S|1 B→0S|0 3.自上而下语法分析,回溯产生的原因是什么? 4.P100 练习4,反复提取 ...

随机推荐

  1. easyui datagrid 的分页刷新按钮

    datagrid  刷新bug: 情形: 当用户A,B  同时操作 datagrid时(记录1,记录2.记录3).如果A如果删除记录1,  B此时已选中了记录1 ,记录2 , 这时B点击分页中的刷新按 ...

  2. (VC)解决绘图时闪烁问题的一点经验[转]

    转自:http://www.cnblogs.com/lidabo/p/3429862.html 清除屏幕闪烁 (转自网上) <一> 由于作图过于复杂和频繁,所以时常出现闪烁的情况,一些防止 ...

  3. Ehcache(04)——设置缓存的大小

    http://haohaoxuexi.iteye.com/blog/2116749 设置缓存的大小 目录 1     CacheManager级别 2     Cache级别 3     大小衡量 4 ...

  4. java静态代理与动态代理简单分析

    原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/5860749.html 1.动态代理(Dynamic Proxy) 代理分为静态代理和动态代理 ...

  5. Java Zip压缩实现

    最近在自学javaWeb,先复习一下java,把还给老师的东西再找回来(知识如果不用很快就会忘记啊).. 今天看到了zip压缩,决定要整理一下. java将有关zip压缩的内容都封装在java.uti ...

  6. MFC中关于子对话框中编辑框不能编辑的问题

    最近在用MFC写程序.发现子对话框中的编辑框不能编辑.具体问题是这样的: 我有一个对话框YhglDlg,创建了这个对话框的子对话框ZjyhxxDlg,子对话框的Style属性为Child,Border ...

  7. Cortex-M3 Context Switching

    http://www.embedded.com/design/embedded/4231326/Taking-advantage-of-the-Cortex-M3-s-pre-emptive-cont ...

  8. HTML之一 符号实体

    符号实体和”语言代码“以及”字符集“无关.

  9. [Angular2 Router] Configuring a Home Route and Fallback Route - Learn An Essential Routing Concept

    In this tutorial we are going to learn how to configure the Angular 2 router to cover some commonly ...

  10. javascript 中 in操作符

    in in 操作检查对象中是否有名为 property 的属性.也可以检查对象的原型,以便知道该属性是否为原型链的一部分. 对于一般的对象属性需要用字符串指定属性的名称 var mycar = {ma ...