1 /////////////////////////////////////////////////////////////////////////////
4 // ADLib, Prop and their related set of tools and documentation are in the
5 // public domain. The author(s) of this software reserve no copyrights on
6 // the source code and any code generated using the tools. You are encouraged
7 // to use ADLib and Prop to develop software, in both academic and commercial
8 // settings, and are welcomed to incorporate any part of ADLib and Prop into
11 // Although you are under no obligation to do so, we strongly recommend that
12 // you give away all software developed using our tools.
14 // We also ask that credit be given to us when ADLib and/or Prop are used in
15 // your programs, and that this notice be preserved intact in all the source
18 // This software is still under development and we welcome(read crave for)
19 // any suggestions and help from the users.
23 //////////////////////////////////////////////////////////////////////////////
25 #define TreeGrammar_Iterators
28 #include <AD/automata/treegram.ph>
30 #include <AD/rewrite/b_rules.h>
31 #include <AD/hash/dchash.h>
33 //////////////////////////////////////////////////////////////////////////////
35 // Make hidden types visible for use.
37 //////////////////////////////////////////////////////////////////////////////
38 typedef TreeGrammar::Functor Functor;
39 typedef TreeGrammar::NonTerminal NonTerminal;
40 typedef TreeGrammar::Rule Rule;
41 typedef TreeGrammar::Cost Cost;
42 typedef BURS_RuleSet::LeafReduction LeafReduction;
43 typedef BURS_RuleSet::Reduction Reduction;
44 typedef BURS_RuleSet::ChainRule ChainRule;
46 //////////////////////////////////////////////////////////////////////////////
48 // Hash functions and equality functions for leaf reductions.
50 //////////////////////////////////////////////////////////////////////////////
51 inline Bool equal (const LeafReduction * a, const LeafReduction * b)
52 { return a->f == b->f && a->cost == b->cost && a->rule == b->rule;
54 inline unsigned hash (const LeafReduction * a)
55 { return a->f + a->cost + a->rule; }
57 //////////////////////////////////////////////////////////////////////////////
59 // Hash functions and equality functions for non-leaf reductions.
61 //////////////////////////////////////////////////////////////////////////////
62 inline Bool equal (const Reduction * a, const Reduction * b)
63 { if (a->f != b->f || a->cost != b->cost ||
64 a->rule != b->rule || a->n != b->n) return false;
65 for (int i = a->n - 1; i >= 0; i--)
66 if (a->rhs[i] != b->rhs[i]) return false;
69 inline unsigned hash (const Reduction * a)
70 { unsigned h = a->f + a->cost + a->rule + a->n;
71 for (int i = a->n - 1; i >= 0; i--) h += a->rhs[i];
75 //////////////////////////////////////////////////////////////////////////////
77 // Hash functions and equality functions for chain reductions.
79 //////////////////////////////////////////////////////////////////////////////
80 inline Bool equal (const ChainRule * a, const ChainRule * b)
81 { return a->rhs == b->rhs && a->cost == b->cost && a->rule == b->rule;
83 inline unsigned hash (const ChainRule * a)
84 { return a->rhs + a->cost + a->rule; }
86 //////////////////////////////////////////////////////////////////////////////
88 // Internal implementation
90 //////////////////////////////////////////////////////////////////////////////
91 class BURS_RuleSet_Impl {
92 BURS_RuleSet_Impl(const BURS_RuleSet_Impl&);
93 void operator = (const BURS_RuleSet_Impl&);
95 DCHashTable <LeafReduction *, int> leaf_map;
96 DCHashTable <Reduction *, int> non_leaf_map;
97 DCHashTable <ChainRule *, int> chain_rule_map;
98 inline BURS_RuleSet_Impl() {}
99 inline ~BURS_RuleSet_Impl() {}
102 //////////////////////////////////////////////////////////////////////////////
104 // Constructor and destructor
106 //////////////////////////////////////////////////////////////////////////////
107 BURS_RuleSet:: BURS_RuleSet( Mem& mem, const TreeGrammar& g) : G(g)
109 ///////////////////////////////////////////////////////////////////////////
110 // Create a new set of hash tables.
111 ///////////////////////////////////////////////////////////////////////////
112 impl = new BURS_RuleSet_Impl;
114 ///////////////////////////////////////////////////////////////////////////
115 // Count the number of rules of each kind.
116 ///////////////////////////////////////////////////////////////////////////
117 leaf_reduction_count = 0; // e.g. A -> c
118 reduction_count = 0; // e.g. A -> f (A_1, A_2, ..., A_n)
119 chain_rule_count = 0; // e.g. A -> B
120 has_wild_card = false; // assume we don't have wildcard in grammar
122 { foreach_production (i, g) count_rules(g[i].term); }
124 ///////////////////////////////////////////////////////////////////////////
125 // Allocate the tables.
126 ///////////////////////////////////////////////////////////////////////////
127 leaf_reduction_table = new LeafReduction [ leaf_reduction_count ];
128 reduction_table = new Reduction * [ reduction_count ];
129 chain_rule_table = new ChainRule [ chain_rule_count ];
130 int non_term_count = g.max_variable() + 1 + leaf_reduction_count +
131 reduction_count + chain_rule_count;
132 non_term_to_tree = new TreeTerm [non_term_count];
133 { for (int i = 0; i < non_term_count; i++)
134 non_term_to_tree[i] = wild_term;
137 ///////////////////////////////////////////////////////////////////////////
138 // Now normalise the patterns into canonical form.
139 ///////////////////////////////////////////////////////////////////////////
141 leaf_reduction_count = 0;
142 chain_rule_count = 0;
143 non_terminal_count = g.max_variable() + 1;
145 { foreach_production (i, g)
146 add_reduction(mem, i, g[i].var, g[i].term, g[i].cost);
148 assert(non_terminal_count <= non_term_count);
150 ///////////////////////////////////////////////////////////////////////////
151 // Finally compute the list of non-unit reductions partitioned by
153 ///////////////////////////////////////////////////////////////////////////
154 reductions = new ReductionList * [ g.max_functor() + 1 ];
155 { foreach_functor (f,g) reductions[f] = 0; }
156 { for (int i = 0; i < reduction_count; i++) {
157 Functor f = reduction_table[i]->f;
159 new (mem, reduction_table[i], reductions[f]) ReductionList;
163 ///////////////////////////////////////////////////////////////////////////
165 ///////////////////////////////////////////////////////////////////////////
169 //////////////////////////////////////////////////////////////////////////////
173 //////////////////////////////////////////////////////////////////////////////
174 BURS_RuleSet::~BURS_RuleSet()
175 { delete [] reduction_table;
176 delete [] chain_rule_table;
177 delete [] leaf_reduction_table;
178 delete [] reductions;
181 //////////////////////////////////////////////////////////////////////////////
183 // Method to count the number of canonical rules.
185 //////////////////////////////////////////////////////////////////////////////
186 void BURS_RuleSet::count_rules(TreeTerm t)
188 case wild_term: has_wild_card = true; chain_rule_count++;
189 case var_term(v): chain_rule_count++;
190 case tree_term(_,0,_): leaf_reduction_count++;
191 case tree_term(_,n,subterms):
192 for (int i = n - 1; i >= 0; i--) count_rules(subterms[i]);
194 case _: assert("Error in BURS_RuleSet::count_rules");
198 //////////////////////////////////////////////////////////////////////////////
200 // Method to add an reduction rule into the table
202 //////////////////////////////////////////////////////////////////////////////
203 NonTerminal BURS_RuleSet::add_reduction
204 (Mem& mem, Rule r, NonTerminal lhs, TreeTerm t, Cost cost)
206 case tree_term(F,0,_):
207 leaf_reduction_table[ leaf_reduction_count ].f = F;
208 leaf_reduction_table[ leaf_reduction_count ].cost = cost;
209 leaf_reduction_table[ leaf_reduction_count ].rule = r;
210 Ix i = impl->leaf_map.lookup(leaf_reduction_table + leaf_reduction_count);
212 return impl->leaf_map.key(i)->lhs;
214 impl->leaf_map.insert(leaf_reduction_table + leaf_reduction_count,0);
216 { non_term_to_tree[lhs] = t;
217 return leaf_reduction_table[ leaf_reduction_count++ ].lhs = lhs;
219 NonTerminal T = non_terminal_count++;
220 non_term_to_tree[T] = t;
221 return leaf_reduction_table[ leaf_reduction_count++ ].lhs = T;
224 case tree_term(F,N,S):
225 { Reduction * red = new (mem, N) Reduction;
230 { for (int i = 0; i < N; i++) {
232 case wild_term: red->rhs[i] = 0;
234 red->rhs[i] = add_reduction(mem, -1, -1, S[i], 0);
238 Ix i = impl->non_leaf_map.lookup(red);
240 return impl->non_leaf_map.key(i)->lhs;
242 reduction_table[ reduction_count++ ] = red;
243 impl->non_leaf_map.insert(red,0);
245 { non_term_to_tree[lhs] = t;
246 return red->lhs = lhs;
248 NonTerminal T = non_terminal_count++;
249 non_term_to_tree[T] = t;
255 chain_rule_table[ chain_rule_count ].rhs = 0;
256 chain_rule_table[ chain_rule_count ].cost = cost;
257 chain_rule_table[ chain_rule_count ].rule = r;
258 Ix i = impl->chain_rule_map.lookup(chain_rule_table + chain_rule_count);
260 return impl->chain_rule_map.key(i)->lhs;
262 impl->chain_rule_map.insert(chain_rule_table + chain_rule_count,0);
264 { non_term_to_tree[lhs] = t;
265 return chain_rule_table[ chain_rule_count++ ].lhs = lhs;
267 NonTerminal T = non_terminal_count++;
268 non_term_to_tree[T] = t;
269 return chain_rule_table[ chain_rule_count++ ].lhs = T;
273 chain_rule_table[ chain_rule_count ].rhs = v;
274 chain_rule_table[ chain_rule_count ].cost = cost;
275 chain_rule_table[ chain_rule_count ].rule = r;
276 Ix i = impl->chain_rule_map.lookup(chain_rule_table + chain_rule_count);
278 return impl->chain_rule_map.key(i)->lhs;
280 impl->chain_rule_map.insert(chain_rule_table + chain_rule_count,0);
282 { non_term_to_tree[lhs] = t;
283 return chain_rule_table[ chain_rule_count++ ].lhs = lhs;
285 NonTerminal T = v; // non_terminal_count++;
286 non_term_to_tree[T] = t;
287 return chain_rule_table[ chain_rule_count++ ].lhs = T;
290 case _: assert("Error in BURS_RuleSet::add_reduction\n");
295 //////////////////////////////////////////////////////////////////////////////
299 //////////////////////////////////////////////////////////////////////////////
301 //////////////////////////////////////////////////////////////////////////////
303 // Print a leaf reduction rule
305 //////////////////////////////////////////////////////////////////////////////
306 ostream& BURS_RuleSet::print (ostream& f, const BURS_RuleSet::LeafReduction& r) const
307 { G.print_variable(f, r.lhs);
309 G.print_functor (f, r.f);
310 if (r.cost > 0) f << "\t(" << r.cost << ')';
314 //////////////////////////////////////////////////////////////////////////////
316 // Print a reduction rule
318 //////////////////////////////////////////////////////////////////////////////
319 ostream& BURS_RuleSet::print (ostream& f, const BURS_RuleSet::Reduction& r) const
320 { G.print_variable(f, r.lhs);
322 const char * f_name = G.functor_name(r.f);
323 if (f_name[0] == '#')
324 { char begin_s = f_name[1];
325 char end_s = f_name[strlen(f_name)-1];
327 for (int i = 0; i < r.n; i++) {
329 if (i < r.n - 1) f << " ... ";
333 { G.print_functor (f, r.f);
335 for (int i = 0; i < r.n; i++) {
337 if (i < r.n - 1) f << ',';
341 if (r.cost > 0) f << "\t(" << r.cost << ')';
345 //////////////////////////////////////////////////////////////////////////////
347 // Print a chain rule
349 //////////////////////////////////////////////////////////////////////////////
350 ostream& BURS_RuleSet::print (ostream& f, const BURS_RuleSet::ChainRule& r) const
351 { G.print_variable(f,r.lhs);
354 if (r.cost > 0) f << "\t(" << r.cost << ')';
358 //////////////////////////////////////////////////////////////////////////////
362 //////////////////////////////////////////////////////////////////////////////
363 ostream& operator <<(ostream& f, const BURS_RuleSet& r)
365 for (i = 0; i < r.number_of_leaf_reductions(); i++)
366 r.print(f,r.leaf(i)) << '\n';
367 for (i = 0; i < r.number_of_reductions(); i++)
368 r.print(f,r.reduction(i)) << '\n';
369 for (i = 0; i < r.number_of_chain_rules(); i++)
370 r.print(f,r.chain_rule(i)) << '\n';
374 //////////////////////////////////////////////////////////////////////////////
376 // Print a non-terminal
378 //////////////////////////////////////////////////////////////////////////////
379 ostream& BURS_RuleSet::print (ostream& f, NonTerminal n) const
380 { return G.print(f,non_term_to_tree[n]); }