1 /* This group of functions does the character class compression.
2 It goes over the dfa and relabels the arcs with the partitions
3 of characters in the NFA. The partitions are stored in the
9 * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
10 * Set (PCCTS) -- PCCTS is in the public domain. An individual or
11 * company may do whatever they wish with source code distributed with
12 * PCCTS or the code generated by PCCTS, including the incorporation of
13 * PCCTS, or its output, into commerical software.
15 * We encourage users to develop software with PCCTS. However, we do ask
16 * that credit is given to us for developing PCCTS. By "credit",
17 * we mean that if you incorporate our source code into one of your
18 * programs (commercial product, research project, or otherwise) that you
19 * acknowledge this fact somewhere in the documentation, research report,
20 * etc... If you like PCCTS and have developed a nice tool with the
21 * output, please mention that you developed it using PCCTS. In
22 * addition, we ask that this header remain intact in our source code.
23 * As long as these guidelines are kept, we expect to continue enhancing
24 * this system and expect to make other tools available as they are
29 * With mods by Terence Parr; AHPCRC, University of Minnesota
45 int class_no = CHAR_RANGE; /* number of classes for labels */
46 int first_el[CHAR_RANGE]; /* first element in each class partition */
47 set class_sets[CHAR_RANGE]; /* array holds partitions from class */
50 /* goes through labels on NFA graph and partitions the characters into
51 * character classes. This reduces the amount of space required for each
52 * dfa node, since only one arc is required each class instead of one arc
55 * 0 no compression done
56 * 1 remove unused characters from classes
57 * 2 compress equivalent characters into same class
59 * returns the number of character classes required
61 int relabel(start,level)
66 set_free(used_classes);
67 partition(start,level);
68 label_with_classes(start);
70 /* classes equivalent to all characters in alphabet */
71 class_no = CHAR_RANGE;
76 /* makes character class sets for new labels */
77 partition(start,level)
78 nfa_node *start; /* beginning of nfa graph */
79 int level; /* compression level to uses */
85 unpart_chars = set_dup(used_chars);
87 /* EOF (-1+1) alway in class 0 */
88 class_sets[0] = set_of(0);
90 used_classes = set_of(0);
91 temp = set_dif(unpart_chars, class_sets[0]);
92 set_free(unpart_chars);
98 while (!set_nil(unpart_chars)){
99 /* don't look for equivalent labels if c <= 1 */
101 current_class = set_of(set_int(unpart_chars));
103 current_class = set_dup(unpart_chars);
104 intersect_nfa_labels(start,¤t_class);
106 set_orel(class_no,&used_classes);
107 first_el[class_no] = set_int(current_class);
108 class_sets[class_no] = current_class;
109 temp = set_dif(unpart_chars,current_class);
110 set_free(unpart_chars);
115 /* free unpart_chars -ATG 5/6/95 */
116 set_free(unpart_chars);
119 /* group all the other unused characters into a class */
120 set_orel(class_no,&used_classes);
121 first_el[class_no] = set_int(current_class);
122 class_sets[class_no] = set_dif(normal_chars,used_chars);
128 /* given pointer to beginning of graph and recursively walks it trying
129 * to find a maximal partition. This partion in returned in maximal_class
131 intersect_nfa_labels(start,maximal_class)
135 /* pick a new operation number */
137 r_intersect(start,maximal_class);
140 r_intersect(start,maximal_class)
146 if(start && start->nfa_set != operation_no)
148 start->nfa_set = operation_no;
149 temp = set_and(*maximal_class,start->label);
152 set_free(*maximal_class);
153 *maximal_class = temp;
157 r_intersect(start->trans[0],maximal_class);
158 r_intersect(start->trans[1],maximal_class);
163 /* puts class labels in place of old character labels */
164 label_with_classes(start)
177 /* only do node if it hasn't been done before */
178 if (start && start->nfa_set != operation_no){
179 start->nfa_set = operation_no;
181 for (i = 0; i<class_no; ++i){
182 /* if one element of class in old_label,
184 if (set_el(first_el[i],start->label))
185 set_orel(i,&new_label);
187 set_free(start->label);
188 start->label = new_label;
189 /* do any nodes that can be reached from this one */
190 label_node(start->trans[0]);
191 label_node(start->trans[1]);