1324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver/*
2324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * [The "BSD license"]
3324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  Copyright (c) 2010 Terence Parr
4324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  All rights reserved.
5324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *
6324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  Redistribution and use in source and binary forms, with or without
7324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  modification, are permitted provided that the following conditions
8324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  are met:
9324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  1. Redistributions of source code must retain the above copyright
10324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *      notice, this list of conditions and the following disclaimer.
11324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  2. Redistributions in binary form must reproduce the above copyright
12324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *      notice, this list of conditions and the following disclaimer in the
13324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *      documentation and/or other materials provided with the distribution.
14324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  3. The name of the author may not be used to endorse or promote products
15324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *      derived from this software without specific prior written permission.
16324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *
17324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */
28324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverpackage org.antlr.tool;
29324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
30324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.analysis.DFA;
31324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.analysis.NFAState;
32324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.grammar.v3.ANTLRParser;
33324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.misc.IntSet;
34324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.misc.Interval;
35324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.runtime.CommonToken;
36324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.runtime.Token;
37324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.runtime.TokenSource;
38324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.runtime.tree.CommonTree;
39324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.runtime.tree.Tree;
40324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.runtime.tree.TreeAdaptor;
41324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.stringtemplate.v4.ST;
42324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.omg.PortableInterceptor.ORBInitInfoPackage.DuplicateName;
43324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
44324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport java.util.*;
45324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
46324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver/** Grammars are first converted to ASTs using this class and then are
47324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  converted to NFAs via a tree walker.
48324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *
49324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  The reader may notice that I have made a very non-OO decision in this
50324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  class to track variables for many different kinds of nodes.  It wastes
51324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  space for nodes that don't need the values and OO principles cry out
52324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  for a new class type for each kind of node in my tree.  I am doing this
53324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  on purpose for a variety of reasons.  I don't like using the type
54324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  system for different node types; it yields too many damn class files
55324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  which I hate.  Perhaps if I put them all in one file.  Most importantly
56324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  though I hate all the type casting that would have to go on.  I would
57324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  have all sorts of extra work to do.  Ick.  Anyway, I'm doing all this
58324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  on purpose, not out of ignorance. ;)
59324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */
60324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverpublic class GrammarAST extends CommonTree {
61324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	static int count = 0;
62324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
63324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public int ID = ++count;
64324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
65324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	private String textOverride;
66324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
67324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public String enclosingRuleName;
68324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
69324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    /** If this is a decision node, what is the lookahead DFA? */
70324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public DFA lookaheadDFA = null;
71324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
72324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    /** What NFA start state was built from this node? */
73324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public NFAState NFAStartState = null;
74324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
75324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** This is used for TREE_BEGIN nodes to point into
76324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  the NFA.  TREE_BEGINs point at left edge of DOWN for LOOK computation
77324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     *  purposes (Nullable tree child list needs special code gen when matching).
78324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
79324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public NFAState NFATreeDownState = null;
80324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
81324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Rule ref nodes, token refs, set, and NOT set refs need to track their
82324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  location in the generated NFA so that local FOLLOW sets can be
83324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  computed during code gen for automatic error recovery.
84324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
85324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public NFAState followingNFAState = null;
86324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
87324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** If this is a SET node, what are the elements? */
88324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    protected IntSet setValue = null;
89324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
90324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    /** If this is a BLOCK node, track options here */
91324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    protected Map<String,Object> blockOptions;
92324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
93324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** If this is a BLOCK node for a rewrite rule, track referenced
94324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  elements here.  Don't track elements in nested subrules.
95324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
96324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public Set<GrammarAST> rewriteRefsShallow;
97324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
98324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/*	If REWRITE node, track EVERY element and label ref to right of ->
99324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  for this rewrite rule.  There could be multiple of these per
100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  rule:
101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *
102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *     a : ( ... -> ... | ... -> ... ) -> ... ;
103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *
104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  We may need a list of all refs to do definitions for whole rewrite
105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  later.
106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *
107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  If BLOCK then tracks every element at that level and below.
108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public Set<GrammarAST> rewriteRefsDeep;
110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public Map<String,Object> terminalOptions;
112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** if this is an ACTION node, this is the outermost enclosing
114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  alt num in rule.  For actions, define.g sets these (used to
115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  be codegen.g).  We need these set so we can examine actions
116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  early, before code gen, for refs to rule predefined properties
117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  and rule labels.  For most part define.g sets outerAltNum, but
118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  codegen.g does the ones for %foo(a={$ID.text}) type refs as
119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  the {$ID...} is not seen as an action until code gen pulls apart.
120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public int outerAltNum;
122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** if this is a TOKEN_REF or RULE_REF node, this is the code ST
124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  generated for this node.  We need to update it later to add
125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  a label if someone does $tokenref or $ruleref in an action.
126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public ST code;
128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    /**
130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     *
131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     * @return
132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     */
133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public Map<String, Object> getBlockOptions() {
134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return blockOptions;
135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    /**
138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     *
139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     * @param blockOptions
140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver     */
141324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public void setBlockOptions(Map<String, Object> blockOptions) {
142324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        this.blockOptions = blockOptions;
143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public GrammarAST() {;}
146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
147324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public GrammarAST(int t, String txt) {
148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		initialize(t,txt);
149324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
150324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
151324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public GrammarAST(Token token) {
152324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		initialize(token);
153324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
154324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
155324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public void initialize(int i, String s) {
156324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        token = new CommonToken(i,s);
157324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		token.setTokenIndex(-1);
158324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
159324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
160324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public void initialize(Tree ast) {
161324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		GrammarAST t = ((GrammarAST)ast);
162324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		this.startIndex = t.startIndex;
163324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		this.stopIndex = t.stopIndex;
164324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		this.token = t.token;
165324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		this.enclosingRuleName = t.enclosingRuleName;
166324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		this.setValue = t.setValue;
167324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		this.blockOptions = t.blockOptions;
168324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		this.outerAltNum = t.outerAltNum;
169324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
170324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
171324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public void initialize(Token token) {
172324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        this.token = token;
173324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( token!=null ) {
174324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			startIndex = token.getTokenIndex();
175324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			stopIndex = startIndex;
176324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
177324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
178324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
179324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public DFA getLookaheadDFA() {
180324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return lookaheadDFA;
181324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
182324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
183324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public void setLookaheadDFA(DFA lookaheadDFA) {
184324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        this.lookaheadDFA = lookaheadDFA;
185324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
186324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
187324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public NFAState getNFAStartState() {
188324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return NFAStartState;
189324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
190324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
191324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public void setNFAStartState(NFAState nfaStartState) {
192324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		this.NFAStartState = nfaStartState;
193324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
194324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
195324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Save the option key/value pair and process it; return the key
196324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  or null if invalid option.
197324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
198324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public String setBlockOption(Grammar grammar, String key, Object value) {
199324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( blockOptions == null ) {
200324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			blockOptions = new HashMap();
201324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
202324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return setOption(blockOptions, Grammar.legalBlockOptions, grammar, key, value);
203324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
204324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
205324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public String setTerminalOption(Grammar grammar, String key, Object value) {
206324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( terminalOptions == null ) {
207324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			terminalOptions = new HashMap<String,Object>();
208324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
209324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return setOption(terminalOptions, Grammar.legalTokenOptions, grammar, key, value);
210324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
211324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
212324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public String setOption(Map options, Set legalOptions, Grammar grammar, String key, Object value) {
213324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( !legalOptions.contains(key) ) {
214324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ErrorManager.grammarError(ErrorManager.MSG_ILLEGAL_OPTION,
215324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver									  grammar,
216324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver									  token,
217324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver									  key);
218324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return null;
219324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
220324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( value instanceof String ) {
221324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			String vs = (String)value;
222324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( vs.charAt(0)=='"' ) {
223324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				value = vs.substring(1,vs.length()-1); // strip quotes
224324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
225324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
226324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( key.equals("k") ) {
227324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			grammar.numberOfManualLookaheadOptions++;
228324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
229324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if ( key.equals("backtrack") && value.toString().equals("true") ) {
230324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            grammar.composite.getRootGrammar().atLeastOneBacktrackOption = true;
231324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
232324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        options.put(key, value);
233324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return key;
234324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
235324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
236324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public Object getBlockOption(String key) {
237324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Object value = null;
238324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( blockOptions != null ) {
239324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			value = blockOptions.get(key);
240324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
241324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return value;
242324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
243324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
244324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public void setOptions(Grammar grammar, Map options) {
245324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( options==null ) {
246324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			this.blockOptions = null;
247324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return;
248324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
249324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String[] keys = (String[])options.keySet().toArray(new String[options.size()]);
250324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		for (String optionName : keys) {
251324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			String stored= setBlockOption(grammar, optionName, options.get(optionName));
252324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( stored==null ) {
253324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				options.remove(optionName);
254324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
255324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
256324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
257324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
258324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @Override
259324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public String getText() {
260324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( textOverride!=null ) return textOverride;
261324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if ( token!=null ) {
262324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            return token.getText();
263324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
264324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return "";
265324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
266324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
267324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public void setType(int type) {
268324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		token.setType(type);
269324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
270324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
271324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public void setText(String text) {
272324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		textOverride = text; // don't alt tokens as others might see
273324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
274324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
275324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @Override
276324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public int getType() {
277324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if ( token!=null ) {
278324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            return token.getType();
279324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
280324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return -1;
281324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
282324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
283324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @Override
284324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public int getLine() {
285324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		int line=0;
286324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if ( token!=null ) {
287324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            line = token.getLine();
288324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
289324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( line==0 ) {
290324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			Tree child = getChild(0);
291324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( child!=null ) {
292324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				line = child.getLine();
293324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
294324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
295324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return line;
296324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
297324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
298324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @Override
299324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public int getCharPositionInLine(){
300324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		int col=0;
301324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if ( token!=null ) {
302324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            col = token.getCharPositionInLine();
303324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
304324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( col==0 ) {
305324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			Tree child = getChild(0);
306324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( child!=null ) {
307324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				col = child.getCharPositionInLine();
308324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
309324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
310324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return col;
311324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
312324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
313324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public void setLine(int line) {
314324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        token.setLine(line);
315324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
316324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
317324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public void setCharPositionInLine(int value){
318324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        token.setCharPositionInLine(value);
319324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
320324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
321324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver 	public IntSet getSetValue() {
322324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return setValue;
323324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
324324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
325324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public void setSetValue(IntSet setValue) {
326324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        this.setValue = setValue;
327324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
328324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
329324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public GrammarAST getLastChild() {
330324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if (getChildCount() == 0)
331324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            return null;
332324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return (GrammarAST)getChild(getChildCount() - 1);
333324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
334324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
335324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public GrammarAST getNextSibling() {
336324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return (GrammarAST)getParent().getChild(getChildIndex() + 1);
337324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
338324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
339324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public GrammarAST getLastSibling() {
340324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        Tree parent = getParent();
341324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if ( parent==null ) {
342324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            return null;
343324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
344324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return (GrammarAST)parent.getChild(parent.getChildCount() - 1);
345324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
346324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
347324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
348324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public GrammarAST[] getChildrenAsArray() {
349324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return (GrammarAST[])getChildren().toArray(new GrammarAST[getChildCount()]);
350324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
351324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
352324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    private static final GrammarAST DescendantDownNode = new GrammarAST(Token.DOWN, "DOWN");
353324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    private static final GrammarAST DescendantUpNode = new GrammarAST(Token.UP, "UP");
354324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
355324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public static List<Tree> descendants(Tree root){
356324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return descendants(root, false);
357324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
358324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
359324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public static List<Tree> descendants(Tree root, boolean insertDownUpNodes){
360324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        List<Tree> result = new ArrayList<Tree>();
361324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        int count = root.getChildCount();
362324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
363324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if (insertDownUpNodes){
364324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            result.add(root);
365324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            result.add(DescendantDownNode);
366324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
367324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            for (int i = 0 ; i < count ; i++){
368324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                Tree child = root.getChild(i);
369324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                for (Tree subchild : descendants(child, true))
370324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    result.add(subchild);
371324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
372324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
373324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            result.add(DescendantUpNode);
374324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }else{
375324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            result.add(root);
376324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            for (int i = 0 ; i < count ; i++){
377324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                Tree child = root.getChild(i);
378324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                for (Tree subchild : descendants(child, false))
379324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                    result.add(subchild);
380324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            }
381324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
382324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
383324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return result;
384324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
385324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
386324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public GrammarAST findFirstType(int ttype) {
387324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// check this node (the root) first
388324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( this.getType()==ttype ) {
389324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return this;
390324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
391324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// else check children
392324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		List<Tree> descendants = descendants(this);
393324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		for (Tree child : descendants) {
394324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( child.getType()==ttype ) {
395324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				return (GrammarAST)child;
396324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
397324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
398324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return null;
399324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
400324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
401324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public List<GrammarAST> findAllType(int ttype) {
402324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		List<GrammarAST> nodes = new ArrayList<GrammarAST>();
403324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		_findAllType(ttype, nodes);
404324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return nodes;
405324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
406324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
407324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public void _findAllType(int ttype, List<GrammarAST> nodes) {
408324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// check this node (the root) first
409324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( this.getType()==ttype ) nodes.add(this);
410324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// check children
411324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		for (int i = 0; i < getChildCount(); i++){
412324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			GrammarAST child = (GrammarAST)getChild(i);
413324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			child._findAllType(ttype, nodes);
414324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
415324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
416324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
417324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    /** Make nodes unique based upon Token so we can add them to a Set; if
418324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  not a GrammarAST, check type.
419324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
420324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	@Override
421324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public boolean equals(Object ast) {
422324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( this == ast ) {
423324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return true;
424324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
425324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( !(ast instanceof GrammarAST) ) {
426324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return this.getType() == ((Tree)ast).getType();
427324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
428324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		GrammarAST t = (GrammarAST)ast;
429324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return token.getLine() == t.getLine() &&
430324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			   token.getCharPositionInLine() == t.getCharPositionInLine();
431324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
432324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
433324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    /** Make nodes unique based upon Token so we can add them to a Set; if
434324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  not a GrammarAST, check type.
435324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
436324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @Override
437324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public int hashCode(){
438324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if (token == null)
439324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            return 0;
440324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
441324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return token.hashCode();
442324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
443324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
444324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** See if tree has exact token types and structure; no text */
445324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public boolean hasSameTreeStructure(Tree other) {
446324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// check roots first.
447324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if (this.getType() != other.getType()) return false;
448324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// if roots match, do full list match test on children.
449324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Iterator<Tree> thisDescendants = descendants(this, true).iterator();
450324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Iterator<Tree> otherDescendants = descendants(other, true).iterator();
451324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		while (thisDescendants.hasNext()) {
452324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if (!otherDescendants.hasNext())
453324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				return false;
454324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if (thisDescendants.next().getType() != otherDescendants.next().getType())
455324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				return false;
456324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
457324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return !otherDescendants.hasNext();
458324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
459324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
460324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public static GrammarAST dup(Tree t) {
461324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( t==null ) {
462324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return null;
463324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
464324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		GrammarAST dup_t = new GrammarAST();
465324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		dup_t.initialize(t);
466324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return dup_t;
467324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
468324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
469324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    @Override
470324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    public Tree dupNode(){
471324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        return dup(this);
472324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver    }
473324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
474324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/**Duplicate a tree, assuming this is a root node of a tree--
475324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 * duplicate that node and what's below; ignore siblings of root node.
476324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
477324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public static GrammarAST dupTreeNoActions(GrammarAST t, GrammarAST parent) {
478324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( t==null ) {
479324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return null;
480324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
481324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		GrammarAST result = (GrammarAST)t.dupNode();
482324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		for (GrammarAST subchild : getChildrenForDupTree(t)) {
483324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			result.addChild(dupTreeNoActions(subchild, result));
484324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
485324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return result;
486324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
487324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
488324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	private static List<GrammarAST> getChildrenForDupTree(GrammarAST t) {
489324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		List<GrammarAST> result = new ArrayList<GrammarAST>();
490324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		for (int i = 0; i < t.getChildCount(); i++){
491324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			GrammarAST child = (GrammarAST)t.getChild(i);
492324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			int ttype = child.getType();
493324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if (ttype == ANTLRParser.REWRITES || ttype == ANTLRParser.REWRITE || ttype==ANTLRParser.ACTION) {
494324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				continue;
495324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
496324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
497324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if (ttype == ANTLRParser.BANG || ttype == ANTLRParser.ROOT) {
498324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				for (GrammarAST subchild : getChildrenForDupTree(child))
499324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					result.add(subchild);
500324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			} else {
501324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				result.add(child);
502324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
503324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
504324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( result.size()==1 && result.get(0).getType()==ANTLRParser.EOA &&
505324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			 t.getType()==ANTLRParser.ALT )
506324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		{
507324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			// can't have an empty alt, insert epsilon
508324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			result.add(0, new GrammarAST(ANTLRParser.EPSILON, "epsilon"));
509324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
510324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
511324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return result;
512324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
513324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
514324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public static GrammarAST dupTree(GrammarAST t) {
515324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( t==null ) {
516324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return null;
517324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
518324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		GrammarAST root = dup(t);		// make copy of root
519324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// copy all children of root.
520324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		for (int i= 0; i < t.getChildCount(); i++) {
521324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			GrammarAST child = (GrammarAST)t.getChild(i);
522324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			root.addChild(dupTree(child));
523324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
524324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return root;
525324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
526324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
527324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public void setTreeEnclosingRuleNameDeeply(String rname) {
528324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		enclosingRuleName = rname;
529324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if (getChildCount() == 0) return;
530324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		for (Object child : getChildren()) {
531324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if (!(child instanceof GrammarAST)) {
532324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				continue;
533324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
534324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			GrammarAST grammarAST = (GrammarAST)child;
535324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			grammarAST.setTreeEnclosingRuleNameDeeply(rname);
536324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
537324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
538324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
539324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	String toStringList() {
540324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return "";
541324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
542324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
543324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Track start/stop token for subtree root created for a rule.
544324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  Only works with Tree nodes.  For rules that match nothing,
545324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  seems like this will yield start=i and stop=i-1 in a nil node.
546324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  Might be useful info so I'll not force to be i..i.
547324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
548324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public void setTokenBoundaries(Token startToken, Token stopToken) {
549324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( startToken!=null ) startIndex = startToken.getTokenIndex();
550324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( stopToken!=null ) stopIndex = stopToken.getTokenIndex();
551324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
552324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
553324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public GrammarAST getBlockALT(int i) {
554324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( this.getType()!=ANTLRParser.BLOCK ) return null;
555324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		int alts = 0;
556324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		for (int j =0 ; j < getChildCount(); j++) {
557324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if (getChild(j).getType() == ANTLRParser.ALT) {
558324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				alts++;
559324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
560324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if (alts == i) {
561324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				return (GrammarAST)getChild(j);
562324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
563324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
564324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return null;
565324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
566324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
567