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.codegen;
29324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
30324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
31324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.Tool;
32324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.analysis.DFA;
33324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.analysis.*;
34324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.grammar.v3.ANTLRLexer;
35324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.grammar.v3.ANTLRParser;
36324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.grammar.v3.ActionTranslator;
37324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.grammar.v3.CodeGenTreeWalker;
38324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.misc.BitSet;
39324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.misc.*;
40324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.runtime.*;
41324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.runtime.tree.CommonTreeNodeStream;
42324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.antlr.tool.*;
43324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport org.stringtemplate.v4.*;
44324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
45324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport java.io.IOException;
46324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport java.io.Writer;
47324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverimport java.util.*;
48324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
49324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver/** ANTLR's code generator.
50324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *
51324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  Generate recognizers derived from grammars.  Language independence
52324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  achieved through the use of STGroup objects.  All output
53324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  strings are completely encapsulated in the group files such as Java.stg.
54324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  Some computations are done that are unused by a particular language.
55324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  This generator just computes and sets the values into the templates;
56324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  the templates are free to use or not use the information.
57324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *
58324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  To make a new code generation target, define X.stg for language X
59324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  by copying from existing Y.stg most closely releated to your language;
60324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  e.g., to do CSharp.stg copy Java.stg.  The template group file has a
61324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  bunch of templates that are needed by the code generator.  You can add
62324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  a new target w/o even recompiling ANTLR itself.  The language=X option
63324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  in a grammar file dictates which templates get loaded/used.
64324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *
65324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  Some language like C need both parser files and header files.  Java needs
66324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  to have a separate file for the cyclic DFA as ANTLR generates bytecodes
67324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  directly (which cannot be in the generated parser Java file).  To facilitate
68324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  this,
69324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *
70324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver * cyclic can be in same file, but header, output must be searpate.  recognizer
71324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver *  is in outptufile.
72324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver */
73324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruverpublic class CodeGenerator {
74324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** When generating SWITCH statements, some targets might need to limit
75324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  the size (based upon the number of case labels).  Generally, this
76324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  limit will be hit only for lexers where wildcard in a UNICODE
77324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  vocabulary environment would generate a SWITCH with 65000 labels.
78324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
79324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public final static int MSCL_DEFAULT = 300;
80324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public static int MAX_SWITCH_CASE_LABELS = MSCL_DEFAULT;
81324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public final static int MSA_DEFAULT = 3;
82324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public static int MIN_SWITCH_ALTS = MSA_DEFAULT;
83324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public boolean GENERATE_SWITCHES_WHEN_POSSIBLE = true;
84324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public static boolean LAUNCH_ST_INSPECTOR = false;
85324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public final static int MADSI_DEFAULT = 60; // do lots of states inline (needed for expression rules)
86324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public static int MAX_ACYCLIC_DFA_STATES_INLINE = MADSI_DEFAULT;
87324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
88324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public static String classpathTemplateRootDirectoryName =
89324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		"org/antlr/codegen/templates";
90324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
91324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Which grammar are we generating code for?  Each generator
92324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  is attached to a specific grammar.
93324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
94324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public Grammar grammar;
95324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
96324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** What language are we generating? */
97324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected String language;
98324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
99324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** The target specifies how to write out files and do other language
100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  specific actions.
101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public Target target = null;
103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Where are the templates this generator should use to generate code? */
105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected STGroup templates;
106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** The basic output templates without AST or templates stuff; this will be
108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  the templates loaded for the language such as Java.stg *and* the Dbg
109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  stuff if turned on.  This is used for generating syntactic predicates.
110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected STGroup baseTemplates;
112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected ST recognizerST;
114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected ST outputFileST;
115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected ST headerFileST;
116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Used to create unique labels */
118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected int uniqueLabelNumber = 1;
119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** A reference to the ANTLR tool so we can learn about output directories
121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  and such.
122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected Tool tool;
124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Generate debugging event method calls */
126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected boolean debug;
127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Create a Tracer object and make the recognizer invoke this. */
129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected boolean trace;
130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Track runtime parsing information about decisions etc...
132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  This requires the debugging event mechanism to work.
133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected boolean profile;
135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected int lineWidth = 72;
137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** I have factored out the generation of acyclic DFAs to separate class */
139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public ACyclicDFACodeGenerator acyclicDFAGenerator =
140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		new ACyclicDFACodeGenerator(this);
141324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
142324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** I have factored out the generation of cyclic DFAs to separate class */
143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/*
144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public CyclicDFACodeGenerator cyclicDFAGenerator =
145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		new CyclicDFACodeGenerator(this);
146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		*/
147324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public static final String VOCAB_FILE_EXTENSION = ".tokens";
149324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected final static String vocabFilePattern =
150324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		"<tokens:{it|<it.name>=<it.type>\n}>" +
151324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		"<literals:{it|<it.name>=<it.type>\n}>";
152324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
153324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public CodeGenerator(Tool tool, Grammar grammar, String language) {
154324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		this.tool = tool;
155324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		this.grammar = grammar;
156324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		this.language = language;
157324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		target = loadLanguageTarget(language);
158324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
159324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
160324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public static Target loadLanguageTarget(String language) {
161324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Target target = null;
162324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String targetName = "org.antlr.codegen."+language+"Target";
163324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		try {
164324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			Class c = Class.forName(targetName);
165324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			target = (Target)c.newInstance();
166324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
167324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		catch (ClassNotFoundException cnfe) {
168324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			target = new Target(); // use default
169324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
170324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		catch (InstantiationException ie) {
171324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ErrorManager.error(ErrorManager.MSG_CANNOT_CREATE_TARGET_GENERATOR,
172324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							   targetName,
173324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							   ie);
174324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
175324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		catch (IllegalAccessException cnfe) {
176324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ErrorManager.error(ErrorManager.MSG_CANNOT_CREATE_TARGET_GENERATOR,
177324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							   targetName,
178324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							   cnfe);
179324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
180324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return target;
181324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
182324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
183324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** load the main language.stg template group file */
184324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public void loadTemplates(String language) {
185324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String langDir = classpathTemplateRootDirectoryName+"/"+language;
186324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		STGroup coreTemplates = new STGroupFile(langDir+"/"+language+".stg");
187324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
188324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		baseTemplates = coreTemplates;
189324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( coreTemplates ==null ) {
190324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ErrorManager.error(ErrorManager.MSG_MISSING_CODE_GEN_TEMPLATES,
191324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							   language);
192324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return;
193324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
194324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
195324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// dynamically add subgroups that act like filters to apply to
196324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// their supergroup.  E.g., Java:Dbg:AST:ASTParser::ASTDbg.
197324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String outputOption = (String)grammar.getOption("output");
198324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( outputOption!=null && outputOption.equals("AST") ) {
199324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( debug && grammar.type!=Grammar.LEXER ) {
200324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				STGroup dbgTemplates = new STGroupFile(langDir+"/Dbg.stg");
201324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				dbgTemplates.importTemplates(coreTemplates);
202324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				baseTemplates = dbgTemplates;
203324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				STGroup astTemplates = new STGroupFile(langDir+"/AST.stg");
204324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				astTemplates.importTemplates(dbgTemplates);
205324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				STGroup astParserTemplates = astTemplates;
206324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				if ( grammar.type==Grammar.TREE_PARSER ) {
207324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					astParserTemplates = new STGroupFile(langDir+"/ASTTreeParser.stg");
208324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					astParserTemplates.importTemplates(astTemplates);
209324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				}
210324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				else {
211324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					astParserTemplates = new STGroupFile(langDir+"/ASTParser.stg");
212324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					astParserTemplates.importTemplates(astTemplates);
213324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				}
214324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				STGroup astDbgTemplates = new STGroupFile(langDir+"/ASTDbg.stg");
215324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				astDbgTemplates.importTemplates(astParserTemplates);
216324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				templates = astDbgTemplates;
217324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				dbgTemplates.iterateAcrossValues = true; // ST v3 compatibility with Maps
218324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				astDbgTemplates.iterateAcrossValues = true;
219324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				astParserTemplates.iterateAcrossValues = true;
220324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
221324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			else {
222324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				STGroup astTemplates = new STGroupFile(langDir+"/AST.stg");
223324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				astTemplates.importTemplates(coreTemplates);
224324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				STGroup astParserTemplates = astTemplates;
225324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				if ( grammar.type==Grammar.TREE_PARSER ) {
226324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					astParserTemplates = new STGroupFile(langDir+"/ASTTreeParser.stg");
227324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					astParserTemplates.importTemplates(astTemplates);
228324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				}
229324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				else {
230324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					astParserTemplates = new STGroupFile(langDir+"/ASTParser.stg");
231324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					astParserTemplates.importTemplates(astTemplates);
232324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				}
233324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				templates = astParserTemplates;
234324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				astTemplates.iterateAcrossValues = true; // ST v3 compatibility with Maps
235324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				astParserTemplates.iterateAcrossValues = true;
236324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
237324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
238324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		else if ( outputOption!=null && outputOption.equals("template") ) {
239324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( debug && grammar.type!=Grammar.LEXER ) {
240324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				STGroup dbgTemplates = new STGroupFile(langDir+"/Dbg.stg");
241324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				dbgTemplates.importTemplates(coreTemplates);
242324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				baseTemplates = dbgTemplates;
243324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				STGroup stTemplates = new STGroupFile(langDir+"/ST.stg");
244324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				stTemplates.importTemplates(dbgTemplates);
245324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				templates = stTemplates;
246324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				dbgTemplates.iterateAcrossValues = true;
247324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
248324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			else {
249324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				STGroup stTemplates = new STGroupFile(langDir+"/ST.stg");
250324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				stTemplates.importTemplates(coreTemplates);
251324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				templates = stTemplates;
252324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
253324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			templates.iterateAcrossValues = true; // ST v3 compatibility with Maps
254324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
255324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		else if ( debug && grammar.type!=Grammar.LEXER ) {
256324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			STGroup dbgTemplates = new STGroupFile(langDir+"/Dbg.stg");
257324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			dbgTemplates.importTemplates(coreTemplates);
258324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			templates = dbgTemplates;
259324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			baseTemplates = templates;
260324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			baseTemplates.iterateAcrossValues = true; // ST v3 compatibility with Maps
261324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
262324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		else {
263324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			templates = coreTemplates;
264324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			coreTemplates.iterateAcrossValues = true; // ST v3 compatibility with Maps
265324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
266324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
267324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
268324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Given the grammar to which we are attached, walk the AST associated
269324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  with that grammar to create NFAs.  Then create the DFAs for all
270324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  decision points in the grammar by converting the NFAs to DFAs.
271324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  Finally, walk the AST again to generate code.
272324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *
273324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  Either 1 or 2 files are written:
274324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *
275324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 * 		recognizer: the main parser/lexer/treewalker item
276324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 * 		header file: language like C/C++ need extern definitions
277324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *
278324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  The target, such as JavaTarget, dictates which files get written.
279324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
280324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public ST genRecognizer() {
281324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		//System.out.println("### generate "+grammar.name+" recognizer");
282324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// LOAD OUTPUT TEMPLATES
283324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		loadTemplates(language);
284324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( templates==null ) {
285324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return null;
286324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
287324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
288324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// CREATE NFA FROM GRAMMAR, CREATE DFA FROM NFA
289324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( ErrorManager.doNotAttemptAnalysis() ) {
290324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return null;
291324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
292324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		target.performGrammarAnalysis(this, grammar);
293324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
294324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
295324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// some grammar analysis errors will not yield reliable DFA
296324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( ErrorManager.doNotAttemptCodeGen() ) {
297324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return null;
298324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
299324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
300324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// OPTIMIZE DFA
301324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		DFAOptimizer optimizer = new DFAOptimizer(grammar);
302324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		optimizer.optimize();
303324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
304324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// OUTPUT FILE (contains recognizerST)
305324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		outputFileST = templates.getInstanceOf("outputFile");
306324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
307324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// HEADER FILE
308324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( templates.isDefined("headerFile") ) {
309324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			headerFileST = templates.getInstanceOf("headerFile");
310324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
311324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		else {
312324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			// create a dummy to avoid null-checks all over code generator
313324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			headerFileST = new ST(templates,"xyz");
314324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			headerFileST.add("cyclicDFAs", (Object)null); // it normally sees this from outputFile
315324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			//headerFileST.impl.name = "dummy-header-file";
316324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
317324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
318324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		boolean filterMode = grammar.getOption("filter")!=null &&
319324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							  grammar.getOption("filter").equals("true");
320324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        boolean canBacktrack = grammar.getSyntacticPredicates()!=null ||
321324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                               grammar.composite.getRootGrammar().atLeastOneBacktrackOption ||
322324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver                               filterMode;
323324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
324324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        // TODO: move this down further because generating the recognizer
325324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// alters the model with info on who uses predefined properties etc...
326324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// The actions here might refer to something.
327324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
328324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// The only two possible output files are available at this point.
329324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// Verify action scopes are ok for target and dump actions into output
330324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// Templates can say <actions.parser.header> for example.
331324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Map<String, Map<String, Object>> actions = grammar.getActions();
332324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		verifyActionScopesOkForTarget(actions);
333324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// translate $x::y references
334324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		translateActionAttributeReferences(actions);
335324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
336324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        ST gateST = templates.getInstanceOf("actionGate");
337324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        if ( filterMode ) {
338324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            // if filtering, we need to set actions to execute at backtracking
339324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            // level 1 not 0.
340324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            gateST = templates.getInstanceOf("filteringActionGate");
341324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
342324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        grammar.setSynPredGateIfNotAlready(gateST);
343324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
344324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        headerFileST.add("actions", actions);
345324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		outputFileST.add("actions", actions);
346324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
347324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		headerFileST.add("buildTemplate", new Boolean(grammar.buildTemplate()));
348324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		outputFileST.add("buildTemplate", new Boolean(grammar.buildTemplate()));
349324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		headerFileST.add("buildAST", new Boolean(grammar.buildAST()));
350324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		outputFileST.add("buildAST", new Boolean(grammar.buildAST()));
351324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
352324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		outputFileST.add("rewriteMode", Boolean.valueOf(grammar.rewriteMode()));
353324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		headerFileST.add("rewriteMode", Boolean.valueOf(grammar.rewriteMode()));
354324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
355324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		outputFileST.add("backtracking", Boolean.valueOf(canBacktrack));
356324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		headerFileST.add("backtracking", Boolean.valueOf(canBacktrack));
357324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// turn on memoize attribute at grammar level so we can create ruleMemo.
358324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// each rule has memoize attr that hides this one, indicating whether
359324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// it needs to save results
360324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String memoize = (String)grammar.getOption("memoize");
361324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		outputFileST.add("memoize",
362324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						 (grammar.atLeastOneRuleMemoizes ||
363324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						  Boolean.valueOf(memoize != null && memoize.equals("true")) &&
364324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						  canBacktrack));
365324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		headerFileST.add("memoize",
366324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						 (grammar.atLeastOneRuleMemoizes ||
367324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						  Boolean.valueOf(memoize != null && memoize.equals("true")) &&
368324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						  canBacktrack));
369324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
370324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
371324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		outputFileST.add("trace", Boolean.valueOf(trace));
372324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		headerFileST.add("trace", Boolean.valueOf(trace));
373324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
374324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		outputFileST.add("profile", Boolean.valueOf(profile));
375324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		headerFileST.add("profile", Boolean.valueOf(profile));
376324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
377324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// RECOGNIZER
378324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( grammar.type==Grammar.LEXER ) {
379324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			recognizerST = templates.getInstanceOf("lexer");
380324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			outputFileST.add("LEXER", Boolean.valueOf(true));
381324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			headerFileST.add("LEXER", Boolean.valueOf(true));
382324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			recognizerST.add("filterMode",
383324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							 Boolean.valueOf(filterMode));
384324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
385324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		else if ( grammar.type==Grammar.PARSER ||
386324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			grammar.type==Grammar.COMBINED )
387324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		{
388324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			recognizerST = templates.getInstanceOf("parser");
389324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			outputFileST.add("PARSER", Boolean.valueOf(true));
390324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			headerFileST.add("PARSER", Boolean.valueOf(true));
391324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
392324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		else {
393324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			recognizerST = templates.getInstanceOf("treeParser");
394324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			outputFileST.add("TREE_PARSER", Boolean.valueOf(true));
395324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			headerFileST.add("TREE_PARSER", Boolean.valueOf(true));
396324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            recognizerST.add("filterMode",
397324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							 Boolean.valueOf(filterMode));
398324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
399324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		outputFileST.add("recognizer", recognizerST);
400324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		headerFileST.add("recognizer", recognizerST);
401324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		outputFileST.add("actionScope",
402324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						 grammar.getDefaultActionScope(grammar.type));
403324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		headerFileST.add("actionScope",
404324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						 grammar.getDefaultActionScope(grammar.type));
405324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
406324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String targetAppropriateFileNameString =
407324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			target.getTargetStringLiteralFromString(grammar.getFileName());
408324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		outputFileST.add("fileName", targetAppropriateFileNameString);
409324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		headerFileST.add("fileName", targetAppropriateFileNameString);
410324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		outputFileST.add("ANTLRVersion", tool.VERSION);
411324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		headerFileST.add("ANTLRVersion", tool.VERSION);
412324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		outputFileST.add("generatedTimestamp", Tool.getCurrentTimeStamp());
413324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		headerFileST.add("generatedTimestamp", Tool.getCurrentTimeStamp());
414324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
415324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// GENERATE RECOGNIZER
416324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// Walk the AST holding the input grammar, this time generating code
417324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// Decisions are generated by using the precomputed DFAs
418324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// Fill in the various templates with data
419324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		CodeGenTreeWalker gen = new CodeGenTreeWalker(new CommonTreeNodeStream(grammar.getGrammarTree()));
420324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		try {
421324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			gen.grammar_(
422324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						grammar,
423324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						recognizerST,
424324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						outputFileST,
425324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						headerFileST);
426324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
427324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		catch (RecognitionException re) {
428324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ErrorManager.error(ErrorManager.MSG_BAD_AST_STRUCTURE,
429324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							   re);
430324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
431324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
432324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		genTokenTypeConstants(recognizerST);
433324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		genTokenTypeConstants(outputFileST);
434324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		genTokenTypeConstants(headerFileST);
435324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
436324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( grammar.type!=Grammar.LEXER ) {
437324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			genTokenTypeNames(recognizerST);
438324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			genTokenTypeNames(outputFileST);
439324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			genTokenTypeNames(headerFileST);
440324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
441324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
442324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// Now that we know what synpreds are used, we can set into template
443324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Set synpredNames = null;
444324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( grammar.synPredNamesUsedInDFA.size()>0 ) {
445324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			synpredNames = grammar.synPredNamesUsedInDFA;
446324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
447324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		outputFileST.add("synpreds", synpredNames);
448324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		headerFileST.add("synpreds", synpredNames);
449324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
450324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// all recognizers can see Grammar object
451324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		recognizerST.add("grammar", grammar);
452324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
453324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if (LAUNCH_ST_INSPECTOR) {
454324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			outputFileST.inspect();
455324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( templates.isDefined("headerFile") ) headerFileST.inspect();
456324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
457324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
458324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// WRITE FILES
459324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		try {
460324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			target.genRecognizerFile(tool,this,grammar,outputFileST);
461324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( templates.isDefined("headerFile") ) {
462324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				ST extST = templates.getInstanceOf("headerFileExtension");
463324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				target.genRecognizerHeaderFile(tool,this,grammar,headerFileST,extST.render());
464324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
465324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			// write out the vocab interchange file; used by antlr,
466324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			// does not change per target
467324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ST tokenVocabSerialization = genTokenVocabOutput();
468324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			String vocabFileName = getVocabFileName();
469324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( vocabFileName!=null ) {
470324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				write(tokenVocabSerialization, vocabFileName);
471324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
472324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			//System.out.println(outputFileST.getDOTForDependencyGraph(false));
473324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
474324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		catch (IOException ioe) {
475324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ErrorManager.error(ErrorManager.MSG_CANNOT_WRITE_FILE, ioe);
476324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
477324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		/*
478324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		System.out.println("num obj.prop refs: "+ ASTExpr.totalObjPropRefs);
479324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		System.out.println("num reflection lookups: "+ ASTExpr.totalReflectionLookups);
480324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		*/
481324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
482324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return outputFileST;
483324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
484324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
485324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Some targets will have some extra scopes like C++ may have
486324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  '@headerfile:name {action}' or something.  Make sure the
487324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  target likes the scopes in action table.
488324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
489324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected void verifyActionScopesOkForTarget(Map actions) {
490324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Set actionScopeKeySet = actions.keySet();
491324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		for (Iterator it = actionScopeKeySet.iterator(); it.hasNext();) {
492324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			String scope = (String)it.next();
493324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( !target.isValidActionScope(grammar.type, scope) ) {
494324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				// get any action from the scope to get error location
495324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				Map scopeActions = (Map)actions.get(scope);
496324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				GrammarAST actionAST =
497324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					(GrammarAST)scopeActions.values().iterator().next();
498324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				ErrorManager.grammarError(
499324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					ErrorManager.MSG_INVALID_ACTION_SCOPE,grammar,
500324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					actionAST.getToken(),scope,
501324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					grammar.getGrammarTypeString());
502324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
503324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
504324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
505324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
506324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Actions may reference $x::y attributes, call translateAction on
507324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  each action and replace that action in the Map.
508324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
509324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected void translateActionAttributeReferences(Map actions) {
510324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Set actionScopeKeySet = actions.keySet();
511324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		for (Iterator it = actionScopeKeySet.iterator(); it.hasNext();) {
512324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			String scope = (String)it.next();
513324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			Map scopeActions = (Map)actions.get(scope);
514324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			translateActionAttributeReferencesForSingleScope(null,scopeActions);
515324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
516324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
517324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
518324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Use for translating rule @init{...} actions that have no scope */
519324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public void translateActionAttributeReferencesForSingleScope(
520324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Rule r,
521324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Map scopeActions)
522324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	{
523324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String ruleName=null;
524324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( r!=null ) {
525324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ruleName = r.name;
526324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
527324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Set actionNameSet = scopeActions.keySet();
528324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		for (Iterator nameIT = actionNameSet.iterator(); nameIT.hasNext();) {
529324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			String name = (String) nameIT.next();
530324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			GrammarAST actionAST = (GrammarAST)scopeActions.get(name);
531324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			List chunks = translateAction(ruleName,actionAST);
532324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			scopeActions.put(name, chunks); // replace with translation
533324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
534324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
535324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
536324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Error recovery in ANTLR recognizers.
537324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *
538324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  Based upon original ideas:
539324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *
540324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  Algorithms + Data Structures = Programs by Niklaus Wirth
541324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *
542324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  and
543324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *
544324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  A note on error recovery in recursive descent parsers:
545324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  http://portal.acm.org/citation.cfm?id=947902.947905
546324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *
547324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  Later, Josef Grosch had some good ideas:
548324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  Efficient and Comfortable Error Recovery in Recursive Descent Parsers:
549324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  ftp://www.cocolab.com/products/cocktail/doca4.ps/ell.ps.zip
550324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *
551324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  Like Grosch I implemented local FOLLOW sets that are combined at run-time
552324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  upon error to avoid parsing overhead.
553324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
554324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public void generateLocalFOLLOW(GrammarAST referencedElementNode,
555324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver									String referencedElementName,
556324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver									String enclosingRuleName,
557324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver									int elementIndex)
558324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	{
559324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		/*
560324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		System.out.println("compute FOLLOW "+grammar.name+"."+referencedElementNode.toString()+
561324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						 " for "+referencedElementName+"#"+elementIndex +" in "+
562324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						 enclosingRuleName+
563324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						 " line="+referencedElementNode.getLine());
564324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						 */
565324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		NFAState followingNFAState = referencedElementNode.followingNFAState;
566324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		LookaheadSet follow = null;
567324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( followingNFAState!=null ) {
568324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			// compute follow for this element and, as side-effect, track
569324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			// the rule LOOK sensitivity.
570324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			follow = grammar.FIRST(followingNFAState);
571324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
572324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
573324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( follow==null ) {
574324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ErrorManager.internalError("no follow state or cannot compute follow");
575324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			follow = new LookaheadSet();
576324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
577324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( follow.member(Label.EOF) ) {
578324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			// TODO: can we just remove?  Seems needed here:
579324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			// compilation_unit : global_statement* EOF
580324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			// Actually i guess we resync to EOF regardless
581324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			follow.remove(Label.EOF);
582324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
583324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		//System.out.println(" "+follow);
584324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
585324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        List tokenTypeList = null;
586324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        long[] words = null;
587324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( follow.tokenTypeSet==null ) {
588324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			words = new long[1];
589324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            tokenTypeList = new ArrayList();
590324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
591324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		else {
592324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			BitSet bits = BitSet.of(follow.tokenTypeSet);
593324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			words = bits.toPackedArray();
594324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver            tokenTypeList = follow.tokenTypeSet.toList();
595324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver        }
596324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// use the target to convert to hex strings (typically)
597324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String[] wordStrings = new String[words.length];
598324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		for (int j = 0; j < words.length; j++) {
599324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			long w = words[j];
600324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			wordStrings[j] = target.getTarget64BitStringFromValue(w);
601324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
602324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		recognizerST.addAggr("bitsets.{name,inName,bits,tokenTypes,tokenIndex}",
603324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							 referencedElementName,
604324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							 enclosingRuleName,
605324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							 wordStrings,
606324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							 tokenTypeList,
607324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							 Utils.integer(elementIndex));
608324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		outputFileST.addAggr("bitsets.{name,inName,bits,tokenTypes,tokenIndex}",
609324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							 referencedElementName,
610324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							 enclosingRuleName,
611324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							 wordStrings,
612324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							 tokenTypeList,
613324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							 Utils.integer(elementIndex));
614324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		headerFileST.addAggr("bitsets.{name,inName,bits,tokenTypes,tokenIndex}",
615324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							 referencedElementName,
616324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							 enclosingRuleName,
617324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							 wordStrings,
618324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							 tokenTypeList,
619324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							 Utils.integer(elementIndex));
620324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
621324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
622324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	// L O O K A H E A D  D E C I S I O N  G E N E R A T I O N
623324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
624324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Generate code that computes the predicted alt given a DFA.  The
625324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  recognizerST can be either the main generated recognizerTemplate
626324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  for storage in the main parser file or a separate file.  It's up to
627324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  the code that ultimately invokes the codegen.g grammar rule.
628324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *
629324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  Regardless, the output file and header file get a copy of the DFAs.
630324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
631324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public ST genLookaheadDecision(ST recognizerST,
632324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver								   DFA dfa)
633324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	{
634324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ST decisionST;
635324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// If we are doing inline DFA and this one is acyclic and LL(*)
636324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// I have to check for is-non-LL(*) because if non-LL(*) the cyclic
637324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// check is not done by DFA.verify(); that is, verify() avoids
638324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// doesStateReachAcceptState() if non-LL(*)
639324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( dfa.canInlineDecision() ) {
640324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			decisionST =
641324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				acyclicDFAGenerator.genFixedLookaheadDecision(getTemplates(), dfa);
642324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
643324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		else {
644324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			// generate any kind of DFA here (cyclic or acyclic)
645324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			dfa.createStateTables(this);
646324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			outputFileST.add("cyclicDFAs", dfa);
647324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			headerFileST.add("cyclicDFAs", dfa);
648324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			decisionST = templates.getInstanceOf("dfaDecision");
649324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			String description = dfa.getNFADecisionStartState().getDescription();
650324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			description = target.getTargetStringLiteralFromString(description);
651324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( description!=null ) {
652324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				decisionST.add("description", description);
653324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
654324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			decisionST.add("decisionNumber",
655324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						   Utils.integer(dfa.getDecisionNumber()));
656324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
657324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return decisionST;
658324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
659324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
660324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** A special state is huge (too big for state tables) or has a predicated
661324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  edge.  Generate a simple if-then-else.  Cannot be an accept state as
662324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  they have no emanating edges.  Don't worry about switch vs if-then-else
663324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  because if you get here, the state is super complicated and needs an
664324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  if-then-else.  This is used by the new DFA scheme created June 2006.
665324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
666324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public ST generateSpecialState(DFAState s) {
667324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ST stateST;
668324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		stateST = templates.getInstanceOf("cyclicDFAState");
669324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		stateST.add("needErrorClause", Boolean.valueOf(true));
670324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		stateST.add("semPredState",
671324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					Boolean.valueOf(s.isResolvedWithPredicates()));
672324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		stateST.add("stateNumber", s.stateNumber);
673324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		stateST.add("decisionNumber", s.dfa.decisionNumber);
674324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
675324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		boolean foundGatedPred = false;
676324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ST eotST = null;
677324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		for (int i = 0; i < s.getNumberOfTransitions(); i++) {
678324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			Transition edge = (Transition) s.transition(i);
679324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ST edgeST;
680324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( edge.label.getAtom()==Label.EOT ) {
681324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				// this is the default clause; has to held until last
682324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				edgeST = templates.getInstanceOf("eotDFAEdge");
683324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				stateST.remove("needErrorClause");
684324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				eotST = edgeST;
685324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
686324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			else {
687324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				edgeST = templates.getInstanceOf("cyclicDFAEdge");
688324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				ST exprST =
689324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					genLabelExpr(templates,edge,1);
690324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				edgeST.add("labelExpr", exprST);
691324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
692324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			edgeST.add("edgeNumber", Utils.integer(i + 1));
693324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			edgeST.add("targetStateNumber",
694324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					   Utils.integer(edge.target.stateNumber));
695324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			// stick in any gated predicates for any edge if not already a pred
696324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( !edge.label.isSemanticPredicate() ) {
697324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				DFAState t = (DFAState)edge.target;
698324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				SemanticContext preds =	t.getGatedPredicatesInNFAConfigurations();
699324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				if ( preds!=null ) {
700324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					foundGatedPred = true;
701324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					ST predST = preds.genExpr(this,
702324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver														  getTemplates(),
703324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver														  t.dfa);
704324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					edgeST.add("predicates", predST.render());
705324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				}
706324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
707324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( edge.label.getAtom()!=Label.EOT ) {
708324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				stateST.add("edges", edgeST);
709324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
710324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
711324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( foundGatedPred ) {
712324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			// state has >= 1 edge with a gated pred (syn or sem)
713324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			// must rewind input first, set flag.
714324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			stateST.add("semPredState", new Boolean(foundGatedPred));
715324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
716324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( eotST!=null ) {
717324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			stateST.add("edges", eotST);
718324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
719324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return stateST;
720324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
721324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
722324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Generate an expression for traversing an edge. */
723324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected ST genLabelExpr(STGroup templates,
724324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  Transition edge,
725324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  int k)
726324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	{
727324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Label label = edge.label;
728324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( label.isSemanticPredicate() ) {
729324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return genSemanticPredicateExpr(templates, edge);
730324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
731324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( label.isSet() ) {
732324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return genSetExpr(templates, label.getSet(), k, true);
733324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
734324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// must be simple label
735324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ST eST = templates.getInstanceOf("lookaheadTest");
736324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		eST.add("atom", getTokenTypeAsTargetLabel(label.getAtom()));
737324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		eST.add("atomAsInt", Utils.integer(label.getAtom()));
738324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		eST.add("k", Utils.integer(k));
739324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return eST;
740324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
741324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
742324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected ST genSemanticPredicateExpr(STGroup templates,
743324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver													  Transition edge)
744324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	{
745324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		DFA dfa = ((DFAState)edge.target).dfa; // which DFA are we in
746324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Label label = edge.label;
747324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		SemanticContext semCtx = label.getSemanticContext();
748324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return semCtx.genExpr(this,templates,dfa);
749324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
750324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
751324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** For intervals such as [3..3, 30..35], generate an expression that
752324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  tests the lookahead similar to LA(1)==3 || (LA(1)>=30&&LA(1)<=35)
753324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
754324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public ST genSetExpr(STGroup templates,
755324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver									 IntSet set,
756324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver									 int k,
757324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver									 boolean partOfDFA)
758324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	{
759324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( !(set instanceof IntervalSet) ) {
760324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			throw new IllegalArgumentException("unable to generate expressions for non IntervalSet objects");
761324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
762324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		IntervalSet iset = (IntervalSet)set;
763324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( iset.getIntervals()==null || iset.getIntervals().size()==0 ) {
764324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ST emptyST = new ST(templates, "");
765324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			emptyST.impl.name = "empty-set-expr";
766324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return emptyST;
767324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
768324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String testSTName = "lookaheadTest";
769324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String testRangeSTName = "lookaheadRangeTest";
770324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( !partOfDFA ) {
771324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			testSTName = "isolatedLookaheadTest";
772324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			testRangeSTName = "isolatedLookaheadRangeTest";
773324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
774324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ST setST = templates.getInstanceOf("setTest");
775324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Iterator iter = iset.getIntervals().iterator();
776324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		int rangeNumber = 1;
777324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		while (iter.hasNext()) {
778324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			Interval I = (Interval) iter.next();
779324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			int a = I.a;
780324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			int b = I.b;
781324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ST eST;
782324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( a==b ) {
783324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				eST = templates.getInstanceOf(testSTName);
784324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				eST.add("atom", getTokenTypeAsTargetLabel(a));
785324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				eST.add("atomAsInt", Utils.integer(a));
786324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				//eST.add("k",Utils.integer(k));
787324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
788324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			else {
789324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				eST = templates.getInstanceOf(testRangeSTName);
790324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				eST.add("lower", getTokenTypeAsTargetLabel(a));
791324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				eST.add("lowerAsInt", Utils.integer(a));
792324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				eST.add("upper", getTokenTypeAsTargetLabel(b));
793324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				eST.add("upperAsInt", Utils.integer(b));
794324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				eST.add("rangeNumber", Utils.integer(rangeNumber));
795324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
796324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			eST.add("k", Utils.integer(k));
797324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			setST.add("ranges", eST);
798324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			rangeNumber++;
799324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
800324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return setST;
801324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
802324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
803324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	// T O K E N  D E F I N I T I O N  G E N E R A T I O N
804324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
805324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Set attributes tokens and literals attributes in the incoming
806324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  code template.  This is not the token vocab interchange file, but
807324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  rather a list of token type ID needed by the recognizer.
808324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
809324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected void genTokenTypeConstants(ST code) {
810324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// make constants for the token types
811324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Iterator tokenIDs = grammar.getTokenIDs().iterator();
812324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		while (tokenIDs.hasNext()) {
813324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			String tokenID = (String) tokenIDs.next();
814324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			int tokenType = grammar.getTokenType(tokenID);
815324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( tokenType==Label.EOF ||
816324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				 tokenType>=Label.MIN_TOKEN_TYPE )
817324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			{
818324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				// don't do FAUX labels 'cept EOF
819324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				code.addAggr("tokens.{name,type}", tokenID, Utils.integer(tokenType));
820324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
821324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
822324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
823324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
824324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Generate a token names table that maps token type to a printable
825324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  name: either the label like INT or the literal like "begin".
826324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
827324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected void genTokenTypeNames(ST code) {
828324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		for (int t=Label.MIN_TOKEN_TYPE; t<=grammar.getMaxTokenType(); t++) {
829324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			String tokenName = grammar.getTokenDisplayName(t);
830324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( tokenName!=null ) {
831324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				tokenName=target.getTargetStringLiteralFromString(tokenName, true);
832324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				code.add("tokenNames", tokenName);
833324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
834324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
835324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
836324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
837324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Get a meaningful name for a token type useful during code generation.
838324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  Literals without associated names are converted to the string equivalent
839324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  of their integer values. Used to generate x==ID and x==34 type comparisons
840324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  etc...  Essentially we are looking for the most obvious way to refer
841324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  to a token type in the generated code.  If in the lexer, return the
842324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  char literal translated to the target language.  For example, ttype=10
843324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  will yield '\n' from the getTokenDisplayName method.  That must
844324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  be converted to the target languages literals.  For most C-derived
845324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  languages no translation is needed.
846324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
847324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public String getTokenTypeAsTargetLabel(int ttype) {
848324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( grammar.type==Grammar.LEXER ) {
849324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			String name = grammar.getTokenDisplayName(ttype);
850324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return target.getTargetCharLiteralFromANTLRCharLiteral(this,name);
851324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
852324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return target.getTokenTypeAsTargetLabel(this,ttype);
853324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
854324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
855324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Generate a token vocab file with all the token names/types.  For example:
856324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  ID=7
857324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  FOR=8
858324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  'for'=8
859324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *
860324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  This is independent of the target language; used by antlr internally
861324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
862324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected ST genTokenVocabOutput() {
863324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ST vocabFileST = new ST(vocabFilePattern);
864324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		vocabFileST.add("literals",(Object)null); // "define" literals arg
865324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		vocabFileST.add("tokens",(Object)null);
866324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		vocabFileST.impl.name = "vocab-file";
867324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// make constants for the token names
868324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Iterator tokenIDs = grammar.getTokenIDs().iterator();
869324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		while (tokenIDs.hasNext()) {
870324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			String tokenID = (String) tokenIDs.next();
871324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			int tokenType = grammar.getTokenType(tokenID);
872324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( tokenType>=Label.MIN_TOKEN_TYPE ) {
873324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				vocabFileST.addAggr("tokens.{name,type}", tokenID, Utils.integer(tokenType));
874324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
875324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
876324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
877324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// now dump the strings
878324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Iterator literals = grammar.getStringLiterals().iterator();
879324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		while (literals.hasNext()) {
880324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			String literal = (String) literals.next();
881324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			int tokenType = grammar.getTokenType(literal);
882324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( tokenType>=Label.MIN_TOKEN_TYPE ) {
883324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				vocabFileST.addAggr("tokens.{name,type}", literal, Utils.integer(tokenType));
884324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
885324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
886324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
887324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return vocabFileST;
888324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
889324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
890324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public List translateAction(String ruleName,
891324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver								GrammarAST actionTree)
892324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	{
893324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( actionTree.getType()==ANTLRParser.ARG_ACTION ) {
894324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return translateArgAction(ruleName, actionTree);
895324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
896324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ActionTranslator translator = new ActionTranslator(this,ruleName,actionTree);
897324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		List chunks = translator.translateToChunks();
898324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		chunks = target.postProcessAction(chunks, actionTree.token);
899324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return chunks;
900324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
901324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
902324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Translate an action like [3,"foo",a[3]] and return a List of the
903324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  translated actions.  Because actions are themselves translated to a list
904324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  of chunks, must cat together into a ST>.  Don't translate
905324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  to strings early as we need to eval templates in context.
906324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
907324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public List<ST> translateArgAction(String ruleName,
908324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										   GrammarAST actionTree)
909324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	{
910324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String actionText = actionTree.token.getText();
911324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		List<String> args = getListOfArgumentsFromAction(actionText,',');
912324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		List<ST> translatedArgs = new ArrayList<ST>();
913324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		for (String arg : args) {
914324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( arg!=null ) {
915324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				Token actionToken =
916324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					new CommonToken(ANTLRParser.ACTION,arg);
917324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				ActionTranslator translator =
918324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					new ActionTranslator(this,ruleName,
919324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver											  actionToken,
920324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver											  actionTree.outerAltNum);
921324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				List chunks = translator.translateToChunks();
922324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				chunks = target.postProcessAction(chunks, actionToken);
923324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				ST catST = new ST(templates, "<chunks>");
924324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				catST.add("chunks", chunks);
925324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				translatedArgs.add(catST);
926324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
927324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
928324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( translatedArgs.size()==0 ) {
929324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return null;
930324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
931324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return translatedArgs;
932324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
933324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
934324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public static List<String> getListOfArgumentsFromAction(String actionText,
935324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver															int separatorChar)
936324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	{
937324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		List<String> args = new ArrayList<String>();
938324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		getListOfArgumentsFromAction(actionText, 0, -1, separatorChar, args);
939324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return args;
940324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
941324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
942324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Given an arg action like
943324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *
944324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  [x, (*a).foo(21,33), 3.2+1, '\n',
945324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  "a,oo\nick", {bl, "fdkj"eck}, ["cat\n,", x, 43]]
946324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *
947324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  convert to a list of arguments.  Allow nested square brackets etc...
948324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  Set separatorChar to ';' or ',' or whatever you want.
949324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
950324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public static int getListOfArgumentsFromAction(String actionText,
951324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver												   int start,
952324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver												   int targetChar,
953324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver												   int separatorChar,
954324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver												   List<String> args)
955324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	{
956324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( actionText==null ) {
957324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return -1;
958324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
959324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		actionText = actionText.replaceAll("//.*\n", "");
960324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		int n = actionText.length();
961324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		//System.out.println("actionText@"+start+"->"+(char)targetChar+"="+actionText.substring(start,n));
962324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		int p = start;
963324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		int last = p;
964324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		while ( p<n && actionText.charAt(p)!=targetChar ) {
965324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			int c = actionText.charAt(p);
966324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			switch ( c ) {
967324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				case '\'' :
968324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					p++;
969324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					while ( p<n && actionText.charAt(p)!='\'' ) {
970324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						if ( actionText.charAt(p)=='\\' && (p+1)<n &&
971324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							 actionText.charAt(p+1)=='\'' )
972324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						{
973324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							p++; // skip escaped quote
974324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						}
975324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						p++;
976324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					}
977324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					p++;
978324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					break;
979324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				case '"' :
980324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					p++;
981324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					while ( p<n && actionText.charAt(p)!='\"' ) {
982324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						if ( actionText.charAt(p)=='\\' && (p+1)<n &&
983324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							 actionText.charAt(p+1)=='\"' )
984324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						{
985324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							p++; // skip escaped quote
986324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						}
987324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						p++;
988324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					}
989324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					p++;
990324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					break;
991324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				case '(' :
992324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					p = getListOfArgumentsFromAction(actionText,p+1,')',separatorChar,args);
993324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					break;
994324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				case '{' :
995324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					p = getListOfArgumentsFromAction(actionText,p+1,'}',separatorChar,args);
996324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					break;
997324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				case '<' :
998324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					if ( actionText.indexOf('>',p+1)>=p ) {
999324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						// do we see a matching '>' ahead?  if so, hope it's a generic
1000324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						// and not less followed by expr with greater than
1001324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						p = getListOfArgumentsFromAction(actionText,p+1,'>',separatorChar,args);
1002324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					}
1003324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					else {
1004324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						p++; // treat as normal char
1005324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					}
1006324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					break;
1007324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				case '[' :
1008324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					p = getListOfArgumentsFromAction(actionText,p+1,']',separatorChar,args);
1009324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					break;
1010324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				default :
1011324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					if ( c==separatorChar && targetChar==-1 ) {
1012324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						String arg = actionText.substring(last, p);
1013324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						//System.out.println("arg="+arg);
1014324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						args.add(arg.trim());
1015324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver						last = p+1;
1016324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					}
1017324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					p++;
1018324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					break;
1019324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
1020324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1021324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( targetChar==-1 && p<=n ) {
1022324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			String arg = actionText.substring(last, p).trim();
1023324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			//System.out.println("arg="+arg);
1024324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( arg.length()>0 ) {
1025324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				args.add(arg.trim());
1026324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
1027324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1028324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		p++;
1029324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return p;
1030324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1031324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1032324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Given a template constructor action like %foo(a={...}) in
1033324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  an action, translate it to the appropriate template constructor
1034324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  from the templateLib. This translates a *piece* of the action.
1035324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
1036324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public ST translateTemplateConstructor(String ruleName,
1037324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver													   int outerAltNum,
1038324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver													   Token actionToken,
1039324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver													   String templateActionText)
1040324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	{
1041324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// first, parse with antlr.g
1042324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		//System.out.println("translate template: "+templateActionText);
1043324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ANTLRLexer lexer = new ANTLRLexer(new ANTLRStringStream(templateActionText));
1044324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		lexer.setFileName(grammar.getFileName());
1045324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ANTLRParser parser = ANTLRParser.createParser(new CommonTokenStream(lexer));
1046324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		parser.setFileName(grammar.getFileName());
1047324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ANTLRParser.rewrite_template_return parseResult = null;
1048324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		try {
1049324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			parseResult = parser.rewrite_template();
1050324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1051324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		catch (RecognitionException re) {
1052324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ErrorManager.grammarError(ErrorManager.MSG_INVALID_TEMPLATE_ACTION,
1053324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  grammar,
1054324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  actionToken,
1055324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  templateActionText);
1056324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1057324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		catch (Exception tse) {
1058324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ErrorManager.internalError("can't parse template action",tse);
1059324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1060324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		GrammarAST rewriteTree = (GrammarAST)parseResult.getTree();
1061324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1062324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// then translate via codegen.g
1063324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		CodeGenTreeWalker gen = new CodeGenTreeWalker(new CommonTreeNodeStream(rewriteTree));
1064324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		gen.init(grammar);
1065324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		gen.setCurrentRuleName(ruleName);
1066324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		gen.setOuterAltNum(outerAltNum);
1067324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ST st = null;
1068324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		try {
1069324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			st = gen.rewrite_template();
1070324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1071324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		catch (RecognitionException re) {
1072324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ErrorManager.error(ErrorManager.MSG_BAD_AST_STRUCTURE,
1073324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver							   re);
1074324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1075324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return st;
1076324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1077324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1078324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1079324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public void issueInvalidScopeError(String x,
1080324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver									   String y,
1081324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver									   Rule enclosingRule,
1082324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver									   Token actionToken,
1083324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver									   int outerAltNum)
1084324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	{
1085324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		//System.out.println("error $"+x+"::"+y);
1086324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Rule r = grammar.getRule(x);
1087324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		AttributeScope scope = grammar.getGlobalScope(x);
1088324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( scope==null ) {
1089324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( r!=null ) {
1090324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				scope = r.ruleScope; // if not global, might be rule scope
1091324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
1092324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1093324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( scope==null ) {
1094324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ErrorManager.grammarError(ErrorManager.MSG_UNKNOWN_DYNAMIC_SCOPE,
1095324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  grammar,
1096324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  actionToken,
1097324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  x);
1098324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1099324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		else if ( scope.getAttribute(y)==null ) {
1100324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ErrorManager.grammarError(ErrorManager.MSG_UNKNOWN_DYNAMIC_SCOPE_ATTRIBUTE,
1101324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  grammar,
1102324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  actionToken,
1103324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  x,
1104324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  y);
1105324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1106324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1107324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1108324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public void issueInvalidAttributeError(String x,
1109324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										   String y,
1110324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										   Rule enclosingRule,
1111324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										   Token actionToken,
1112324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										   int outerAltNum)
1113324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	{
1114324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		//System.out.println("error $"+x+"."+y);
1115324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( enclosingRule==null ) {
1116324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			// action not in a rule
1117324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ErrorManager.grammarError(ErrorManager.MSG_ATTRIBUTE_REF_NOT_IN_RULE,
1118324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  grammar,
1119324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  actionToken,
1120324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  x,
1121324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  y);
1122324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return;
1123324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1124324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1125324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// action is in a rule
1126324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Grammar.LabelElementPair label = enclosingRule.getRuleLabel(x);
1127324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1128324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( label!=null || enclosingRule.getRuleRefsInAlt(x, outerAltNum)!=null ) {
1129324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			// $rulelabel.attr or $ruleref.attr; must be unknown attr
1130324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			String refdRuleName = x;
1131324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( label!=null ) {
1132324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				refdRuleName = enclosingRule.getRuleLabel(x).referencedRuleName;
1133324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
1134324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			Rule refdRule = grammar.getRule(refdRuleName);
1135324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			AttributeScope scope = refdRule.getAttributeScope(y);
1136324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( scope==null ) {
1137324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				ErrorManager.grammarError(ErrorManager.MSG_UNKNOWN_RULE_ATTRIBUTE,
1138324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  grammar,
1139324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  actionToken,
1140324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  refdRuleName,
1141324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  y);
1142324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
1143324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			else if ( scope.isParameterScope ) {
1144324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				ErrorManager.grammarError(ErrorManager.MSG_INVALID_RULE_PARAMETER_REF,
1145324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  grammar,
1146324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  actionToken,
1147324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  refdRuleName,
1148324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  y);
1149324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
1150324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			else if ( scope.isDynamicRuleScope ) {
1151324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				ErrorManager.grammarError(ErrorManager.MSG_INVALID_RULE_SCOPE_ATTRIBUTE_REF,
1152324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  grammar,
1153324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  actionToken,
1154324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  refdRuleName,
1155324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  y);
1156324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
1157324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1158324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1159324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1160324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1161324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public void issueInvalidAttributeError(String x,
1162324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										   Rule enclosingRule,
1163324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										   Token actionToken,
1164324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										   int outerAltNum)
1165324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	{
1166324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		//System.out.println("error $"+x);
1167324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( enclosingRule==null ) {
1168324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			// action not in a rule
1169324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ErrorManager.grammarError(ErrorManager.MSG_ATTRIBUTE_REF_NOT_IN_RULE,
1170324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  grammar,
1171324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  actionToken,
1172324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  x);
1173324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return;
1174324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1175324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1176324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// action is in a rule
1177324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Grammar.LabelElementPair label = enclosingRule.getRuleLabel(x);
1178324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		AttributeScope scope = enclosingRule.getAttributeScope(x);
1179324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1180324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( label!=null ||
1181324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			 enclosingRule.getRuleRefsInAlt(x, outerAltNum)!=null ||
1182324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			 enclosingRule.name.equals(x) )
1183324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		{
1184324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ErrorManager.grammarError(ErrorManager.MSG_ISOLATED_RULE_SCOPE,
1185324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  grammar,
1186324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  actionToken,
1187324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  x);
1188324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1189324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		else if ( scope!=null && scope.isDynamicRuleScope ) {
1190324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ErrorManager.grammarError(ErrorManager.MSG_ISOLATED_RULE_ATTRIBUTE,
1191324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  grammar,
1192324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  actionToken,
1193324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver										  x);
1194324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1195324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		else {
1196324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			ErrorManager.grammarError(ErrorManager.MSG_UNKNOWN_SIMPLE_ATTRIBUTE,
1197324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver									  grammar,
1198324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver									  actionToken,
1199324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver									  x);
1200324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1201324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1202324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1203324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	// M I S C
1204324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1205324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public STGroup getTemplates() {
1206324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return templates;
1207324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1208324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1209324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public STGroup getBaseTemplates() {
1210324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return baseTemplates;
1211324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1212324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1213324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public void setDebug(boolean debug) {
1214324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		this.debug = debug;
1215324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1216324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1217324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public void setTrace(boolean trace) {
1218324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		this.trace = trace;
1219324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1220324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1221324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public void setProfile(boolean profile) {
1222324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		this.profile = profile;
1223324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( profile ) {
1224324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			setDebug(true); // requires debug events
1225324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1226324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1227324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1228324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public ST getRecognizerST() {
1229324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return outputFileST;
1230324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1231324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1232324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Generate TParser.java and TLexer.java from T.g if combined, else
1233324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  just use T.java as output regardless of type.
1234324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
1235324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public String getRecognizerFileName(String name, int type) {
1236324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		ST extST = templates.getInstanceOf("codeFileExtension");
1237324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String recognizerName = grammar.getRecognizerName();
1238324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return recognizerName+extST.render();
1239324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		/*
1240324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		String suffix = "";
1241324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( type==Grammar.COMBINED ||
1242324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			 (type==Grammar.LEXER && !grammar.implicitLexer) )
1243324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		{
1244324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			suffix = Grammar.grammarTypeToFileNameSuffix[type];
1245324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1246324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return name+suffix+extST.toString();
1247324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		*/
1248324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1249324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1250324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** What is the name of the vocab file generated for this grammar?
1251324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  Returns null if no .tokens file should be generated.
1252324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
1253324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public String getVocabFileName() {
1254324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( grammar.isBuiltFromString() ) {
1255324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return null;
1256324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1257324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return grammar.name+VOCAB_FILE_EXTENSION;
1258324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1259324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1260324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public void write(ST code, String fileName) throws IOException {
1261324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		//long start = System.currentTimeMillis();
1262324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		Writer w = tool.getOutputFile(grammar, fileName);
1263324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		// Write the output to a StringWriter
1264324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		STWriter wr = new AutoIndentWriter(w);
1265324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		wr.setLineWidth(lineWidth);
1266324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		code.write(wr);
1267324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		w.close();
1268324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		//long stop = System.currentTimeMillis();
1269324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		//System.out.println("render time for "+fileName+": "+(int)(stop-start)+"ms");
1270324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1271324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1272324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** You can generate a switch rather than if-then-else for a DFA state
1273324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  if there are no semantic predicates and the number of edge label
1274324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  values is small enough; e.g., don't generate a switch for a state
1275324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  containing an edge label such as 20..52330 (the resulting byte codes
1276324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  would overflow the method 65k limit probably).
1277324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
1278324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	protected boolean canGenerateSwitch(DFAState s) {
1279324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( !GENERATE_SWITCHES_WHEN_POSSIBLE ) {
1280324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return false;
1281324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1282324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		int size = 0;
1283324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		for (int i = 0; i < s.getNumberOfTransitions(); i++) {
1284324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			Transition edge = (Transition) s.transition(i);
1285324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( edge.label.isSemanticPredicate() ) {
1286324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				return false;
1287324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
1288324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			// can't do a switch if the edges are going to require predicates
1289324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( edge.label.getAtom()==Label.EOT ) {
1290324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				int EOTPredicts = ((DFAState)edge.target).getUniquelyPredictedAlt();
1291324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				if ( EOTPredicts==NFA.INVALID_ALT_NUMBER ) {
1292324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					// EOT target has to be a predicate then; no unique alt
1293324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver					return false;
1294324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				}
1295324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
1296324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			// if target is a state with gated preds, we need to use preds on
1297324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			// this edge then to reach it.
1298324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			if ( ((DFAState)edge.target).getGatedPredicatesInNFAConfigurations()!=null ) {
1299324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver				return false;
1300324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			}
1301324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			size += edge.label.getSet().size();
1302324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1303324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		if ( s.getNumberOfTransitions()<MIN_SWITCH_ALTS ||
1304324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			 size>MAX_SWITCH_CASE_LABELS ) {
1305324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			return false;
1306324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		}
1307324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return true;
1308324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1309324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver
1310324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	/** Create a label to track a token / rule reference's result.
1311324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  Technically, this is a place where I break model-view separation
1312324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  as I am creating a variable name that could be invalid in a
1313324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  target language, however, label ::= <ID><INT> is probably ok in
1314324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 *  all languages we care about.
1315324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	 */
1316324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	public String createUniqueLabel(String name) {
1317324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver		return new StringBuffer()
1318324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver			.append(name).append(uniqueLabelNumber++).toString();
1319324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver	}
1320324c4644fee44b9898524c09511bd33c3f12e2dfBen Gruver}
1321