automata.c
上传用户:itx_2006
上传日期:2007-01-06
资源大小:493k
文件大小:7k
源码类别:

编译器/解释器

开发平台:

Others

  1. /* Automata conversion functions for DLG
  2.  *
  3.  * SOFTWARE RIGHTS
  4.  *
  5.  * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
  6.  * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
  7.  * company may do whatever they wish with source code distributed with
  8.  * PCCTS or the code generated by PCCTS, including the incorporation of
  9.  * PCCTS, or its output, into commerical software.
  10.  *
  11.  * We encourage users to develop software with PCCTS.  However, we do ask
  12.  * that credit is given to us for developing PCCTS.  By "credit",
  13.  * we mean that if you incorporate our source code into one of your
  14.  * programs (commercial product, research project, or otherwise) that you
  15.  * acknowledge this fact somewhere in the documentation, research report,
  16.  * etc...  If you like PCCTS and have developed a nice tool with the
  17.  * output, please mention that you developed it using PCCTS.  In
  18.  * addition, we ask that this header remain intact in our source code.
  19.  * As long as these guidelines are kept, we expect to continue enhancing
  20.  * this system and expect to make other tools available as they are
  21.  * completed.
  22.  *
  23.  * DLG 1.33
  24.  * Will Cohen
  25.  * With mods by Terence Parr; AHPCRC, University of Minnesota
  26.  * 1989-1998
  27.  */
  28. #include <stdio.h>
  29. #include "dlg.h"
  30. #ifdef MEMCHK
  31. #include "trax.h"
  32. #else
  33. #ifdef __STDC__
  34. #include <stdlib.h>
  35. #else
  36. #include <malloc.h>
  37. #endif /* __STDC__ */
  38. #endif
  39. #define hash_list struct _hash_list_
  40. hash_list{
  41. hash_list *next; /* next thing in list */
  42. dfa_node *node;
  43.  };
  44. int dfa_allocated = 0; /* keeps track of number of dfa nodes */
  45. dfa_node **dfa_array; /* root of binary tree that stores dfa array */
  46. dfa_node *dfa_model_node;
  47. hash_list  *dfa_hash[HASH_SIZE]; /* used to quickly find */
  48. /* desired dfa node */
  49. void
  50. make_dfa_model_node(width)
  51. int width;
  52. {
  53. register int i;
  54. dfa_model_node = (dfa_node*) malloc(sizeof(dfa_node)
  55.  + sizeof(int)*width);
  56. dfa_model_node->node_no = -1; /* impossible value for real dfa node */
  57. dfa_model_node->dfa_set = 0;
  58. dfa_model_node->alternatives = FALSE;
  59. dfa_model_node->done = FALSE;
  60. dfa_model_node->nfa_states = empty;
  61. for(i = 0; i<width; i++){
  62. dfa_model_node->trans[i] = NIL_INDEX;
  63. }
  64. }
  65. /* adds a new nfa to the binary tree and returns a pointer to it */
  66. dfa_node *new_dfa_node(nfa_states)
  67. set nfa_states;
  68. {
  69. register int j;
  70. register dfa_node *t;
  71. static int dfa_size=0; /* elements dfa_array[] can hold */
  72. ++dfa_allocated;
  73. if (dfa_size<=dfa_allocated){
  74. /* need to redo array */
  75. if (!dfa_array){
  76. /* need some to do inital allocation */
  77. dfa_size=dfa_allocated+DFA_MIN;
  78. dfa_array=(dfa_node **) malloc(sizeof(dfa_node*)*
  79. dfa_size);
  80. }else{
  81. /* need more space */
  82. dfa_size=2*(dfa_allocated+1);
  83. dfa_array=(dfa_node **) realloc(dfa_array,
  84. sizeof(dfa_node*)*dfa_size);
  85. }
  86. }
  87. /* fill out entry in array */
  88. t = (dfa_node*) malloc(sizeof(nfa_node)+sizeof(int)*class_no);
  89. *t = *dfa_model_node;
  90. for (j=0; j<class_no; ++j)
  91. t->trans[j] = NIL_INDEX;
  92. t->node_no = dfa_allocated;
  93. t->nfa_states = set_dup(nfa_states);
  94. dfa_array[dfa_allocated] = t;
  95. return t;
  96. }
  97. /* past a pointer to the start start of the nfa graph
  98.  * nfa_to_dfa convers this graph to dfa.  The function returns
  99.  * a pointer to the first dfa state.
  100.  * NOTE:  The function that prints out the table will have to figure out how
  101.  * to find the other dfa states given the first dfa_state and the number of dfa
  102.  * nodes allocated
  103.  */
  104. dfa_node **nfa_to_dfa(start)
  105. nfa_node *start;
  106. {
  107. register dfa_node *d_state, *trans_d_state;
  108. register int a;
  109. set t;
  110. int last_done;
  111. unsigned *nfa_list;
  112. unsigned *reach_list;
  113. reach_list = (unsigned *) malloc((2+nfa_allocated)*sizeof(unsigned));
  114. if (!start) return NULL;
  115. t = set_of(NFA_NO(start));
  116. _set_pdq(t,reach_list);
  117. closure(&t,reach_list);
  118. /* Make t a dfa state */
  119. d_state = dfastate(t);
  120. last_done = DFA_NO(d_state);
  121. do {
  122. /* Mark dfa state x as "done" */
  123. d_state->done = TRUE;
  124. nfa_list = set_pdq(d_state->nfa_states);
  125. for (a = 0; a<class_no; ++a) {
  126. /* Add NFA states reached by a from d_state */
  127. reach(nfa_list,a,reach_list);
  128. /* Were any states found? */
  129. if ((*reach_list)!=nil) {
  130. /* was t=empty; */
  131. set_free(t);
  132. /* yes, compute closure */
  133. closure(&t,reach_list);
  134. /* Make DFA state of it ... */
  135. trans_d_state = dfastate(t);
  136. /* And make transition x->t, labeled with a */
  137. d_state->trans[a] = DFA_NO(trans_d_state);
  138. d_state->alternatives = TRUE;
  139. }
  140. }
  141. free(nfa_list);
  142. ++last_done; /* move forward in queue */
  143. /* And so forth until nothing isn't done */
  144. d_state = DFA(last_done);
  145. } while (last_done<=dfa_allocated);
  146. free(reach_list);
  147. set_free(t);
  148. /* returns pointer to the array that holds the automaton */
  149. return dfa_array;
  150. }
  151. void clear_hash()
  152. {
  153. register int i;
  154. for(i=0; i<HASH_SIZE; ++i)
  155. dfa_hash[i] = 0;
  156. }
  157. #if HASH_STAT
  158. fprint_hash_stats(f)
  159. FILE *f;
  160. {
  161. register hash_list *p;
  162. register int i,j;
  163. register total;
  164. total=0;
  165. for(i=0; i<HASH_SIZE; ++i){
  166. j=0;
  167. p = dfa_hash[i];
  168. while(p){
  169. ++j;
  170. p = p->next;
  171. }
  172. total+=j;
  173. fprintf(f,"bin[%d] has %dn",i,j);
  174. }
  175. fprintf(f,"total = %dn",total);
  176. }
  177. #endif
  178. /* Returns a pointer to a dfa node that has the same nfa nodes in it.
  179.  * This may or maynot be a newly created node.
  180.  */
  181. dfa_node *dfastate(nfa_states)
  182. set nfa_states; /* list of nfa states it could be */
  183. {
  184. register hash_list *p;
  185. int bin;
  186. /* hash using set and see if it exists */
  187. bin = set_hash(nfa_states,HASH_SIZE);
  188. p = dfa_hash[bin];
  189. while(p && !set_equ(nfa_states,(p->node)->nfa_states)){
  190. p = p->next;
  191. }
  192. if(!p){
  193. /* next state to add to hash table */
  194. p = (hash_list*)malloc(sizeof(hash_list));
  195. p->node = new_dfa_node(nfa_states);
  196. p->next = dfa_hash[bin];
  197. dfa_hash[bin] = p;
  198. }
  199. return (p->node);
  200. }
  201. /* this reach assumes the closure has been done already on set */
  202. int reach(nfa_list,a,reach_list)
  203. unsigned *nfa_list;
  204. register int a;
  205. unsigned *reach_list;
  206. {
  207. register unsigned *e;
  208. register nfa_node *node;
  209. int t=0;
  210. e = nfa_list;
  211. if (e){
  212. while (*e != nil){
  213. node = NFA(*e);
  214. if (set_el(a,node->label)){
  215. t=1;
  216. *reach_list=NFA_NO(node->trans[0]);
  217. ++reach_list;
  218. }
  219. ++e;
  220. }
  221. }
  222. *reach_list=nil;
  223. return t;
  224. }
  225. /* finds all the nodes that can be reached by epsilon transitions
  226.    from the set of a nodes and returns puts them back in set b */
  227. set closure(b,reach_list)
  228. set *b;
  229. unsigned *reach_list;
  230. {
  231. register nfa_node *node,*n; /* current node being examined */
  232. register unsigned *e;
  233. ++operation_no;
  234. #if 0
  235. t = e = set_pdq(*b);
  236. #else
  237. e=reach_list;
  238. #endif
  239. while (*e != nil){
  240. node = NFA(*e);
  241. set_orel(NFA_NO(node),b);
  242. /* mark it done */
  243. node->nfa_set = operation_no;
  244. if ((n=node->trans[0]) != NIL_INDEX && set_nil(node->label) &&
  245.   (n->nfa_set != operation_no)){
  246. /* put in b */
  247. set_orel(NFA_NO(n),b);
  248. close1(n,operation_no,b);
  249. }
  250. if ((n=node->trans[1]) != NIL_INDEX &&
  251.   (n->nfa_set != operation_no)){
  252. /* put in b */
  253. set_orel(NFA_NO(node->trans[1]),b);
  254. close1(n,operation_no,b);
  255. }
  256. ++e;
  257. }
  258. #if 0
  259. free(t);
  260. #endif
  261. return *b;
  262. }
  263. void close1(node,o,b)
  264. nfa_node *node;
  265. int o; /* marker to avoid cycles */
  266. set *b;
  267. {
  268. register nfa_node *n; /* current node being examined */
  269. /* mark it done */
  270. node->nfa_set = o;
  271. if ((n=node->trans[0]) != NIL_INDEX && set_nil(node->label) &&
  272.   (n->nfa_set != o)){
  273. /* put in b */
  274. set_orel(NFA_NO(n),b);
  275. close1(n,o,b);
  276. }
  277. if ((n=node->trans[1]) != NIL_INDEX &&
  278.   (n->nfa_set != o)){
  279. /* put in b */
  280. set_orel(NFA_NO(node->trans[1]),b);
  281. close1(n,o,b);
  282. }
  283. }