• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * [The "BSD license"]
3  *  Copyright (c) 2010 Terence Parr
4  *  All rights reserved.
5  *
6  *  Redistribution and use in source and binary forms, with or without
7  *  modification, are permitted provided that the following conditions
8  *  are met:
9  *  1. Redistributions of source code must retain the above copyright
10  *      notice, this list of conditions and the following disclaimer.
11  *  2. Redistributions in binary form must reproduce the above copyright
12  *      notice, this list of conditions and the following disclaimer in the
13  *      documentation and/or other materials provided with the distribution.
14  *  3. The name of the author may not be used to endorse or promote products
15  *      derived from this software without specific prior written permission.
16  *
17  *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */package org.antlr.tool;
28 
29 import org.antlr.analysis.Label;
30 import org.antlr.analysis.NFAState;
31 import org.antlr.grammar.v3.ANTLRParser;
32 import org.antlr.grammar.v3.AssignTokenTypesWalker;
33 import org.antlr.misc.Utils;
34 import org.antlr.runtime.RecognitionException;
35 import org.antlr.runtime.tree.CommonTreeNodeStream;
36 
37 import java.util.ArrayList;
38 import java.util.HashSet;
39 import java.util.Iterator;
40 import java.util.LinkedHashMap;
41 import java.util.List;
42 import java.util.Map;
43 import java.util.Set;
44 import java.util.Vector;
45 
46 /** A tree of component (delegate) grammars.
47  *
48  *  Rules defined in delegates are "inherited" like multi-inheritance
49  *  so you can override them.  All token types must be consistent across
50  *  rules from all delegate grammars, so they must be stored here in one
51  *  central place.
52  *
53  *  We have to start out assuming a composite grammar situation as we can't
54  *  look into the grammar files a priori to see if there is a delegate
55  *  statement.  Because of this, and to avoid duplicating token type tracking
56  *  in each grammar, even single noncomposite grammars use one of these objects
57  *  to track token types.
58  */
59 public class CompositeGrammar {
60 	public static final int MIN_RULE_INDEX = 1;
61 
62 	public CompositeGrammarTree delegateGrammarTreeRoot;
63 
64 	/** Used during getRuleReferenceClosure to detect computation cycles */
65 	protected Set<NFAState> refClosureBusy = new HashSet<NFAState>();
66 
67 	/** Used to assign state numbers; all grammars in composite share common
68 	 *  NFA space.  This NFA tracks state numbers number to state mapping.
69 	 */
70 	public int stateCounter = 0;
71 
72 	/** The NFA states in the NFA built from rules across grammars in composite.
73 	 *  Maps state number to NFAState object.
74 	 *  This is a Vector instead of a List because I need to be able to grow
75 	 *  this properly.  After talking to Josh Bloch, Collections guy at Sun,
76 	 *  I decided this was easiest solution.
77 	 */
78 	protected Vector<NFAState> numberToStateList = new Vector<NFAState>(1000);
79 
80 	/** Token names and literal tokens like "void" are uniquely indexed.
81 	 *  with -1 implying EOF.  Characters are different; they go from
82 	 *  -1 (EOF) to \uFFFE.  For example, 0 could be a binary byte you
83 	 *  want to lexer.  Labels of DFA/NFA transitions can be both tokens
84 	 *  and characters.  I use negative numbers for bookkeeping labels
85 	 *  like EPSILON. Char/String literals and token types overlap in the same
86 	 *  space, however.
87 	 */
88 	protected int maxTokenType = Label.MIN_TOKEN_TYPE-1;
89 
90 	/** Map token like ID (but not literals like "while") to its token type */
91 	public Map<String, Integer> tokenIDToTypeMap = new LinkedHashMap<String, Integer>();
92 
93 	/** Map token literals like "while" to its token type.  It may be that
94 	 *  WHILE="while"=35, in which case both tokenIDToTypeMap and this
95 	 *  field will have entries both mapped to 35.
96 	 */
97 	public Map<String, Integer> stringLiteralToTypeMap = new LinkedHashMap<String, Integer>();
98 	/** Reverse index for stringLiteralToTypeMap */
99 	public Vector<String> typeToStringLiteralList = new Vector<String>();
100 
101 	/** Map a token type to its token name.
102 	 *  Must subtract MIN_TOKEN_TYPE from index.
103 	 */
104 	public Vector<String> typeToTokenList = new Vector<String>();
105 
106 	/** If combined or lexer grammar, track the rules.
107 	 * 	Track lexer rules so we can warn about undefined tokens.
108 	 *  This is combined set of lexer rules from all lexer grammars
109 	 *  seen in all imports.
110 	 */
111 	protected Set<String> lexerRules = new HashSet<String>();
112 
113 	/** Rules are uniquely labeled from 1..n among all grammars */
114 	protected int ruleIndex = MIN_RULE_INDEX;
115 
116 	/** Map a rule index to its name; use a Vector on purpose as new
117 	 *  collections stuff won't let me setSize and make it grow.  :(
118 	 *  I need a specific guaranteed index, which the Collections stuff
119 	 *  won't let me have.
120 	 */
121 	protected Vector<Rule> ruleIndexToRuleList = new Vector<Rule>();
122 
123 	public boolean watchNFAConversion = false;
124 
initTokenSymbolTables()125 	protected void initTokenSymbolTables() {
126 		// the faux token types take first NUM_FAUX_LABELS positions
127 		// then we must have room for the predefined runtime token types
128 		// like DOWN/UP used for tree parsing.
129 		typeToTokenList.setSize(Label.NUM_FAUX_LABELS+Label.MIN_TOKEN_TYPE-1);
130 		typeToTokenList.set(Label.NUM_FAUX_LABELS+Label.INVALID, "<INVALID>");
131 		typeToTokenList.set(Label.NUM_FAUX_LABELS+Label.EOT, "<EOT>");
132 		typeToTokenList.set(Label.NUM_FAUX_LABELS+Label.SEMPRED, "<SEMPRED>");
133 		typeToTokenList.set(Label.NUM_FAUX_LABELS+Label.SET, "<SET>");
134 		typeToTokenList.set(Label.NUM_FAUX_LABELS+Label.EPSILON, Label.EPSILON_STR);
135 		typeToTokenList.set(Label.NUM_FAUX_LABELS+Label.EOF, "EOF");
136 		typeToTokenList.set(Label.NUM_FAUX_LABELS+Label.EOR_TOKEN_TYPE-1, "<EOR>");
137 		typeToTokenList.set(Label.NUM_FAUX_LABELS+Label.DOWN-1, "DOWN");
138 		typeToTokenList.set(Label.NUM_FAUX_LABELS+Label.UP-1, "UP");
139 		tokenIDToTypeMap.put("<INVALID>", Utils.integer(Label.INVALID));
140 		tokenIDToTypeMap.put("<EOT>", Utils.integer(Label.EOT));
141 		tokenIDToTypeMap.put("<SEMPRED>", Utils.integer(Label.SEMPRED));
142 		tokenIDToTypeMap.put("<SET>", Utils.integer(Label.SET));
143 		tokenIDToTypeMap.put("<EPSILON>", Utils.integer(Label.EPSILON));
144 		tokenIDToTypeMap.put("EOF", Utils.integer(Label.EOF));
145 		tokenIDToTypeMap.put("<EOR>", Utils.integer(Label.EOR_TOKEN_TYPE));
146 		tokenIDToTypeMap.put("DOWN", Utils.integer(Label.DOWN));
147 		tokenIDToTypeMap.put("UP", Utils.integer(Label.UP));
148 	}
149 
150 	@SuppressWarnings("OverridableMethodCallInConstructor")
CompositeGrammar()151 	public CompositeGrammar() {
152 		initTokenSymbolTables();
153 	}
154 
155 	@SuppressWarnings("OverridableMethodCallInConstructor")
CompositeGrammar(Grammar g)156 	public CompositeGrammar(Grammar g) {
157 		this();
158 		setDelegationRoot(g);
159 	}
160 
setDelegationRoot(Grammar root)161 	public void setDelegationRoot(Grammar root) {
162 		delegateGrammarTreeRoot = new CompositeGrammarTree(root);
163 		root.compositeTreeNode = delegateGrammarTreeRoot;
164 	}
165 
getRule(String ruleName)166 	public Rule getRule(String ruleName) {
167 		return delegateGrammarTreeRoot.getRule(ruleName);
168 	}
169 
getOption(String key)170 	public Object getOption(String key) {
171 		return delegateGrammarTreeRoot.getOption(key);
172 	}
173 
174 	/** Add delegate grammar as child of delegator */
addGrammar(Grammar delegator, Grammar delegate)175 	public void addGrammar(Grammar delegator, Grammar delegate) {
176 		if ( delegator.compositeTreeNode==null ) {
177 			delegator.compositeTreeNode = new CompositeGrammarTree(delegator);
178 		}
179 		delegator.compositeTreeNode.addChild(new CompositeGrammarTree(delegate));
180 
181 		/*// find delegator in tree so we can add a child to it
182 		CompositeGrammarTree t = delegateGrammarTreeRoot.findNode(delegator);
183 		t.addChild();
184 		*/
185 		// make sure new grammar shares this composite
186 		delegate.composite = this;
187 	}
188 
189 	/** Get parent of this grammar */
getDelegator(Grammar g)190 	public Grammar getDelegator(Grammar g) {
191 		CompositeGrammarTree me = delegateGrammarTreeRoot.findNode(g);
192 		if ( me==null ) {
193 			return null; // not found
194 		}
195 		if ( me.parent!=null ) {
196 			return me.parent.grammar;
197 		}
198 		return null;
199 	}
200 
201 	/** Get list of all delegates from all grammars in the delegate subtree of g.
202 	 *  The grammars are in delegation tree preorder.  Don't include g itself
203 	 *  in list as it is not a delegate of itself.
204 	 */
getDelegates(Grammar g)205 	public List<Grammar> getDelegates(Grammar g) {
206 		CompositeGrammarTree t = delegateGrammarTreeRoot.findNode(g);
207 		if ( t==null ) {
208 			return null; // no delegates
209 		}
210 		List<Grammar> grammars = t.getPostOrderedGrammarList();
211 		grammars.remove(grammars.size()-1); // remove g (last one)
212 		return grammars;
213 	}
214 
getDirectDelegates(Grammar g)215 	public List<Grammar> getDirectDelegates(Grammar g) {
216 		CompositeGrammarTree t = delegateGrammarTreeRoot.findNode(g);
217 		List<CompositeGrammarTree> children = t.children;
218 		if ( children==null ) {
219 			return null;
220 		}
221 		List<Grammar> grammars = new ArrayList<Grammar>();
222 		for (int i = 0; children!=null && i < children.size(); i++) {
223 			CompositeGrammarTree child = children.get(i);
224 			grammars.add(child.grammar);
225 		}
226 		return grammars;
227 	}
228 
229 	/** Get delegates below direct delegates of g */
getIndirectDelegates(Grammar g)230 	public List<Grammar> getIndirectDelegates(Grammar g) {
231 		List<Grammar> direct = getDirectDelegates(g);
232 		List<Grammar> delegates = getDelegates(g);
233 		if ( direct!=null ) {
234 			delegates.removeAll(direct);
235 		}
236 		return delegates;
237 	}
238 
239 	/** Return list of delegate grammars from root down to g.
240 	 *  Order is root, ..., g.parent.  (g not included).
241 	 */
getDelegators(Grammar g)242 	public List<Grammar> getDelegators(Grammar g) {
243 		if ( g==delegateGrammarTreeRoot.grammar ) {
244 			return null;
245 		}
246 		List<Grammar> grammars = new ArrayList<Grammar>();
247 		CompositeGrammarTree t = delegateGrammarTreeRoot.findNode(g);
248 		// walk backwards to root, collecting grammars
249 		CompositeGrammarTree p = t.parent;
250 		while ( p!=null ) {
251 			grammars.add(0, p.grammar); // add to head so in order later
252 			p = p.parent;
253 		}
254 		return grammars;
255 	}
256 
257 	/** Get set of rules for grammar g that need to have manual delegation
258 	 *  methods.  This is the list of rules collected from all direct/indirect
259 	 *  delegates minus rules overridden in grammar g.
260 	 *
261 	 *  This returns null except for the delegate root because it is the only
262 	 *  one that has to have a complete grammar rule interface.  The delegates
263 	 *  should not be instantiated directly for use as parsers (you can create
264 	 *  them to pass to the root parser's ctor as arguments).
265 	 */
getDelegatedRules(Grammar g)266 	public Set<? extends Rule> getDelegatedRules(Grammar g) {
267 		if ( g!=delegateGrammarTreeRoot.grammar ) {
268 			return null;
269 		}
270 		Set<? extends Rule> rules = getAllImportedRules(g);
271 		for (Iterator<? extends Rule> it = rules.iterator(); it.hasNext();) {
272 			Rule r = it.next();
273 			Rule localRule = g.getLocallyDefinedRule(r.name);
274 			// if locally defined or it's not local but synpred, don't make
275 			// a delegation method
276 			if ( localRule!=null || r.isSynPred ) {
277 				it.remove(); // kill overridden rules
278 			}
279 		}
280 		return rules;
281 	}
282 
283 	/** Get all rule definitions from all direct/indirect delegate grammars
284 	 *  of g.
285 	 */
getAllImportedRules(Grammar g)286 	public Set<? extends Rule> getAllImportedRules(Grammar g) {
287 		Set<String> ruleNames = new HashSet<String>();
288 		Set<Rule> rules = new HashSet<Rule>();
289 		CompositeGrammarTree subtreeRoot = delegateGrammarTreeRoot.findNode(g);
290 
291 		List<Grammar> grammars = subtreeRoot.getPreOrderedGrammarList();
292 		// walk all grammars preorder, priority given to grammar listed first.
293 		for (int i = 0; i < grammars.size(); i++) {
294 			Grammar delegate = grammars.get(i);
295 			// for each rule in delegate, add to rules if no rule with that
296 			// name as been seen.  (can't use removeAll; wrong hashcode/equals on Rule)
297 			for (Rule r : delegate.getRules()) {
298 				if ( !ruleNames.contains(r.name) ) {
299 					ruleNames.add(r.name); // track that we've seen this
300 					rules.add(r);
301 				}
302 			}
303 		}
304 		return rules;
305 	}
306 
getRootGrammar()307 	public Grammar getRootGrammar() {
308 		if ( delegateGrammarTreeRoot==null ) {
309 			return null;
310 		}
311 		return delegateGrammarTreeRoot.grammar;
312 	}
313 
getGrammar(String grammarName)314 	public Grammar getGrammar(String grammarName) {
315 		CompositeGrammarTree t = delegateGrammarTreeRoot.findNode(grammarName);
316 		if ( t!=null ) {
317 			return t.grammar;
318 		}
319 		return null;
320 	}
321 
322 	// NFA spans multiple grammars, must handle here
323 
getNewNFAStateNumber()324 	public int getNewNFAStateNumber() {
325 		return stateCounter++;
326 	}
327 
addState(NFAState state)328 	public void addState(NFAState state) {
329 		numberToStateList.setSize(state.stateNumber+1); // make sure we have room
330 		numberToStateList.set(state.stateNumber, state);
331 	}
332 
getState(int s)333 	public NFAState getState(int s) {
334 		return numberToStateList.get(s);
335 	}
336 
assignTokenTypes()337 	public void assignTokenTypes() throws RecognitionException {
338 		// ASSIGN TOKEN TYPES for all delegates (same walker)
339 		//System.out.println("### assign types");
340 		AssignTokenTypesWalker ttypesWalker = new AssignTokenTypesBehavior();
341 		List<Grammar> grammars = delegateGrammarTreeRoot.getPostOrderedGrammarList();
342 		for (int i = 0; grammars!=null && i < grammars.size(); i++) {
343 			Grammar g = grammars.get(i);
344 			ttypesWalker.setTreeNodeStream(new CommonTreeNodeStream(g.getGrammarTree()));
345 			try {
346 				//System.out.println("    walking "+g.name);
347 				ttypesWalker.grammar_(g);
348 			}
349 			catch (RecognitionException re) {
350 				ErrorManager.error(ErrorManager.MSG_BAD_AST_STRUCTURE,
351 								   re);
352 			}
353 		}
354 		// the walker has filled literals, tokens, and alias tables.
355 		// now tell it to define them in the root grammar
356 		ttypesWalker.defineTokens(delegateGrammarTreeRoot.grammar);
357 	}
358 
translateLeftRecursiveRules()359 	public void translateLeftRecursiveRules() {
360 		List<Grammar> grammars = delegateGrammarTreeRoot.getPostOrderedGrammarList();
361 		for (int i = 0; grammars!=null && i < grammars.size(); i++) {
362 			Grammar g = grammars.get(i);
363 			if ( !(g.type==Grammar.PARSER || g.type==Grammar.COMBINED) ) continue;
364 			for (GrammarAST r : g.grammarTree.findAllType(ANTLRParser.RULE)) {
365 				if ( !Character.isUpperCase(r.getChild(0).getText().charAt(0)) ) {
366 					if ( LeftRecursiveRuleAnalyzer.hasImmediateRecursiveRuleRefs(r, r.enclosingRuleName) ) {
367 						g.translateLeftRecursiveRule(r);
368 					}
369 				}
370 			}
371 		}
372 	}
373 
defineGrammarSymbols()374 	public void defineGrammarSymbols() {
375 		delegateGrammarTreeRoot.trimLexerImportsIntoCombined();
376 		List<Grammar> grammars = delegateGrammarTreeRoot.getPostOrderedGrammarList();
377 		for (int i = 0; grammars!=null && i < grammars.size(); i++) {
378 			Grammar g = grammars.get(i);
379 			g.defineGrammarSymbols();
380 		}
381 		for (int i = 0; grammars!=null && i < grammars.size(); i++) {
382 			Grammar g = grammars.get(i);
383 			g.checkNameSpaceAndActions();
384 		}
385 		minimizeRuleSet();
386 	}
387 
createNFAs()388 	public void createNFAs() {
389 		if ( ErrorManager.doNotAttemptAnalysis() ) {
390 			return;
391 		}
392 		List<Grammar> grammars = delegateGrammarTreeRoot.getPostOrderedGrammarList();
393 		//System.out.println("### createNFAs for composite; grammars: "+names);
394 		for (int i = 0; grammars!=null && i < grammars.size(); i++) {
395 			Grammar g = grammars.get(i);
396 			g.createRuleStartAndStopNFAStates();
397 		}
398 		for (int i = 0; grammars!=null && i < grammars.size(); i++) {
399 			Grammar g = grammars.get(i);
400 			g.buildNFA();
401 		}
402 	}
403 
minimizeRuleSet()404 	public void minimizeRuleSet() {
405 		Set<String> ruleDefs = new HashSet<String>();
406 		_minimizeRuleSet(ruleDefs, delegateGrammarTreeRoot);
407 	}
408 
_minimizeRuleSet(Set<String> ruleDefs, CompositeGrammarTree p)409 	public void _minimizeRuleSet(Set<String> ruleDefs,
410 								 CompositeGrammarTree p) {
411 		Set<String> localRuleDefs = new HashSet<String>();
412 		Set<String> overrides = new HashSet<String>();
413 		// compute set of non-overridden rules for this delegate
414 		for (Rule r : p.grammar.getRules()) {
415 			if ( !ruleDefs.contains(r.name) ) {
416 				localRuleDefs.add(r.name);
417 			}
418 			else if ( !r.name.equals(Grammar.ARTIFICIAL_TOKENS_RULENAME) ) {
419 				// record any overridden rule 'cept tokens rule
420 				overrides.add(r.name);
421 			}
422 		}
423 		//System.out.println("rule defs for "+p.grammar.name+": "+localRuleDefs);
424 		//System.out.println("overridden rule for "+p.grammar.name+": "+overrides);
425 		p.grammar.overriddenRules = overrides;
426 
427 		// make set of all rules defined thus far walking delegation tree.
428 		// the same rule in two delegates resolves in favor of first found
429 		// in tree therefore second must not be included
430 		ruleDefs.addAll(localRuleDefs);
431 
432 		// pass larger set of defined rules to delegates
433 		if ( p.children!=null ) {
434 			for (CompositeGrammarTree delegate : p.children) {
435 				_minimizeRuleSet(ruleDefs, delegate);
436 			}
437 		}
438 	}
439 
440 	/*
441 	public void minimizeRuleSet() {
442 		Set<Rule> refs = _minimizeRuleSet(delegateGrammarTreeRoot);
443 		System.out.println("all rule refs: "+refs);
444 	}
445 
446 	public Set<Rule> _minimizeRuleSet(CompositeGrammarTree p) {
447 		Set<Rule> refs = new HashSet<Rule>();
448 		for (GrammarAST refAST : p.grammar.ruleRefs) {
449 			System.out.println("ref "+refAST.getText()+": "+refAST.NFAStartState+
450 							   " enclosing rule: "+refAST.NFAStartState.enclosingRule+
451 							   " invoking rule: "+((NFAState)refAST.NFAStartState.transition[0].target).enclosingRule);
452 			refs.add(((NFAState)refAST.NFAStartState.transition[0].target).enclosingRule);
453 		}
454 
455 		if ( p.children!=null ) {
456 			for (CompositeGrammarTree delegate : p.children) {
457 				Set<Rule> delegateRuleRefs = _minimizeRuleSet(delegate);
458 				refs.addAll(delegateRuleRefs);
459 			}
460 		}
461 
462 		return refs;
463 	}
464 	*/
465 
466 	/*
467 	public void oldminimizeRuleSet() {
468 		// first walk to remove all overridden rules
469 		Set<String> ruleDefs = new HashSet<String>();
470 		Set<String> ruleRefs = new HashSet<String>();
471 		for (GrammarAST refAST : delegateGrammarTreeRoot.grammar.ruleRefs) {
472 			String rname = refAST.getText();
473 			ruleRefs.add(rname);
474 		}
475 		_minimizeRuleSet(ruleDefs,
476 						 ruleRefs,
477 						 delegateGrammarTreeRoot);
478 		System.out.println("overall rule defs: "+ruleDefs);
479 	}
480 
481 	public void _minimizeRuleSet(Set<String> ruleDefs,
482 								 Set<String> ruleRefs,
483 								 CompositeGrammarTree p) {
484 		Set<String> localRuleDefs = new HashSet<String>();
485 		for (Rule r : p.grammar.getRules()) {
486 			if ( !ruleDefs.contains(r.name) ) {
487 				localRuleDefs.add(r.name);
488 				ruleDefs.add(r.name);
489 			}
490 		}
491 		System.out.println("rule defs for "+p.grammar.name+": "+localRuleDefs);
492 
493 		// remove locally-defined rules not in ref set
494 		// find intersection of local rules and references from delegator
495 		// that is set of rules needed by delegator
496 		Set<String> localRuleDefsSatisfyingRefsFromBelow = new HashSet<String>();
497 		for (String r : ruleRefs) {
498 			if ( localRuleDefs.contains(r) ) {
499 				localRuleDefsSatisfyingRefsFromBelow.add(r);
500 			}
501 		}
502 
503 		// now get list of refs from localRuleDefsSatisfyingRefsFromBelow.
504 		// Those rules are also allowed in this delegate
505 		for (GrammarAST refAST : p.grammar.ruleRefs) {
506 			if ( localRuleDefsSatisfyingRefsFromBelow.contains(refAST.enclosingRuleName) ) {
507 				// found rule ref within needed rule
508 			}
509 		}
510 
511 		// remove rule refs not in the new rule def set
512 
513 		// walk all children, adding rules not already defined
514 		if ( p.children!=null ) {
515 			for (CompositeGrammarTree delegate : p.children) {
516 				_minimizeRuleSet(ruleDefs, ruleRefs, delegate);
517 			}
518 		}
519 	}
520 	*/
521 
522 	/*
523 	public void trackNFAStatesThatHaveLabeledEdge(Label label,
524 												  NFAState stateWithLabeledEdge)
525 	{
526 		Set<NFAState> states = typeToNFAStatesWithEdgeOfTypeMap.get(label);
527 		if ( states==null ) {
528 			states = new HashSet<NFAState>();
529 			typeToNFAStatesWithEdgeOfTypeMap.put(label, states);
530 		}
531 		states.add(stateWithLabeledEdge);
532 	}
533 
534 	public Map<Label, Set<NFAState>> getTypeToNFAStatesWithEdgeOfTypeMap() {
535 		return typeToNFAStatesWithEdgeOfTypeMap;
536 	}
537 
538 	public Set<NFAState> getStatesWithEdge(Label label) {
539 		return typeToNFAStatesWithEdgeOfTypeMap.get(label);
540 	}
541 */
542 }
543