1 ///////////////////////////////////////////////////////////////////////////////
2 // This file is generated automatically using Prop (version 2.3.3),
3 // last updated on Mar 30, 1997.
4 // The original source file is "treegen.pcc".
5 ///////////////////////////////////////////////////////////////////////////////
8 //////////////////////////////////////////////////////////////////////////////
11 // ADLib, Prop and their related set of tools and documentation are in the
12 // public domain. The author(s) of this software reserve no copyrights on
13 // the source code and any code generated using the tools. You are encouraged
14 // to use ADLib and Prop to develop software, in both academic and commercial
15 // settings, and are welcomed to incorporate any part of ADLib and Prop into
18 // Although you are under no obligation to do so, we strongly recommend that
19 // you give away all software developed using our tools.
21 // We also ask that credit be given to us when ADLib and/or Prop are used in
22 // your programs, and that this notice be preserved intact in all the source
25 // This software is still under development and we welcome(read crave for)
26 // any suggestions and help from the users.
30 //////////////////////////////////////////////////////////////////////////////
34 #include <AD/automata/treegram.h> // tree grammar
35 #include <AD/automata/treegen.h> // tree automata compiler
36 #include <AD/contain/bitset.h> // bit set
37 #include <AD/hash/dchash.h> // direct chaining hash map
38 #include <AD/contain/vararray.h> // variable sized array
39 #include <AD/contain/slnklist.h> // linked list
40 #include <AD/memory/mempool.h> // memory pool
42 //////////////////////////////////////////////////////////////////////////////
43 // Make hidden types visible
44 //////////////////////////////////////////////////////////////////////////////
45 typedef TreeGrammar::TreeProduction TreeProduction
;
46 typedef TreeGrammar::Functor Functor
;
47 typedef TreeGrammar::Arity Arity
;
48 typedef TreeGrammar::Variable Variable
;
49 typedef TreeGrammar::State State
;
50 typedef TreeGrammar::Rule Rule
;
51 typedef TreeAutomaton::Equiv Equiv
;
52 typedef SLinkList
<State
> StateList
;
54 //////////////////////////////////////////////////////////////////////////////
55 // Class TreeGenerator represents the internals of the automata compiler.
56 // This stuff is completely hidden from the interface.
57 //////////////////////////////////////////////////////////////////////////////
60 TreeGenerator(const TreeGenerator
&); // no copy constructor
61 void operator = (const TreeGenerator
&); // no assignment
65 ///////////////////////////////////////////////////////////////////////////
66 // Internal data structures
67 ///////////////////////////////////////////////////////////////////////////
70 TreeGrammar
& G
; // the grammar
71 MemPool mem
; // memory pool
72 BitSet
** ruleset_map
; // non-terminal -> rule set
73 Rule
* rule_map
; // non-terminal -> rule set
74 DCHashTable
<TreeTerm
, Variable
> non_terminals
; // term -> non-terminals map
75 VarArray
<TreeTerm
> n_states
; // non-terminals -> term map
76 DCHashTable
<BitSet
*, State
> state_labels
; // non-terminal set -> state mapping
77 DCHashTable
<TreeTerm
, BitSet
*> delta
; // term -> non-terminals mapping
78 VarArray
<BitSet
*> d_states
; // state -> non-terminal set
79 VarArray
<TreeTerm
> d_terms
; // state -> term map
80 BitSet
*** proj
; // projections
81 BitSet
** closure0
; // transitive closure of each non-terminal
82 Variable max_non_terminal
;
83 State number_of_states
;
84 StateList
*** representers
;
86 ///////////////////////////////////////////////////////////////////////////
88 ///////////////////////////////////////////////////////////////////////////
89 TreeGenerator(TreeGen
& gen
, TreeGrammar
& g
) :
90 treegen(gen
), G(g
), mem(4096), non_terminals(1037),
91 state_labels(1037), delta(1037) {}
93 ///////////////////////////////////////////////////////////////////////////
94 // Methods to process various phases of the compilation.
95 ///////////////////////////////////////////////////////////////////////////
96 void assign_non_terminals ();
97 TreeTerm
assign_non_terminal ( TreeTerm
);
98 void compute_closures ();
99 void compute_projections ();
100 void compute_representers ();
101 void compute_initial_states ();
102 void compute_transitions ();
103 BitSet
* compute_transition (BitSet
*, TreeTerm
, int, int, const BitSet
&, State
[], int []);
104 void compute_delta (BitSet
*, TreeTerm
, int, int, const State
[]);
105 void compute_accept_rules (State
);
106 ostream
& print_report (ostream
&) const;
107 ostream
& print_state (ostream
&, State
) const;
110 //////////////////////////////////////////////////////////////////////////////
111 // The following method is used to assign non-terminal symbols
112 // to each distinct term within the grammar
113 //////////////////////////////////////////////////////////////////////////////
114 void TreeGenerator::assign_non_terminals()
116 ///////////////////////////////////////////////////////////////////////////
117 // The grammar may already have user defined variable names.
118 // New non-terminals will have encodings right after these variables.
119 ///////////////////////////////////////////////////////////////////////////
120 max_non_terminal
= G
.max_variable() + 1;
121 non_terminals
.insert(wild_term
,0);
122 { for (Variable v
= max_non_terminal
- 1; v
>= 0; v
--)
123 n_states
[v
] = wild_term
;
126 ///////////////////////////////////////////////////////////////////////////
127 // Traverse thru the grammar and compute the non-terminal numbers.
128 // The tree grammar *IS* destructively altered.
129 ///////////////////////////////////////////////////////////////////////////
130 { for (int i
= G
.size() - 1; i
>= 0; i
--)
131 G
.update(i
,assign_non_terminal( G
[i
].term
));
134 ///////////////////////////////////////////////////////////////////////////
135 // Compute the mapping from non-terminal -> accept rule
136 ///////////////////////////////////////////////////////////////////////////
137 ruleset_map
= (BitSet
**)mem
.c_alloc(sizeof(BitSet
*) * max_non_terminal
);
138 rule_map
= (Rule
*) mem
.c_alloc(sizeof(Rule
) * max_non_terminal
);
140 for (i
= max_non_terminal
- 1; i
>= 0; i
--) rule_map
[i
] = -1;
141 for (i
= G
.size() - 1; i
>= 0; i
--) {
142 Variable v
= non_terminals
[G
[i
].term
];
143 if (ruleset_map
[v
] == 0)
144 ruleset_map
[v
] = new (mem
, max_non_terminal
) BitSet
;
145 ruleset_map
[v
]->add(i
);
151 //////////////////////////////////////////////////////////////////////////////
152 // Method to assign non-terminal numbers for a tree term. This is
153 // defined inductive as:
154 //////////////////////////////////////////////////////////////////////////////
155 TreeTerm
TreeGenerator::assign_non_terminal( TreeTerm t
)
157 ///////////////////////////////////////////////////////////////////////////
158 // Step (a) recursively fold the terms.
159 ///////////////////////////////////////////////////////////////////////////
161 #line 153 "treegen.pcc"
162 #line 163 "treegen.pcc"
166 case a_TreeTerm::tag_tree_term
: {
167 #line 160 "treegen.pcc"
169 for (int i
= _tree_term(t
)->_2
- 1; i
>= 0; i
--)
170 _tree_term(t
)->_3
[i
] = assign_non_terminal(_tree_term(t
)->_3
[i
]);
172 #line 163 "treegen.pcc"
174 case a_TreeTerm::tag_var_term
: {
175 #line 155 "treegen.pcc"
178 #line 156 "treegen.pcc"
180 case a_TreeTerm::tag_and_term
: {
181 #line 157 "treegen.pcc"
182 _and_term(t
)->_1
= assign_non_terminal(_and_term(t
)->_1
); _and_term(t
)->_2
= assign_non_terminal(_and_term(t
)->_2
);
184 #line 158 "treegen.pcc"
186 case a_TreeTerm::tag_or_term
: {
187 #line 158 "treegen.pcc"
188 _or_term(t
)->_1
= assign_non_terminal(_or_term(t
)->_1
); _or_term(t
)->_2
= assign_non_terminal(_or_term(t
)->_2
);
190 #line 159 "treegen.pcc"
192 case a_TreeTerm::tag_not_term
: {
193 #line 159 "treegen.pcc"
194 _not_term(t
)->not_term
= assign_non_terminal(_not_term(t
)->not_term
);
196 #line 160 "treegen.pcc"
199 #line 156 "treegen.pcc"
202 #line 157 "treegen.pcc"
206 #line 154 "treegen.pcc"
209 #line 155 "treegen.pcc"
212 #line 163 "treegen.pcc"
213 #line 163 "treegen.pcc"
216 ///////////////////////////////////////////////////////////////////////////
217 // Look it up from the ``non_terminal'' map.
218 ///////////////////////////////////////////////////////////////////////////
219 Ix p
= non_terminals
.lookup(t
);
220 if (p
== 0) { // not found!
221 ////////////////////////////////////////////////////////////////////////
222 // Step (b) if it is not found, assign a new non-terminal number.
223 // Notice that ``wild_term'' always gets the non-terminal number of 0.
224 ////////////////////////////////////////////////////////////////////////
227 #line 175 "treegen.pcc"
228 #line 179 "treegen.pcc"
232 case a_TreeTerm::tag_var_term
: {
233 #line 177 "treegen.pcc"
234 var
= _var_term(t
)->var_term
;
236 #line 178 "treegen.pcc"
239 #line 178 "treegen.pcc"
240 var
= max_non_terminal
++;
242 #line 179 "treegen.pcc"
246 #line 176 "treegen.pcc"
249 #line 177 "treegen.pcc"
252 #line 179 "treegen.pcc"
253 #line 179 "treegen.pcc"
255 non_terminals
.insert(t
,var
); // update map
256 n_states
[var
] = t
; // update inverse map
258 t
= non_terminals
.key(p
);
263 //////////////////////////////////////////////////////////////////////////////
264 // This is the method for computing transitive closure on a non-terminal
265 // set. Transitive closures apply in the presence of single reductions
267 // or logical connectives:
271 // We don't support negation yet since it is anti-monotonic.
272 //////////////////////////////////////////////////////////////////////////////
273 void TreeGenerator::compute_closures()
275 ///////////////////////////////////////////////////////////////////////////
276 // Allocate the array closure0, which maps each non-terminal to
277 // its transitive closure. Closure set are allocated only if
278 // they are non-trivial (i.e. closure0[v] is something other than
280 ///////////////////////////////////////////////////////////////////////////
281 closure0
= (BitSet
**)mem
.c_alloc(sizeof(BitSet
*) * max_non_terminal
);
283 ///////////////////////////////////////////////////////////////////////////
284 // Allocate closures for user defined non-terminals
285 ///////////////////////////////////////////////////////////////////////////
286 { for (Variable v
= G
.min_variable(); v
<= G
.max_variable(); v
++) {
287 closure0
[v
] = new (mem
, max_non_terminal
) BitSet
;
293 ///////////////////////////////////////////////////////////////////////////
294 // Now compute the transitive closure
295 ///////////////////////////////////////////////////////////////////////////
297 BitSet
& temp
= *new(mem
, max_non_terminal
) BitSet
; // temporary set buffer
301 /////////////////////////////////////////////////////////////////////////
302 // Propagate closure information.
303 /////////////////////////////////////////////////////////////////////////
304 foreach (p
, non_terminals
) {
305 TreeTerm term
= non_terminals
.key(p
);
306 Variable var
= non_terminals
.value(p
);
308 /////////////////////////////////////////////////////////////////////
309 // Allocate a new closure set if necessary.
310 /////////////////////////////////////////////////////////////////////
312 #line 236 "treegen.pcc"
313 #line 243 "treegen.pcc"
316 switch (term
->tag__
) {
317 case a_TreeTerm::tag_tree_term
:
318 case a_TreeTerm::tag_not_term
:
319 case a_TreeTerm::tag_set_term
: {
321 #line 242 "treegen.pcc"
324 #line 243 "treegen.pcc"
328 #line 237 "treegen.pcc"
330 #line 237 "treegen.pcc"
334 #line 237 "treegen.pcc"
336 closure0
[var
] = new (mem
, max_non_terminal
) BitSet
;
337 closure0
[var
]->add(0);
338 closure0
[var
]->add(var
);
341 #line 242 "treegen.pcc"
348 #line 243 "treegen.pcc"
349 #line 243 "treegen.pcc"
352 /////////////////////////////////////////////////////////////////////
353 // Propagate closures sets.
354 /////////////////////////////////////////////////////////////////////
356 #line 248 "treegen.pcc"
357 #line 266 "treegen.pcc"
360 switch (term
->tag__
) {
361 case a_TreeTerm::tag_var_term
: {
363 #line 259 "treegen.pcc"
364 (var
!= _var_term(term
)->var_term
)
365 #line 259 "treegen.pcc"
368 #line 259 "treegen.pcc"
370 if (closure0
[_var_term(term
)->var_term
]) {
371 if (closure0
[var
]->Union_if_changed(*closure0
[_var_term(term
)->var_term
])) changed
= true;
373 if (closure0
[var
]->add_if_changed(_var_term(term
)->var_term
)) changed
= true;
376 #line 265 "treegen.pcc"
380 #line 265 "treegen.pcc"
383 #line 266 "treegen.pcc"
386 case a_TreeTerm::tag_and_term
: {
387 #line 249 "treegen.pcc"
389 BitSet
* s1
= closure0
[ non_terminals
[_and_term(term
)->_1
] ];
390 BitSet
* s2
= closure0
[ non_terminals
[_and_term(term
)->_2
] ];
391 temp
.Intersect(*s1
,*s2
);
392 if (closure0
[var
]->Union_if_changed(temp
)) changed
= true;
394 #line 254 "treegen.pcc"
396 case a_TreeTerm::tag_or_term
: {
397 #line 254 "treegen.pcc"
399 BitSet
* s1
= closure0
[ non_terminals
[_or_term(term
)->_1
] ];
400 BitSet
* s2
= closure0
[ non_terminals
[_or_term(term
)->_2
] ];
401 if (closure0
[var
]->Union_if_changed(*s1
)) changed
= true;
402 if (closure0
[var
]->Union_if_changed(*s2
)) changed
= true;
404 #line 259 "treegen.pcc"
406 default: { goto L3
; } break;
410 #line 266 "treegen.pcc"
411 #line 266 "treegen.pcc"
415 /////////////////////////////////////////////////////////////////////////
416 // Propagate closure information to user non-terminals
417 /////////////////////////////////////////////////////////////////////////
418 for (int i
= G
.size() - 1; i
>= 0; i
--) {
419 Variable v1
= G
[i
].var
;
420 Variable v2
= non_terminals
[G
[i
].term
];
421 // cerr << "[" << v1 << " ";
422 // G.print_variable(cerr,v1) << " <= " << v2 << " ";
423 // G.print(cerr,G[i].term) << "]\n";
424 if (v1
== 0) continue;
426 if (closure0
[v1
]->Union_if_changed(*closure0
[v2
])) changed
= true;
428 if (closure0
[v1
]->add_if_changed(v2
)) changed
= true;
434 //////////////////////////////////////////////////////////////////////////////
435 // This is the method for computing projections.
436 // A projection on functor f and arity i (written as proj[f][i]) is
437 // the set of non-terminals that can appear in that position.
438 //////////////////////////////////////////////////////////////////////////////
439 void TreeGenerator::compute_projections()
441 ///////////////////////////////////////////////////////////////////////////
442 // Allocate the projection array.
443 ///////////////////////////////////////////////////////////////////////////
444 { proj
= (BitSet
***)mem
.c_alloc(sizeof(BitSet
**) * (G
.max_functor() + 1));
445 for (Functor f
= G
.min_functor(); f
<= G
.max_functor(); f
++) {
446 if (G
.arity(f
) == 0) continue;
447 proj
[f
] = (BitSet
**)mem
.c_alloc(sizeof(BitSet
*) * G
.arity(f
));
448 for (int i
= G
.arity(f
) - 1; i
>= 0; i
--) {
449 proj
[f
][i
] = new (mem
, max_non_terminal
) BitSet
;
455 ///////////////////////////////////////////////////////////////////////////
456 // Compute the projections by going over the terms and
457 // looking up the non-terminals at each argument.
458 ///////////////////////////////////////////////////////////////////////////
459 { foreach (p
, non_terminals
) {
461 #line 314 "treegen.pcc"
462 #line 322 "treegen.pcc"
464 TreeTerm _V1
= non_terminals
.key(p
);
466 switch (_V1
->tag__
) {
467 case a_TreeTerm::tag_tree_term
: {
468 #line 315 "treegen.pcc"
470 for (int i
= _tree_term(_V1
)->_2
- 1; i
>= 0; i
--) {
471 Variable v
= non_terminals
[ _tree_term(_V1
)->_3
[i
] ];
472 if (closure0
[v
]) proj
[_tree_term(_V1
)->_1
][i
]->Union(*closure0
[v
]);
473 else proj
[_tree_term(_V1
)->_1
][i
]->add(v
);
476 #line 321 "treegen.pcc"
480 #line 321 "treegen.pcc"
483 #line 322 "treegen.pcc"
488 #line 322 "treegen.pcc"
489 #line 322 "treegen.pcc"
495 //////////////////////////////////////////////////////////////////////////////
496 // Method to allocate the representer state list for each functor at
497 // each arity. ``Representers'' are simply interesting states.
498 //////////////////////////////////////////////////////////////////////////////
499 void TreeGenerator::compute_representers()
500 { representers
= (StateList
***)mem
.c_alloc(sizeof(StateList
**) * (G
.max_functor() + 1));
501 for (Functor f
= G
.min_functor(); f
<= G
.max_functor(); f
++)
503 (StateList
**)mem
.c_alloc(sizeof(StateList
*) * G
.arity(f
));
506 //////////////////////////////////////////////////////////////////////////////
507 // Method to compute the accept rules of a state
508 //////////////////////////////////////////////////////////////////////////////
509 void TreeGenerator::compute_accept_rules (State s
)
510 { register const BitSet
& vars
= *d_states
[ s
];
511 register BitSet
& rules
= treegen
.accept_rules(s
);
512 register Rule min_rule
= G
.size();
514 foreach_bit_fast(v
,vars
) {
515 Rule r
= rule_map
[v
];
516 if (r
>= 0 && r
< min_rule
) min_rule
= r
;
517 const BitSet
* r_set
= ruleset_map
[v
];
518 if (r_set
) rules
.Union(*r_set
);
520 if (min_rule
== G
.size()) min_rule
= -1;
521 treegen
.set_accept1(s
, min_rule
);
524 //////////////////////////////////////////////////////////////////////////////
525 // Method to compute the initial states.
526 // These are the ``wildcard'' or no-information state, state 0.
527 // Followed by a state for each unit functor.
528 //////////////////////////////////////////////////////////////////////////////
529 void TreeGenerator::compute_initial_states()
531 ///////////////////////////////////////////////////////////////////////////
532 // Create the first state corresponding to the wildcard.
533 ///////////////////////////////////////////////////////////////////////////
534 number_of_states
= 0;
535 { BitSet
* state_zero
= new (mem
, max_non_terminal
) BitSet
;
537 state_labels
.insert(state_zero
, number_of_states
);
538 d_states
[ number_of_states
] = state_zero
;
539 d_terms
[ number_of_states
] = new(mem
)
540 #line 371 "treegen.pcc"
542 #line 371 "treegen.pcc"
544 treegen
.new_state(0);
545 compute_accept_rules(0);
549 ///////////////////////////////////////////////////////////////////////////
550 // Generate the rest of the terminal states formed by unit functors.
551 ///////////////////////////////////////////////////////////////////////////
552 { foreach (i
, non_terminals
) {
554 #line 381 "treegen.pcc"
555 #line 396 "treegen.pcc"
557 TreeTerm _V2
= non_terminals
.key(i
);
559 switch (_V2
->tag__
) {
560 case a_TreeTerm::tag_tree_term
: {
561 switch (_tree_term(_V2
)->_2
) {
563 #line 382 "treegen.pcc"
564 // use terms with arity 0 only
565 BitSet
* new_state
= new (mem
, max_non_terminal
) BitSet
;
566 Variable v
= non_terminals
.value(i
);
568 if (closure0
[v
]) new_state
->Union(*closure0
[v
]);
569 else new_state
->add(v
);
570 state_labels
.insert(new_state
, number_of_states
);
571 d_states
[ number_of_states
] = new_state
;
572 d_terms
[ number_of_states
] =
573 #line 390 "treegen.pcc"
574 #line 390 "treegen.pcc"
575 new (mem
) TreeTerm_set_term(new_state
)
576 #line 390 "treegen.pcc"
577 #line 390 "treegen.pcc"
579 treegen
.new_state(number_of_states
);
580 treegen
.add_delta(_tree_term(_V2
)->_1
,number_of_states
);
581 compute_accept_rules(number_of_states
);
584 #line 395 "treegen.pcc"
588 #line 395 "treegen.pcc"
591 #line 396 "treegen.pcc"
595 default: { goto L5
; } break;
599 #line 396 "treegen.pcc"
600 #line 396 "treegen.pcc"
606 //////////////////////////////////////////////////////////////////////////////
607 // Method to compute transitions.
608 //////////////////////////////////////////////////////////////////////////////
609 void TreeGenerator::compute_transitions()
611 ///////////////////////////////////////////////////////////////////////////
612 // Some temporary buffers used during this process.
613 ///////////////////////////////////////////////////////////////////////////
614 BitSet
* projected
[256]; // projected states of arity i
615 Bool is_relevant
[256]; // is arity i relevant?
616 State inputs
[256]; // input state of arity i
617 int equiv_class
[256]; // equivalence class of above.
618 BitSet
* T
= 0; // current result non-terminal set
619 TreeTerm term
= new_term(mem
, 0, 255); // current term
621 { for (int i
= G
.max_arity() - 1; i
>= 0; i
--)
622 projected
[i
] = new (mem
, max_non_terminal
) BitSet
;
625 ///////////////////////////////////////////////////////////////////////////
626 // Compute the transitions of the states. We'll start from state 0.
627 ///////////////////////////////////////////////////////////////////////////
628 for (State current
= 0; current
< number_of_states
; current
++) {
629 const BitSet
& S
= *d_states
[current
];
631 ////////////////////////////////////////////////////////////////////////
632 // Iterate over all the non-unit functors and compute their transition
633 // function on this new state ``current.''
634 ////////////////////////////////////////////////////////////////////////
635 for (Functor f
= G
.min_functor(); f
<= G
.max_functor(); f
++) {
637 if ((n
= G
.arity(f
)) == 0) continue;
640 #line 434 "treegen.pcc"
641 #line 436 "treegen.pcc"
644 switch (term
->tag__
) {
645 case a_TreeTerm::tag_tree_term
: {
646 #line 435 "treegen.pcc"
647 _tree_term(term
)->_1
= f
; _tree_term(term
)->_2
= n
;
648 #line 435 "treegen.pcc"
652 #line 436 "treegen.pcc"
654 #line 436 "treegen.pcc"
659 #line 437 "treegen.pcc"
660 #line 437 "treegen.pcc"
663 /////////////////////////////////////////////////////////////////////
664 // Compute the projections on the arguments.
665 // If the intersection of S with the ith projection is an old state T,
666 // then the transition with respect to arity ith must be the same
668 /////////////////////////////////////////////////////////////////////
669 for (int i
= n
- 1; i
>= 0; i
--) {
670 projected
[i
]->Intersect(S
, *proj
[f
][i
]);
671 projected
[i
]->add(0);
672 Ix old
= state_labels
.lookup(projected
[i
]);
673 State mapped
= current
;
674 if (old
&& (mapped
= state_labels
.value(old
)) < current
) {
675 is_relevant
[i
] = false;
677 representers
[f
][i
] = new (mem
, mapped
, representers
[f
][i
]) StateList
;
678 is_relevant
[i
] = true;
680 //////////////////////////////////////////////////////////////////
681 // Update the index map ``mu.''
682 //////////////////////////////////////////////////////////////////
683 treegen
.add_mu(f
,i
,current
,mapped
);
686 /////////////////////////////////////////////////////////////////////
687 // Now compute the transition function of functor f with respect
688 // to the state ``current.'' Check only the arities that can
689 // produce new information. This is done by fixing all ``relevant''
690 // arities to state ``current'' and the rest to the rest of the
691 // representer states.
692 /////////////////////////////////////////////////////////////////////
693 for (int fix
= n
- 1; fix
>= 0; fix
--) {
694 if (! is_relevant
[fix
]) continue;
695 inputs
[ fix
] = current
;
696 equiv_class
[ fix
] = treegen
.index_map(f
,fix
,current
);
697 T
= compute_transition(T
, term
, 0, fix
, *projected
[fix
], inputs
, equiv_class
);
703 //////////////////////////////////////////////////////////////////////////////
704 // Method to compute a set of transitions functions.
705 // We iterate over all the representer states.
706 //////////////////////////////////////////////////////////////////////////////
707 BitSet
* TreeGenerator::compute_transition
708 ( BitSet
* T
, // temporary bitset
709 TreeTerm term
, // temporary term
710 int i
, // current arity to consider
711 int fixed
, // the fixed arity
712 const BitSet
& S
, // input state of the fixed arity
713 State inputs
[], // input states
714 int equiv
[] // equiv class of above
717 if (i
== fixed
) i
++; // skip the fixed arity.
719 #line 494 "treegen.pcc"
720 #line 552 "treegen.pcc"
723 switch (term
->tag__
) {
724 case a_TreeTerm::tag_tree_term
: {
725 #line 496 "treegen.pcc"
727 if (i
< _tree_term(term
)->_2
) {
728 ////////////////////////////////////////////////////////////////////////
729 // Try arity i == wildcard first
730 ////////////////////////////////////////////////////////////////////////
731 _tree_term(term
)->_3
[i
] = wild_term
;
734 T
= compute_transition(T
, term
, i
+1, fixed
, S
, inputs
, equiv
);
736 //////////////////////////////////////////////////////////////////////
737 // Try arity i == a representer state next.
738 ////////////////////////////////////////////////////////////////////////
739 for (StateList
* r
= representers
[_tree_term(term
)->_1
][i
]; r
; r
= r
->tail
) {
741 equiv
[i
] = treegen
.index_map(_tree_term(term
)->_1
,i
,r
->head
);
742 _tree_term(term
)->_3
[i
] = d_terms
[ r
->head
];
743 T
= compute_transition(T
, term
, i
+1, fixed
, S
, inputs
, equiv
);
746 ////////////////////////////////////////////////////////////////////////
747 // Compute the non-terminal set corresponding to the new state.
748 ////////////////////////////////////////////////////////////////////////
749 if (T
== 0) T
= new (mem
, max_non_terminal
) BitSet
;
753 foreach_bit_fast (v
, S
) {
754 _tree_term(term
)->_3
[ fixed
] = n_states
[v
];
755 compute_delta(T
, term
, 0, fixed
, inputs
);
758 ////////////////////////////////////////////////////////////////////////
759 // Now, lookup the new state to see if it is a new one.
760 // If so, create a new state.
761 ////////////////////////////////////////////////////////////////////////
764 if ((s
= state_labels
.lookup(T
))) { // old state
765 mapped
= state_labels
.value(s
);
766 } else { // new state
767 d_states
[ number_of_states
] = T
;
768 d_terms
[ number_of_states
] = new(mem
)
769 #line 538 "treegen.pcc"
771 #line 538 "treegen.pcc"
773 state_labels
.insert(T
, number_of_states
);
774 treegen
.new_state(number_of_states
);
775 compute_accept_rules(number_of_states
);
777 mapped
= number_of_states
++;
780 ////////////////////////////////////////////////////////////////////////
781 // Update the delta table.
782 ////////////////////////////////////////////////////////////////////////
783 treegen
.add_delta(_tree_term(term
)->_1
, equiv
, mapped
);
786 #line 551 "treegen.pcc"
790 #line 552 "treegen.pcc"
792 #line 552 "treegen.pcc"
797 #line 553 "treegen.pcc"
798 #line 553 "treegen.pcc"
803 //////////////////////////////////////////////////////////////////////////////
804 // Method to compute one delta function
805 //////////////////////////////////////////////////////////////////////////////
806 void TreeGenerator::compute_delta
807 ( BitSet
* T
, // temporary bitset
808 TreeTerm term
, // temporary term
809 int i
, // current arity to consider
810 int fixed
, // the fixed arity
811 const State inputs
[] // input states
813 { Bool first
= i
== 0;
817 if ((p
= non_terminals
.lookup(term
))) {
818 ////////////////////////////////////////////////////////////////////////
819 // Found! use the info from the grammar.
820 ////////////////////////////////////////////////////////////////////////
821 Variable v
= non_terminals
.value(p
);
822 if (closure0
[v
]) T
->Union(*closure0
[v
]);
824 } else if ((p
= delta
.lookup(term
))) {
825 ////////////////////////////////////////////////////////////////////////
826 // Found! use the info from the delta map.
827 ////////////////////////////////////////////////////////////////////////
828 T
->Union(* delta
.value(p
));
830 ////////////////////////////////////////////////////////////////////////
831 // Split input state s into subcases and compute the union of all of
832 // them. Memorize individual cases into the map ``delta.''
833 ////////////////////////////////////////////////////////////////////////
835 #line 588 "treegen.pcc"
836 #line 612 "treegen.pcc"
839 switch (term
->tag__
) {
840 case a_TreeTerm::tag_tree_term
: {
841 #line 590 "treegen.pcc"
843 if (i
< _tree_term(term
)->_2
) {
844 const BitSet
& U
= *d_states
[ inputs
[i
] ];
845 TreeTerm save
= _tree_term(term
)->_3
[i
];
848 else { V
= new (mem
, max_non_terminal
) BitSet
; V
->add(0); }
851 foreach_bit_fast (v
, U
) {
852 _tree_term(term
)->_3
[i
] = n_states
[v
];
853 compute_delta(V
, term
, i
+ 1, fixed
, inputs
);
855 _tree_term(term
)->_3
[i
] = save
;
858 TreeTerm n_term
= new_term(mem
, _tree_term(term
)->_1
, _tree_term(term
)->_2
, _tree_term(term
)->_3
);
859 delta
.insert(n_term
,V
);
864 #line 611 "treegen.pcc"
868 #line 612 "treegen.pcc"
870 #line 612 "treegen.pcc"
875 #line 613 "treegen.pcc"
876 #line 613 "treegen.pcc"
881 //////////////////////////////////////////////////////////////////////////////
882 // Method to print a report of the generated tables.
883 //////////////////////////////////////////////////////////////////////////////
884 ostream
& TreeGenerator::print_report(ostream
& log
) const
886 ///////////////////////////////////////////////////////////////////////////
887 // (1) Print the item set.
888 ///////////////////////////////////////////////////////////////////////////
889 { log
<< "\nItems:\n";
890 for (Variable v
= 0; v
< max_non_terminal
; v
++) {
891 log
<< '{' << v
<< "}\t";
892 G
.print(log
, n_states
[v
]) << '\n';
896 ///////////////////////////////////////////////////////////////////////////
897 // (2) Print each state
898 ///////////////////////////////////////////////////////////////////////////
899 { log
<< "\nStates:\n";
900 for (State s
= 0; s
< number_of_states
; s
++) {
907 //////////////////////////////////////////////////////////////////////////////
908 // Method to print a state
909 //////////////////////////////////////////////////////////////////////////////
910 ostream
& TreeGenerator::print_state(ostream
& log
, State s
) const
912 log
<< '<' << s
<< '>';
913 const BitSet
& S
= *d_states
[s
];
915 foreach_bit(v
,S
) G
.print(log
<< '\t', n_states
[v
]) << '\n';
916 if (treegen
.is_accept_state(s
))
917 log
<< "\t[accept " << treegen
.accept1_rule(s
) << "]\n";
921 //////////////////////////////////////////////////////////////////////////////
922 // Client visible methods follow.
923 // All the work has been down by the class TreeGenerator.
924 // Class TreeGen simply ties things up together.
925 //////////////////////////////////////////////////////////////////////////////
927 //////////////////////////////////////////////////////////////////////////////
928 // Constructors and destructor of the class TreeGen.
929 //////////////////////////////////////////////////////////////////////////////
930 TreeGen:: TreeGen(Mem
& m
) : TreeAutomaton(m
), impl(0) {}
931 TreeGen:: TreeGen(Mem
& m
, TreeGrammar
& Gram
)
932 : TreeAutomaton(m
), impl(0) { compile(Gram
); }
933 TreeGen::~TreeGen() { delete impl
; }
935 //////////////////////////////////////////////////////////////////////////////
936 // This is the top level method to compile a tree grammar.
937 //////////////////////////////////////////////////////////////////////////////
938 void TreeGen::compile (TreeGrammar
& Gram
)
940 ///////////////////////////////////////////////////////////////////////////
941 // Let our superclass do its stuff first.
942 ///////////////////////////////////////////////////////////////////////////
943 Super::compile(Gram
);
945 ///////////////////////////////////////////////////////////////////////////
946 // The internal representation is defined here.
947 ///////////////////////////////////////////////////////////////////////////
949 impl
= new TreeGenerator(*this,Gram
);
951 ///////////////////////////////////////////////////////////////////////////
952 // Now carry out the various steps.
953 ///////////////////////////////////////////////////////////////////////////
954 impl
->assign_non_terminals(); // assign unique non-terminal names.
955 impl
->compute_closures(); // compute transitive closures of non-terminals.
956 impl
->compute_projections(); // compute the projections on functors.
957 impl
->compute_representers(); // allocate the representor states.
958 impl
->compute_initial_states(); // compute the initial states first.
959 impl
->compute_transitions(); // compute the rest of the transitions.
962 //////////////////////////////////////////////////////////////////////////////
963 // Method to print a report of the generated tables.
964 //////////////////////////////////////////////////////////////////////////////
965 ostream
& TreeGen::print_report(ostream
& log
) const
966 { Super::print_report(log
);
967 if (impl
) impl
->print_report(log
);
971 //////////////////////////////////////////////////////////////////////////////
972 // Method to print a state of the generated tables.
973 //////////////////////////////////////////////////////////////////////////////
974 ostream
& TreeGen::print_state(ostream
& log
, State s
) const
975 { if (impl
) impl
->print_state(log
,s
);
979 //////////////////////////////////////////////////////////////////////////////
981 //////////////////////////////////////////////////////////////////////////////
982 const char * TreeGen::algorithm() const { return "TreeGen"; }
983 #line 719 "treegen.pcc"
985 ------------------------------- Statistics -------------------------------
986 Merge matching rules = yes
987 Number of DFA nodes merged = 52
988 Number of ifs generated = 11
989 Number of switches generated = 10
992 Adaptive matching = disabled
993 Fast string matching = disabled
994 Inline downcasts = disabled
995 --------------------------------------------------------------------------