package antlr;

/* ANTLR Translator Generator
 * Project led by Terence Parr at http://www.cs.usfca.edu
 * Software rights: http://www.antlr.org/license.html
 *
 * $Id: //depot/code/org.antlr/release/antlr-2.7.7/antlr/CppCodeGenerator.java#2 $
 */

// C++ code generator by Pete Wells: pete@yamuna.demon.co.uk
// #line generation contributed by: Ric Klaren <klaren@cs.utwente.nl>

import java.util.Enumeration;
import java.util.Hashtable;
import antlr.collections.impl.BitSet;
import antlr.collections.impl.Vector;
import java.io.PrintWriter; //SAS: changed for proper text file io
import java.io.IOException;
import java.io.FileWriter;

/** Generate MyParser.cpp, MyParser.hpp, MyLexer.cpp, MyLexer.hpp
 * and MyParserTokenTypes.hpp
 */
public class CppCodeGenerator extends CodeGenerator {
	boolean DEBUG_CPP_CODE_GENERATOR = false;
	// non-zero if inside syntactic predicate generation
	protected int syntacticPredLevel = 0;

	// Are we generating ASTs (for parsers and tree parsers) right now?
	protected boolean genAST = false;

	// Are we saving the text consumed (for lexers) right now?
	protected boolean saveText = false;

	// Generate #line's
	protected boolean genHashLines = true;
	// Generate constructors or not
	protected boolean noConstructors = false;

	// Used to keep track of lineno in output
	protected int outputLine;
	protected String outputFile;

	// Grammar parameters set up to handle different grammar classes.
	// These are used to get instanceof tests out of code generation
	boolean usingCustomAST = false;
	String labeledElementType;
	String labeledElementASTType; // mostly the same as labeledElementType except in parsers
	String labeledElementASTInit;
	String labeledElementInit;
	String commonExtraArgs;
	String commonExtraParams;
	String commonLocalVars;
	String lt1Value;
	String exceptionThrown;
	String throwNoViable;

	// Tracks the rule being generated.  Used for mapTreeId
	RuleBlock currentRule;
	// Tracks the rule or labeled subrule being generated.  Used for AST generation.
	String currentASTResult;
	// Mapping between the ids used in the current alt, and the
	// names of variables used to represent their AST values.
	Hashtable treeVariableMap = new Hashtable();

	/** Used to keep track of which AST variables have been defined in a rule
	 * (except for the #rule_name and #rule_name_in var's
	 */
	Hashtable declaredASTVariables = new Hashtable();

	// Count of unnamed generated variables
	int astVarNumber = 1;
	// Special value used to mark duplicate in treeVariableMap
	protected static final String NONUNIQUE = new String();

	public static final int caseSizeThreshold = 127; // ascii is max

	private Vector semPreds;

	// Used to keep track of which (heterogeneous AST types are used)
	// which need to be set in the ASTFactory of the generated parser
	private Vector astTypes;

	private static String namespaceStd   = "ANTLR_USE_NAMESPACE(std)";
	private static String namespaceAntlr = "ANTLR_USE_NAMESPACE(antlr)";
	private static NameSpace nameSpace = null;

	private static final String preIncludeCpp  = "pre_include_cpp";
	private static final String preIncludeHpp  = "pre_include_hpp";
	private static final String postIncludeCpp = "post_include_cpp";
	private static final String postIncludeHpp = "post_include_hpp";

	/** Create a C++ code-generator using the given Grammar.
	 * The caller must still call setTool, setBehavior, and setAnalyzer
	 * before generating code.
	 */
	public CppCodeGenerator() {
		super();
		charFormatter = new CppCharFormatter();
	}
	/** Adds a semantic predicate string to the sem pred vector
	    These strings will be used to build an array of sem pred names
	    when building a debugging parser.  This method should only be
	    called when the debug option is specified
	 */
	protected int addSemPred(String predicate) {
		semPreds.appendElement(predicate);
		return semPreds.size()-1;
	}
	public void exitIfError()
	{
		if (antlrTool.hasError())
		{
			antlrTool.fatalError("Exiting due to errors.");
		}
	}
	protected int countLines( String s )
	{
		int lines = 0;
		for( int i = 0; i < s.length(); i++ )
		{
			if( s.charAt(i) == '\n' )
				lines++;
		}
		return lines;
	}
	/** Output a String to the currentOutput stream.
	 * Ignored if string is null.
	 * @param s The string to output
	 */
	protected void _print(String s)
	{
		if (s != null)
		{
			outputLine += countLines(s);
			currentOutput.print(s);
		}
	}
	/** Print an action without leading tabs, attempting to
	 * preserve the current indentation level for multi-line actions
	 * Ignored if string is null.
	 * @param s The action string to output
	 */
	protected void _printAction(String s)
	{
		if (s != null)
		{
			outputLine += countLines(s)+1;
			super._printAction(s);
		}
	}
	/** Print an action stored in a token surrounded by #line stuff */
	public void printAction(Token t)
	{
		if (t != null)
		{
			genLineNo(t.getLine());
			printTabs();
			_printAction(processActionForSpecialSymbols(t.getText(), t.getLine(),
																null, null) );
			genLineNo2();
		}
	}
	/** Print a header action by #line stuff also process any tree construction
	 * @param name The name of the header part
	 */
	public void printHeaderAction(String name)
	{
		Token a = (antlr.Token)behavior.headerActions.get(name);
		if (a != null)
		{
			genLineNo(a.getLine());
			println(processActionForSpecialSymbols(a.getText(), a.getLine(),
																null, null) );
			genLineNo2();
		}
	}
	/** Output a String followed by newline, to the currentOutput stream.
	 * Ignored if string is null.
	 * @param s The string to output
	 */
	protected void _println(String s) {
		if (s != null) {
			outputLine += countLines(s)+1;
			currentOutput.println(s);
		}
	}
	/** Output tab indent followed by a String followed by newline,
	 * to the currentOutput stream.  Ignored if string is null.
	 * @param s The string to output
	 */
	protected void println(String s) {
		if (s != null) {
			printTabs();
			outputLine += countLines(s)+1;
			currentOutput.println(s);
		}
	}

	/** Generate a #line or // line depending on options */
	public void genLineNo(int line) {
		if ( line == 0 ) {
			line++;
		}
		if( genHashLines )
			_println("#line "+line+" \""+antlrTool.fileMinusPath(antlrTool.grammarFile)+"\"");
	}

	/** Generate a #line or // line depending on options */
	public void genLineNo(GrammarElement el)
	{
		if( el != null )
			genLineNo(el.getLine());
	}
	/** Generate a #line or // line depending on options */
	public void genLineNo(Token t)
	{
		if (t != null)
			genLineNo(t.getLine());
	}
	/** Generate a #line or // line depending on options */
	public void genLineNo2()
	{
		if( genHashLines )
		{
			_println("#line "+(outputLine+1)+" \""+outputFile+"\"");
		}
	}
	/// Bound safe isDigit
	private boolean charIsDigit( String s, int i )
	{
		return (i < s.length()) && Character.isDigit(s.charAt(i));
	}
	/** Normalize a string coming from antlr's lexer. E.g. translate java
	 * escapes to values. Check their size (multibyte) bomb out if they are
	 * multibyte (bit crude). Then reescape to C++ style things.
	 * Used to generate strings for match() and matchRange()
	 * @param lit the literal string
	 * @param isCharLiteral if it's for a character literal
	 *                       (enforced to be one length) and enclosed in '
	 * FIXME: bombing out on mb chars. Should be done in Lexer.
	 * FIXME: this is another horrible hack.
	 * FIXME: life would be soooo much easier if the stuff from the lexer was
	 * normalized in some way.
	 */
	private String convertJavaToCppString( String lit, boolean isCharLiteral )
	{
		// System.out.println("convertJavaToCppLiteral: "+lit);
		String ret = new String();
		String s = lit;

		int i = 0;
		int val = 0;

		if( isCharLiteral )	// verify & strip off quotes
		{
			if( ! lit.startsWith("'") || ! lit.endsWith("'") )
				antlrTool.error("Invalid character literal: '"+lit+"'");
		}
		else
		{
			if( ! lit.startsWith("\"") || ! lit.endsWith("\"") )
				antlrTool.error("Invalid character string: '"+lit+"'");
		}
		s = lit.substring(1,lit.length()-1);

		String prefix="";
		int maxsize = 255;
		if( grammar instanceof LexerGrammar )
		{
			// vocab size seems to be 1 bigger than it actually is
			maxsize = ((LexerGrammar)grammar).charVocabulary.size() - 1;
			if( maxsize > 255 )
				prefix= "L";
		}

		// System.out.println("maxsize "+maxsize+" prefix "+prefix);

		while ( i < s.length() )
		{
			if( s.charAt(i) == '\\' )
			{
				if( s.length() == i+1 )
					antlrTool.error("Invalid escape in char literal: '"+lit+"' looking at '"+s.substring(i)+"'");

				// deal with escaped junk
				switch ( s.charAt(i+1) ) {
				case 'a' :
					val = 7;
					i += 2;
					break;
				case 'b' :
					val = 8;
					i += 2;
					break;
				case 't' :
					val = 9;
					i += 2;
					break;
				case 'n' :
					val = 10;
					i += 2;
					break;
				case 'f' :
					val = 12;
					i += 2;
					break;
				case 'r' :
					val = 13;
					i += 2;
					break;
				case '"' :
				case '\'' :
				case '\\' :
					val = s.charAt(i+1);
					i += 2;
					break;

				case 'u' :
					// Unicode char \u1234
					if( i+5 < s.length() )
					{
						val = Character.digit(s.charAt(i+2), 16) * 16 * 16 * 16 +
							Character.digit(s.charAt(i+3), 16) * 16 * 16 +
							Character.digit(s.charAt(i+4), 16) * 16 +
							Character.digit(s.charAt(i+5), 16);
						i += 6;
					}
					else
						antlrTool.error("Invalid escape in char literal: '"+lit+"' looking at '"+s.substring(i)+"'");
					break;

				case '0' :					// \123
				case '1' :
				case '2' :
				case '3' :
					if( charIsDigit(s, i+2) )
					{
						if( charIsDigit(s, i+3) )
						{
							val = (s.charAt(i+1)-'0')*8*8 + (s.charAt(i+2)-'0')*8 +
								(s.charAt(i+3)-'0');
							i += 4;
						}
						else
						{
							val = (s.charAt(i+1)-'0')*8 + (s.charAt(i+2)-'0');
							i += 3;
						}
					}
					else
					{
						val = s.charAt(i+1)-'0';
						i += 2;
					}
					break;

				case '4' :
				case '5' :
				case '6' :
				case '7' :
					if ( charIsDigit(s, i+2) )
					{
						val = (s.charAt(i+1)-'0')*8 + (s.charAt(i+2)-'0');
						i += 3;
					}
					else
					{
						val = s.charAt(i+1)-'0';
						i += 2;
					}
				default:
					antlrTool.error("Unhandled escape in char literal: '"+lit+"' looking at '"+s.substring(i)+"'");
					val = 0;
				}
			}
			else
				val = s.charAt(i++);

			if( grammar instanceof LexerGrammar )
			{
				if( val > maxsize )			// abort if too big
				{
					String offender;
					if( ( 0x20 <= val ) && ( val < 0x7F ) )
						offender = charFormatter.escapeChar(val,true);
					else
						offender = "0x"+Integer.toString(val,16);

					antlrTool.error("Character out of range in "+(isCharLiteral?"char literal":"string constant")+": '"+s+"'");
					antlrTool.error("Vocabulary size: "+maxsize+" Character "+offender);
				}
			}

			if( isCharLiteral )
			{
				// we should be at end of char literal here..
				if( i != s.length() )
					antlrTool.error("Invalid char literal: '"+lit+"'");

				if( maxsize <= 255 )
				{
					if ( (val <= 255) && (val & 0x80) != 0 )
						// the joys of sign extension in the support lib *cough*
						// actually the support lib needs to be fixed but that's a bit
						// hairy too.
						ret = "static_cast<unsigned char>('"+charFormatter.escapeChar(val,true)+"')";
					else
						ret = "'"+charFormatter.escapeChar(val,true)+"'";
				}
				else
				{
					// so wchar_t is some implementation defined int like thing
					// so this may even lead to having 16 bit or 32 bit cases...
					// I smell some extra grammar options in the future :(
					ret = "L'"+charFormatter.escapeChar(val,true)+"'";
				}
			}
			else
				ret += charFormatter.escapeChar(val,true);
		}
		if( !isCharLiteral )
			ret = prefix+"\""+ret+"\"";
		return ret;
	}
	/** Generate the parser, lexer, treeparser, and token types in C++
	 */
	public void gen() {
		// Do the code generation
		try {
			// Loop over all grammars
			Enumeration grammarIter = behavior.grammars.elements();
			while (grammarIter.hasMoreElements()) {
				Grammar g = (Grammar)grammarIter.nextElement();
				if ( g.debuggingOutput ) {
					antlrTool.error(g.getFilename()+": C++ mode does not support -debug");
				}
				// Connect all the components to each other
				g.setGrammarAnalyzer(analyzer);
				g.setCodeGenerator(this);
				analyzer.setGrammar(g);
				// To get right overloading behavior across hetrogeneous grammars
				setupGrammarParameters(g);
				g.generate();
				exitIfError();
			}

			// Loop over all token managers (some of which are lexers)
			Enumeration tmIter = behavior.tokenManagers.elements();
			while (tmIter.hasMoreElements()) {
				TokenManager tm = (TokenManager)tmIter.nextElement();
				if (!tm.isReadOnly()) {
					// Write the token manager tokens as C++
					// this must appear before genTokenInterchange so that
					// labels are set on string literals
					genTokenTypes(tm);
					// Write the token manager tokens as plain text
					genTokenInterchange(tm);
				}
				exitIfError();
			}
		}
		catch (IOException e) {
			antlrTool.reportException(e, null);
		}
	}
	/** Generate code for the given grammar element.
	 * @param blk The {...} action to generate
	 */
	public void gen(ActionElement action) {
		if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genAction("+action+")");
		if ( action.isSemPred ) {
			genSemPred(action.actionText, action.line);
		}
		else {
			if ( grammar.hasSyntacticPredicate ) {
				println("if ( inputState->guessing==0 ) {");
				tabs++;
			}

			ActionTransInfo tInfo = new ActionTransInfo();
			String actionStr = processActionForSpecialSymbols(action.actionText,
																			  action.getLine(),
																			  currentRule, tInfo);

			if ( tInfo.refRuleRoot!=null ) {
				// Somebody referenced "#rule", make sure translated var is valid
				// assignment to #rule is left as a ref also, meaning that assignments
				// with no other refs like "#rule = foo();" still forces this code to be
				// generated (unnecessarily).
				println(tInfo.refRuleRoot + " = "+labeledElementASTType+"(currentAST.root);");
			}

			// dump the translated action
			genLineNo(action);
			printAction(actionStr);
			genLineNo2();

			if ( tInfo.assignToRoot ) {
				// Somebody did a "#rule=", reset internal currentAST.root
				println("currentAST.root = "+tInfo.refRuleRoot+";");
				// reset the child pointer too to be last sibling in sibling list
				// now use if else in stead of x ? y : z to shut CC 4.2 up.
				println("if ( "+tInfo.refRuleRoot+"!="+labeledElementASTInit+" &&");
				tabs++;
				println(tInfo.refRuleRoot+"->getFirstChild() != "+labeledElementASTInit+" )");
				println("  currentAST.child = "+tInfo.refRuleRoot+"->getFirstChild();");
			  	tabs--;
				println("else");
				tabs++;
				println("currentAST.child = "+tInfo.refRuleRoot+";");
				tabs--;
				println("currentAST.advanceChildToEnd();");
			}

			if ( grammar.hasSyntacticPredicate ) {
				tabs--;
				println("}");
			}
		}
	}

	/** Generate code for the given grammar element.
	 * @param blk The "x|y|z|..." block to generate
	 */
	public void gen(AlternativeBlock blk) {
		if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("gen("+blk+")");
		println("{");
		genBlockPreamble(blk);
		genBlockInitAction(blk);

		// Tell AST generation to build subrule result
		String saveCurrentASTResult = currentASTResult;
		if (blk.getLabel() != null) {
			currentASTResult = blk.getLabel();
		}

		boolean ok = grammar.theLLkAnalyzer.deterministic(blk);

		CppBlockFinishingInfo howToFinish = genCommonBlock(blk, true);
		genBlockFinish(howToFinish, throwNoViable);

		println("}");

		// Restore previous AST generation
		currentASTResult = saveCurrentASTResult;
	}
	/** Generate code for the given grammar element.
	 * @param blk The block-end element to generate.  Block-end
	 * elements are synthesized by the grammar parser to represent
	 * the end of a block.
	 */
	public void gen(BlockEndElement end) {
		if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genRuleEnd("+end+")");
	}
	/** Generate code for the given grammar element.
	 * Only called from lexer grammars.
	 * @param blk The character literal reference to generate
	 */
	public void gen(CharLiteralElement atom) {
		if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR )
			System.out.println("genChar("+atom+")");

		if ( ! (grammar instanceof LexerGrammar) )
			antlrTool.error("cannot ref character literals in grammar: "+atom);

		if ( atom.getLabel() != null ) {
			println(atom.getLabel() + " = " + lt1Value + ";");
		}

		boolean oldsaveText = saveText;
		saveText = saveText && atom.getAutoGenType() == GrammarElement.AUTO_GEN_NONE;

		// if in lexer and ! on element, save buffer index to kill later
		if ( !saveText||atom.getAutoGenType()==GrammarElement.AUTO_GEN_BANG )
			println("_saveIndex = text.length();");

		print(atom.not ? "matchNot(" : "match(");
		_print(convertJavaToCppString( atom.atomText, true ));
		_println(" /* charlit */ );");

		if ( !saveText || atom.getAutoGenType() == GrammarElement.AUTO_GEN_BANG )
			println("text.erase(_saveIndex);");      // kill text atom put in buffer

		saveText = oldsaveText;
	}
	/** Generate code for the given grammar element.
	 * Only called from lexer grammars.
	 * @param blk The character-range reference to generate
	 */
	public void gen(CharRangeElement r) {
		if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR )
			System.out.println("genCharRangeElement("+r.beginText+".."+r.endText+")");

		if ( ! (grammar instanceof LexerGrammar) )
			antlrTool.error("cannot ref character range in grammar: "+r);

		if ( r.getLabel() != null && syntacticPredLevel == 0) {
			println(r.getLabel() + " = " + lt1Value + ";");
		}
		// Correctly take care of saveIndex stuff...
		boolean save = ( grammar instanceof LexerGrammar &&
							  ( !saveText ||
								 r.getAutoGenType() == GrammarElement.AUTO_GEN_BANG )
						   );
		if (save)
         println("_saveIndex=text.length();");

		println("matchRange("+convertJavaToCppString(r.beginText,true)+
				  ","+convertJavaToCppString(r.endText,true)+");");

		if (save)
         println("text.erase(_saveIndex);");
	}
	/** Generate the lexer C++ files */
	public  void gen(LexerGrammar g) throws IOException {
		// If debugging, create a new sempred vector for this grammar
		if (g.debuggingOutput)
			semPreds = new Vector();

		if( g.charVocabulary.size() > 256 )
			antlrTool.warning(g.getFilename()+": Vocabularies of this size still experimental in C++ mode (vocabulary size now: "+g.charVocabulary.size()+")");

		setGrammar(g);
		if (!(grammar instanceof LexerGrammar)) {
			antlrTool.panic("Internal error generating lexer");
		}

		genBody(g);
		genInclude(g);
	}
	/** Generate code for the given grammar element.
	 * @param blk The (...)+ block to generate
	 */
	public void gen(OneOrMoreBlock blk) {
		if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("gen+("+blk+")");
		String label;
		String cnt;
		println("{ // ( ... )+");
		genBlockPreamble(blk);
		if ( blk.getLabel() != null ) {
			cnt = "_cnt_"+blk.getLabel();
		}
		else {
			cnt = "_cnt" + blk.ID;
		}
		println("int "+cnt+"=0;");
		if ( blk.getLabel() != null ) {
			label = blk.getLabel();
		}
		else {
			label = "_loop" + blk.ID;
		}

		println("for (;;) {");
		tabs++;
		// generate the init action for ()+ ()* inside the loop
		// this allows us to do usefull EOF checking...
		genBlockInitAction(blk);

		// Tell AST generation to build subrule result
		String saveCurrentASTResult = currentASTResult;
		if (blk.getLabel() != null) {
			currentASTResult = blk.getLabel();
		}

		boolean ok = grammar.theLLkAnalyzer.deterministic(blk);

		// generate exit test if greedy set to false
		// and an alt is ambiguous with exit branch
		// or when lookahead derived purely from end-of-file
		// Lookahead analysis stops when end-of-file is hit,
		// returning set {epsilon}.  Since {epsilon} is not
		// ambig with any real tokens, no error is reported
		// by deterministic() routines and we have to check
		// for the case where the lookahead depth didn't get
		// set to NONDETERMINISTIC (this only happens when the
		// FOLLOW contains real atoms + epsilon).
		boolean generateNonGreedyExitPath = false;
		int nonGreedyExitDepth = grammar.maxk;

		if ( !blk.greedy &&
			 blk.exitLookaheadDepth<=grammar.maxk &&
			 blk.exitCache[blk.exitLookaheadDepth].containsEpsilon() )
		{
			generateNonGreedyExitPath = true;
			nonGreedyExitDepth = blk.exitLookaheadDepth;
		}
		else if ( !blk.greedy &&
				  blk.exitLookaheadDepth==LLkGrammarAnalyzer.NONDETERMINISTIC )
		{
			generateNonGreedyExitPath = true;
		}

		// generate exit test if greedy set to false
		// and an alt is ambiguous with exit branch
		if ( generateNonGreedyExitPath ) {
			if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) {
				System.out.println("nongreedy (...)+ loop; exit depth is "+
								   blk.exitLookaheadDepth);
			}
			String predictExit =
				getLookaheadTestExpression(blk.exitCache,
										   nonGreedyExitDepth);
			println("// nongreedy exit test");
			println("if ( "+cnt+">=1 && "+predictExit+") goto "+label+";");
		}

		CppBlockFinishingInfo howToFinish = genCommonBlock(blk, false);
		genBlockFinish(
			howToFinish,
			"if ( "+cnt+">=1 ) { goto "+label+"; } else {" + throwNoViable + "}"
		);

		println(cnt+"++;");
		tabs--;
		println("}");
		println(label+":;");
		println("}  // ( ... )+");

		// Restore previous AST generation
		currentASTResult = saveCurrentASTResult;
	}
	/** Generate the parser C++ file */
	public void gen(ParserGrammar g) throws IOException {

		// if debugging, set up a new vector to keep track of sempred
		//   strings for this grammar
		if (g.debuggingOutput)
			semPreds = new Vector();

		setGrammar(g);
		if (!(grammar instanceof ParserGrammar)) {
			antlrTool.panic("Internal error generating parser");
		}

		genBody(g);
		genInclude(g);
	}
	/** Generate code for the given grammar element.
	 * @param blk The rule-reference to generate
	 */
	public void gen(RuleRefElement rr)
	{
		if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genRR("+rr+")");
		RuleSymbol rs = (RuleSymbol)grammar.getSymbol(rr.targetRule);
		if (rs == null || !rs.isDefined())
		{
			// Is this redundant???
			antlrTool.error("Rule '" + rr.targetRule + "' is not defined", grammar.getFilename(), rr.getLine(), rr.getColumn());
			return;
		}
		if (!(rs instanceof RuleSymbol))
		{
			// Is this redundant???
			antlrTool.error("'" + rr.targetRule + "' does not name a grammar rule", grammar.getFilename(), rr.getLine(), rr.getColumn());
			return;
		}

		genErrorTryForElement(rr);

		// AST value for labeled rule refs in tree walker.
		// This is not AST construction;  it is just the input tree node value.
		if ( grammar instanceof TreeWalkerGrammar &&
			rr.getLabel() != null &&
			syntacticPredLevel == 0 )
		{
			println(rr.getLabel() + " = (_t == ASTNULL) ? "+labeledElementASTInit+" : "+lt1Value+";");
		}

		// if in lexer and ! on rule ref or alt or rule, save buffer index to
		// kill later
		if ( grammar instanceof LexerGrammar && (!saveText||rr.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) )
		{
			println("_saveIndex = text.length();");
		}

		// Process return value assignment if any
		printTabs();
		if (rr.idAssign != null)
		{
			// Warn if the rule has no return type
			if (rs.block.returnAction == null)
			{
				antlrTool.warning("Rule '" + rr.targetRule + "' has no return type", grammar.getFilename(), rr.getLine(), rr.getColumn());
			}
			_print(rr.idAssign + "=");
		} else {
			// Warn about return value if any, but not inside syntactic predicate
			if ( !(grammar instanceof LexerGrammar) && syntacticPredLevel == 0 && rs.block.returnAction != null)
			{
				antlrTool.warning("Rule '" + rr.targetRule + "' returns a value", grammar.getFilename(), rr.getLine(), rr.getColumn());
			}
		}

		// Call the rule
		GenRuleInvocation(rr);

		// if in lexer and ! on element or alt or rule, save buffer index to kill later
		if ( grammar instanceof LexerGrammar && (!saveText||rr.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
			println("text.erase(_saveIndex);");
		}

		// if not in a syntactic predicate
		if (syntacticPredLevel == 0)
		{
			boolean doNoGuessTest = (
				grammar.hasSyntacticPredicate &&
				(
					grammar.buildAST && rr.getLabel() != null ||
					(genAST && rr.getAutoGenType() == GrammarElement.AUTO_GEN_NONE)
				)
			);

			if (doNoGuessTest) {
				println("if (inputState->guessing==0) {");
				tabs++;
			}

			if (grammar.buildAST && rr.getLabel() != null)
			{
				// always gen variable for rule return on labeled rules
				// RK: hmm do I know here if the returnAST needs a cast ?
				println(rr.getLabel() + "_AST = returnAST;");
			}

			if (genAST)
			{
				switch (rr.getAutoGenType())
				{
				case GrammarElement.AUTO_GEN_NONE:
					if( usingCustomAST )
						println("astFactory->addASTChild(currentAST, "+namespaceAntlr+"RefAST(returnAST));");
					else
						println("astFactory->addASTChild( currentAST, returnAST );");
					break;
				case GrammarElement.AUTO_GEN_CARET:
					// FIXME: RK: I'm not so sure this should be an error..
					// I think it might actually work and be usefull at times.
					antlrTool.error("Internal: encountered ^ after rule reference");
					break;
				default:
					break;
				}
			}

			// if a lexer and labeled, Token label defined at rule level, just set it here
			if ( grammar instanceof LexerGrammar && rr.getLabel() != null )
			{
				println(rr.getLabel()+"=_returnToken;");
			}

			if (doNoGuessTest)
			{
				tabs--;
				println("}");
			}
		}
		genErrorCatchForElement(rr);
	}
	/** Generate code for the given grammar element.
	 * @param blk The string-literal reference to generate
	 */
	public void gen(StringLiteralElement atom) {
		if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genString("+atom+")");

		// Variable declarations for labeled elements
		if (atom.getLabel()!=null && syntacticPredLevel == 0) {
			println(atom.getLabel() + " = " + lt1Value + ";");
		}

		// AST
		genElementAST(atom);

		// is there a bang on the literal?
		boolean oldsaveText = saveText;
		saveText = saveText && atom.getAutoGenType()==GrammarElement.AUTO_GEN_NONE;

		// matching
		genMatch(atom);

		saveText = oldsaveText;

		// tack on tree cursor motion if doing a tree walker
		if (grammar instanceof TreeWalkerGrammar) {
			println("_t = _t->getNextSibling();");
		}
	}
	/** Generate code for the given grammar element.
	 * @param blk The token-range reference to generate
	 */
	public void gen(TokenRangeElement r) {
		genErrorTryForElement(r);
		if ( r.getLabel()!=null  && syntacticPredLevel == 0) {
			println(r.getLabel() + " = " + lt1Value + ";");
		}

		// AST
		genElementAST(r);

		// match
		println("matchRange("+r.beginText+","+r.endText+");");
		genErrorCatchForElement(r);
	}
	/** Generate code for the given grammar element.
	 * @param blk The token-reference to generate
	 */
	public void gen(TokenRefElement atom) {
		if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genTokenRef("+atom+")");
		if ( grammar instanceof LexerGrammar ) {
			antlrTool.panic("Token reference found in lexer");
		}
		genErrorTryForElement(atom);
		// Assign Token value to token label variable
		if ( atom.getLabel()!=null && syntacticPredLevel == 0) {
			println(atom.getLabel() + " = " + lt1Value + ";");
		}

		// AST
		genElementAST(atom);
		// matching
		genMatch(atom);
		genErrorCatchForElement(atom);

		// tack on tree cursor motion if doing a tree walker
		if (grammar instanceof TreeWalkerGrammar) {
			println("_t = _t->getNextSibling();");
		}
	}
	public void gen(TreeElement t) {
		// save AST cursor
		println(labeledElementType+" __t" + t.ID + " = _t;");

		// If there is a label on the root, then assign that to the variable
		if (t.root.getLabel() != null) {
			println(t.root.getLabel() + " = (_t == "+labeledElementType+"(ASTNULL)) ? "+labeledElementASTInit+" : _t;");
		}

		// check for invalid modifiers ! and ^ on tree element roots
		if ( t.root.getAutoGenType() == GrammarElement.AUTO_GEN_BANG ) {
			antlrTool.error("Suffixing a root node with '!' is not implemented",
						  grammar.getFilename(), t.getLine(), t.getColumn());
			t.root.setAutoGenType(GrammarElement.AUTO_GEN_NONE);
		}
		if ( t.root.getAutoGenType() == GrammarElement.AUTO_GEN_CARET ) {
			antlrTool.warning("Suffixing a root node with '^' is redundant; already a root",
							 grammar.getFilename(), t.getLine(), t.getColumn());
			t.root.setAutoGenType(GrammarElement.AUTO_GEN_NONE);
		}

		// Generate AST variables
		genElementAST(t.root);
		if (grammar.buildAST) {
			// Save the AST construction state
			println(namespaceAntlr+"ASTPair __currentAST" + t.ID + " = currentAST;");
			// Make the next item added a child of the TreeElement root
			println("currentAST.root = currentAST.child;");
			println("currentAST.child = "+labeledElementASTInit+";");
		}

		// match root
		if ( t.root instanceof WildcardElement ) {
			println("if ( _t == ASTNULL ) throw "+namespaceAntlr+"MismatchedTokenException();");
		}
		else {
			genMatch(t.root);
		}
		// move to list of children
		println("_t = _t->getFirstChild();");

		// walk list of children, generating code for each
		for (int i=0; i<t.getAlternatives().size(); i++) {
			Alternative a = t.getAlternativeAt(i);
			AlternativeElement e = a.head;
			while ( e != null ) {
				e.generate();
				e = e.next;
			}
		}

		if (grammar.buildAST) {
			// restore the AST construction state to that just after the
			// tree root was added
			println("currentAST = __currentAST" + t.ID + ";");
		}
		// restore AST cursor
		println("_t = __t" + t.ID + ";");
		// move cursor to sibling of tree just parsed
		println("_t = _t->getNextSibling();");
	}
	/** Generate the tree-parser C++ files */
	public void gen(TreeWalkerGrammar g) throws IOException {
		setGrammar(g);
		if (!(grammar instanceof TreeWalkerGrammar)) {
			antlrTool.panic("Internal error generating tree-walker");
		}

		genBody(g);
		genInclude(g);
	}
	/** Generate code for the given grammar element.
	 * @param wc The wildcard element to generate
	 */
	public void gen(WildcardElement wc) {
		// Variable assignment for labeled elements
		if (wc.getLabel()!=null && syntacticPredLevel == 0) {
			println(wc.getLabel() + " = " + lt1Value + ";");
		}

		// AST
		genElementAST(wc);
		// Match anything but EOF
		if (grammar instanceof TreeWalkerGrammar) {
			println("if ( _t == "+labeledElementASTInit+" ) throw "+namespaceAntlr+"MismatchedTokenException();");
		}
		else if (grammar instanceof LexerGrammar) {
			if ( grammar instanceof LexerGrammar &&
					(!saveText||wc.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
				println("_saveIndex = text.length();");
			}
			println("matchNot(EOF/*_CHAR*/);");
			if ( grammar instanceof LexerGrammar &&
					(!saveText||wc.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
				println("text.erase(_saveIndex);");      // kill text atom put in buffer
			}
		}
		else {
			println("matchNot(" + getValueString(Token.EOF_TYPE) + ");");
		}

		// tack on tree cursor motion if doing a tree walker
		if (grammar instanceof TreeWalkerGrammar) {
			println("_t = _t->getNextSibling();");
		}
	}
	/** Generate code for the given grammar element.
	 * @param blk The (...)* block to generate
	 */
	public void gen(ZeroOrMoreBlock blk) {
		if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("gen*("+blk+")");
		println("{ // ( ... )*");
		genBlockPreamble(blk);
		String label;
		if ( blk.getLabel() != null ) {
			label = blk.getLabel();
		}
		else {
			label = "_loop" + blk.ID;
		}
		println("for (;;) {");
		tabs++;
		// generate the init action for ()+ ()* inside the loop
		// this allows us to do usefull EOF checking...
		genBlockInitAction(blk);

		// Tell AST generation to build subrule result
		String saveCurrentASTResult = currentASTResult;
		if (blk.getLabel() != null) {
			currentASTResult = blk.getLabel();
		}

		boolean ok = grammar.theLLkAnalyzer.deterministic(blk);

		// generate exit test if greedy set to false
		// and an alt is ambiguous with exit branch
		// or when lookahead derived purely from end-of-file
		// Lookahead analysis stops when end-of-file is hit,
		// returning set {epsilon}.  Since {epsilon} is not
		// ambig with any real tokens, no error is reported
		// by deterministic() routines and we have to check
		// for the case where the lookahead depth didn't get
		// set to NONDETERMINISTIC (this only happens when the
		// FOLLOW contains real atoms + epsilon).
		boolean generateNonGreedyExitPath = false;
		int nonGreedyExitDepth = grammar.maxk;

		if ( !blk.greedy &&
			 blk.exitLookaheadDepth<=grammar.maxk &&
			 blk.exitCache[blk.exitLookaheadDepth].containsEpsilon() )
		{
			generateNonGreedyExitPath = true;
			nonGreedyExitDepth = blk.exitLookaheadDepth;
		}
		else if ( !blk.greedy &&
				  blk.exitLookaheadDepth==LLkGrammarAnalyzer.NONDETERMINISTIC )
		{
			generateNonGreedyExitPath = true;
		}
		if ( generateNonGreedyExitPath ) {
			if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) {
				System.out.println("nongreedy (...)* loop; exit depth is "+
								   blk.exitLookaheadDepth);
			}
			String predictExit =
				getLookaheadTestExpression(blk.exitCache,
										   nonGreedyExitDepth);
			println("// nongreedy exit test");
			println("if ("+predictExit+") goto "+label+";");
		}

		CppBlockFinishingInfo howToFinish = genCommonBlock(blk, false);
		genBlockFinish(howToFinish, "goto " + label + ";");

		tabs--;
		println("}");
		println(label+":;");
		println("} // ( ... )*");

		// Restore previous AST generation
		currentASTResult = saveCurrentASTResult;
	}
	/** Generate an alternative.
	  * @param alt  The alternative to generate
	  * @param blk The block to which the alternative belongs
	  */
	protected void genAlt(Alternative alt, AlternativeBlock blk)
	{
		// Save the AST generation state, and set it to that of the alt
		boolean savegenAST = genAST;
		genAST = genAST && alt.getAutoGen();

		boolean oldsaveTest = saveText;
		saveText = saveText && alt.getAutoGen();

		// Reset the variable name map for the alternative
		Hashtable saveMap = treeVariableMap;
		treeVariableMap = new Hashtable();

		// Generate try block around the alt for  error handling
		if (alt.exceptionSpec != null) {
			println("try {      // for error handling");
			tabs++;
		}

		AlternativeElement elem = alt.head;
		while ( !(elem instanceof BlockEndElement) ) {
			elem.generate(); // alt can begin with anything. Ask target to gen.
			elem = elem.next;
		}

		if ( genAST)
		{
			if (blk instanceof RuleBlock)
			{
				// Set the AST return value for the rule
				RuleBlock rblk = (RuleBlock)blk;
				if( usingCustomAST )
					println(rblk.getRuleName() + "_AST = "+labeledElementASTType+"(currentAST.root);");
				else
					println(rblk.getRuleName() + "_AST = currentAST.root;");
			}
			else if (blk.getLabel() != null) {
				// ### future: also set AST value for labeled subrules.
				// println(blk.getLabel() + "_AST = "+labeledElementASTType+"(currentAST.root);");
				antlrTool.warning("Labeled subrules are not implemented", grammar.getFilename(), blk.getLine(), blk.getColumn());
			}
		}

		if (alt.exceptionSpec != null)
		{
			// close try block
			tabs--;
			println("}");
			genErrorHandler(alt.exceptionSpec);
		}

		genAST = savegenAST;
		saveText = oldsaveTest;

		treeVariableMap = saveMap;
	}
	/** Generate all the bitsets to be used in the parser or lexer
	 * Generate the raw bitset data like "long _tokenSet1_data[] = {...};"
	 * and the BitSet object declarations like
	 * "BitSet _tokenSet1 = new BitSet(_tokenSet1_data);"
	 * Note that most languages do not support object initialization inside a
	 * class definition, so other code-generators may have to separate the
	 * bitset declarations from the initializations (e.g., put the
	 * initializations in the generated constructor instead).
	 * @param bitsetList The list of bitsets to generate.
	 * @param maxVocabulary Ensure that each generated bitset can contain at
	 *        least this value.
	 * @param prefix string glued in from of bitset names used for namespace
	 *        qualifications.
	 */
	protected void genBitsets(
		Vector bitsetList,
		int maxVocabulary,
		String prefix
	)
	{
		TokenManager tm = grammar.tokenManager;

		println("");

		for (int i = 0; i < bitsetList.size(); i++)
		{
			BitSet p = (BitSet)bitsetList.elementAt(i);
			// Ensure that generated BitSet is large enough for vocabulary
			p.growToInclude(maxVocabulary);

			// initialization data
			println(
				"const unsigned long " + prefix + getBitsetName(i) + "_data_" + "[] = { " +
				p.toStringOfHalfWords() +
				" };"
			);

			// Dump the contents of the bitset in readable format...
			String t = "// ";

			for( int j = 0; j < tm.getVocabulary().size(); j++ )
			{
				if ( p.member( j ) )
				{
					if ( (grammar instanceof LexerGrammar) )
					{
						// only dump out for pure printable ascii.
						if( ( 0x20 <= j ) && ( j < 0x7F ) && (j != '\\') )
							t += charFormatter.escapeChar(j,true)+" ";
						else
							t += "0x"+Integer.toString(j,16)+" ";
					}
					else
						t += tm.getTokenStringAt(j)+" ";

					if( t.length() > 70 )
					{
						println(t);
						t = "// ";
					}
				}
			}
			if ( t != "// " )
				println(t);

			// BitSet object
			println(
				"const "+namespaceAntlr+"BitSet " + prefix + getBitsetName(i) + "(" +
				getBitsetName(i) + "_data_," + p.size()/32 +
				");"
			);
		}
	}
	protected void genBitsetsHeader(
		Vector bitsetList,
		int maxVocabulary
	) {
		println("");
		for (int i = 0; i < bitsetList.size(); i++)
		{
			BitSet p = (BitSet)bitsetList.elementAt(i);
			// Ensure that generated BitSet is large enough for vocabulary
			p.growToInclude(maxVocabulary);
			// initialization data
			println("static const unsigned long " + getBitsetName(i) + "_data_" + "[];");
			// BitSet object
			println("static const "+namespaceAntlr+"BitSet " + getBitsetName(i) + ";");
		}
	}
	/** Generate the finish of a block, using a combination of the info
	 * returned from genCommonBlock() and the action to perform when
	 * no alts were taken
	 * @param howToFinish The return of genCommonBlock()
	 * @param noViableAction What to generate when no alt is taken
	 */
	private void genBlockFinish(CppBlockFinishingInfo howToFinish, String noViableAction)
	{
		if (howToFinish.needAnErrorClause &&
			 (howToFinish.generatedAnIf || howToFinish.generatedSwitch)) {
			if ( howToFinish.generatedAnIf ) {
				println("else {");
			}
			else {
				println("{");
			}
			tabs++;
			println(noViableAction);
			tabs--;
			println("}");
		}

		if ( howToFinish.postscript!=null ) {
			println(howToFinish.postscript);
		}
	}
	/** Generate the initaction for a block, which may be a RuleBlock or a
	 * plain AlternativeBLock.
	 * @blk The block for which the preamble is to be generated.
	 */
	protected void genBlockInitAction( AlternativeBlock blk )
	{
		// dump out init action
		if ( blk.initAction!=null ) {
			genLineNo(blk);
			printAction(processActionForSpecialSymbols(blk.initAction, blk.line,
																	 currentRule, null) );
			genLineNo2();
		}
	}
	/** Generate the header for a block, which may be a RuleBlock or a
	 * plain AlternativeBlock. This generates any variable declarations
	 * and syntactic-predicate-testing variables.
	 * @blk The block for which the preamble is to be generated.
	 */
	protected void genBlockPreamble(AlternativeBlock blk) {
		// define labels for rule blocks.
		if ( blk instanceof RuleBlock ) {
			RuleBlock rblk = (RuleBlock)blk;
			if ( rblk.labeledElements!=null ) {
				for (int i=0; i<rblk.labeledElements.size(); i++) {

					AlternativeElement a = (AlternativeElement)rblk.labeledElements.elementAt(i);
					//System.out.println("looking at labeled element: "+a);
					// Variables for labeled rule refs and subrules are different than
					// variables for grammar atoms.  This test is a little tricky because
					// we want to get all rule refs and ebnf, but not rule blocks or
					// syntactic predicates
					if (
						a instanceof RuleRefElement ||
						a instanceof AlternativeBlock &&
						!(a instanceof RuleBlock) &&
						!(a instanceof SynPredBlock) )
					{
						if ( !(a instanceof RuleRefElement) &&
							  ((AlternativeBlock)a).not &&
							  analyzer.subruleCanBeInverted(((AlternativeBlock)a), grammar instanceof LexerGrammar)
						) {
							// Special case for inverted subrules that will be
							// inlined. Treat these like token or char literal
							// references
							println(labeledElementType + " " + a.getLabel() + " = " + labeledElementInit + ";");
							if (grammar.buildAST) {
								genASTDeclaration( a );
							}
						}
						else
						{
							if (grammar.buildAST)
							{
								// Always gen AST variables for labeled elements,
								// even if the element itself is marked with !
								genASTDeclaration( a );
							}
							if ( grammar instanceof LexerGrammar )
								println(namespaceAntlr+"RefToken "+a.getLabel()+";");

							if (grammar instanceof TreeWalkerGrammar) {
								// always generate rule-ref variables for tree walker
								println(labeledElementType + " " + a.getLabel() + " = " + labeledElementInit + ";");
							}
						}
					}
					else
					{
						// It is a token or literal reference.  Generate the
						// correct variable type for this grammar
						println(labeledElementType + " " + a.getLabel() + " = " + labeledElementInit + ";");
						// In addition, generate *_AST variables if building ASTs
						if (grammar.buildAST)
						{
							if (a instanceof GrammarAtom &&
								 ((GrammarAtom)a).getASTNodeType() != null )
							{
								GrammarAtom ga = (GrammarAtom)a;
								genASTDeclaration( a, "Ref"+ga.getASTNodeType() );
							}
							else
							{
								genASTDeclaration( a );
							}
						}
					}
				}
			}
		}
	}
	public void genBody(LexerGrammar g) throws IOException
	{
		outputFile = grammar.getClassName() + ".cpp";
		outputLine = 1;
		currentOutput = antlrTool.openOutputFile(outputFile);
		//SAS: changed for proper text file io

		genAST = false;	// no way to gen trees.
		saveText = true;	// save consumed characters.

		tabs=0;

		// Generate header common to all C++ output files
		genHeader(outputFile);

		printHeaderAction(preIncludeCpp);
		// Generate header specific to lexer C++ file
		println("#include \"" + grammar.getClassName() + ".hpp\"");
		println("#include <antlr/CharBuffer.hpp>");
		println("#include <antlr/TokenStreamException.hpp>");
		println("#include <antlr/TokenStreamIOException.hpp>");
		println("#include <antlr/TokenStreamRecognitionException.hpp>");
		println("#include <antlr/CharStreamException.hpp>");
		println("#include <antlr/CharStreamIOException.hpp>");
		println("#include <antlr/NoViableAltForCharException.hpp>");
		if (grammar.debuggingOutput)
			println("#include <antlr/DebuggingInputBuffer.hpp>");
		println("");
		printHeaderAction(postIncludeCpp);

		if (nameSpace != null)
			nameSpace.emitDeclarations(currentOutput);

		// Generate user-defined lexer file preamble
		printAction(grammar.preambleAction);

		// Generate lexer class definition
		String sup=null;
		if ( grammar.superClass!=null ) {
			sup = grammar.superClass;
		}
		else {
			sup = grammar.getSuperClass();
			if (sup.lastIndexOf('.') != -1)
				sup = sup.substring(sup.lastIndexOf('.')+1);
			sup = namespaceAntlr + sup;
		}

		if( noConstructors )
		{
			println("#if 0");
			println("// constructor creation turned of with 'noConstructor' option");
		}
		//
		// Generate the constructor from InputStream
		//
		println(grammar.getClassName() + "::" + grammar.getClassName() + "(" + namespaceStd + "istream& in)");
		tabs++;
		// if debugging, wrap the input buffer in a debugger
		if (grammar.debuggingOutput)
			println(": " + sup + "(new "+namespaceAntlr+"DebuggingInputBuffer(new "+namespaceAntlr+"CharBuffer(in)),"+g.caseSensitive+")");
		else
			println(": " + sup + "(new "+namespaceAntlr+"CharBuffer(in),"+g.caseSensitive+")");
		tabs--;
		println("{");
		tabs++;

		// if debugging, set up array variables and call user-overridable
		//   debugging setup method
		if ( grammar.debuggingOutput ) {
			println("setRuleNames(_ruleNames);");
			println("setSemPredNames(_semPredNames);");
			println("setupDebugging();");
		}

//		println("setCaseSensitive("+g.caseSensitive+");");
		println("initLiterals();");
		tabs--;
		println("}");
		println("");

		// Generate the constructor from InputBuffer
		println(grammar.getClassName() + "::" + grammar.getClassName() + "("+namespaceAntlr+"InputBuffer& ib)");
		tabs++;
		// if debugging, wrap the input buffer in a debugger
		if (grammar.debuggingOutput)
			println(": " + sup + "(new "+namespaceAntlr+"DebuggingInputBuffer(ib),"+g.caseSensitive+")");
		else
			println(": " + sup + "(ib,"+g.caseSensitive+")");
		tabs--;
		println("{");
		tabs++;

		// if debugging, set up array variables and call user-overridable
		//   debugging setup method
		if ( grammar.debuggingOutput ) {
			println("setRuleNames(_ruleNames);");
			println("setSemPredNames(_semPredNames);");
			println("setupDebugging();");
		}

//		println("setCaseSensitive("+g.caseSensitive+");");
		println("initLiterals();");
		tabs--;
		println("}");
		println("");

		// Generate the constructor from LexerSharedInputState
		println(grammar.getClassName() + "::" + grammar.getClassName() + "(const "+namespaceAntlr+"LexerSharedInputState& state)");
		tabs++;
		println(": " + sup + "(state,"+g.caseSensitive+")");
		tabs--;
		println("{");
		tabs++;

		// if debugging, set up array variables and call user-overridable
		//   debugging setup method
		if ( grammar.debuggingOutput ) {
			println("setRuleNames(_ruleNames);");
			println("setSemPredNames(_semPredNames);");
			println("setupDebugging();");
		}

//		println("setCaseSensitive("+g.caseSensitive+");");
		println("initLiterals();");
		tabs--;
		println("}");
		println("");

		if( noConstructors )
		{
			println("// constructor creation turned of with 'noConstructor' option");
			println("#endif");
		}

		println("void " + grammar.getClassName() + "::initLiterals()");
		println("{");
		tabs++;
		// Generate the initialization of the map
		// containing the string literals used in the lexer
		// The literals variable itself is in CharScanner
		Enumeration keys = grammar.tokenManager.getTokenSymbolKeys();
		while ( keys.hasMoreElements() ) {
			String key = (String)keys.nextElement();
			if ( key.charAt(0) != '"' ) {
				continue;
			}
			TokenSymbol sym = grammar.tokenManager.getTokenSymbol(key);
			if ( sym instanceof StringLiteralSymbol ) {
				StringLiteralSymbol s = (StringLiteralSymbol)sym;
				println("literals["+s.getId()+"] = "+s.getTokenType()+";");
			}
		}

		// Generate the setting of various generated options.
		tabs--;
		println("}");

		Enumeration ids;
		// generate the rule name array for debugging
		if (grammar.debuggingOutput) {
			println("const char* "+grammar.getClassName()+"::_ruleNames[] = {");
			tabs++;

			ids = grammar.rules.elements();
			int ruleNum=0;
			while ( ids.hasMoreElements() ) {
				GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
				if ( sym instanceof RuleSymbol)
					println("\""+((RuleSymbol)sym).getId()+"\",");
			}
			println("0");
			tabs--;
			println("};");
		}

		// Generate nextToken() rule.
		// nextToken() is a synthetic lexer rule that is the implicit OR of all
		// user-defined lexer rules.
		genNextToken();

		// Generate code for each rule in the lexer
		ids = grammar.rules.elements();
		int ruleNum=0;
		while ( ids.hasMoreElements() ) {
			RuleSymbol sym = (RuleSymbol) ids.nextElement();
			// Don't generate the synthetic rules
			if (!sym.getId().equals("mnextToken")) {
				genRule(sym, false, ruleNum++, grammar.getClassName() + "::");
			}
			exitIfError();
		}

		// Generate the semantic predicate map for debugging
		if (grammar.debuggingOutput)
			genSemPredMap(grammar.getClassName() + "::");

		// Generate the bitsets used throughout the lexer
		genBitsets(bitsetsUsed, ((LexerGrammar)grammar).charVocabulary.size(), grammar.getClassName() + "::" );

		println("");
		if (nameSpace != null)
			nameSpace.emitClosures(currentOutput);

		// Close the lexer output stream
		currentOutput.close();
		currentOutput = null;
	}
	public void genInitFactory( Grammar g )
	{
		// Generate the method to initialize an ASTFactory when we're
		// building AST's
		String param_name = "factory ";
		if( ! g.buildAST )
			param_name = "";

		println("void "+ g.getClassName() + "::initializeASTFactory( "+namespaceAntlr+"ASTFactory& "+param_name+")");
		println("{");
		tabs++;

		if( g.buildAST )
		{
			// sort out custom AST types... synchronize token manager with token
			// specs on rules (and other stuff we were able to see from
			// action.g) (imperfect of course)
			TokenManager tm = grammar.tokenManager;
			Enumeration tokens = tm.getTokenSymbolKeys();
			while( tokens.hasMoreElements() )
			{
				String tok = (String)tokens.nextElement();
				TokenSymbol ts = tm.getTokenSymbol(tok);
				// if we have a custom type and there's not a more local override
				// of the tokentype then mark this as the type for the tokentype
				if( ts.getASTNodeType() != null )
				{
					// ensure capacity with this pseudo vector...
					astTypes.ensureCapacity(ts.getTokenType());
					String type = (String)astTypes.elementAt(ts.getTokenType());
					if( type == null )
						astTypes.setElementAt(ts.getASTNodeType(),ts.getTokenType());
					else
					{
						// give a warning over action taken if the types are unequal
						if( ! ts.getASTNodeType().equals(type) )
						{
							antlrTool.warning("Token "+tok+" taking most specific AST type",grammar.getFilename(),1,1);
							antlrTool.warning("  using "+type+" ignoring "+ts.getASTNodeType(),grammar.getFilename(),1,1);
						}
					}
				}
			}
			// now actually write out all the registered types. (except the default
			// type.
			for( int i = 0; i < astTypes.size(); i++ )
			{
				String type = (String)astTypes.elementAt(i);
				if( type != null )
				{
					println("factory.registerFactory("+i
						  +", \""+type+"\", "+type+"::factory);");
				}
			}
			println("factory.setMaxNodeType("+grammar.tokenManager.maxTokenType()+");");
		}
		tabs--;
		println("}");
	}
	// FIXME: and so why are we passing here a g param while inside
	// we merrily use the global grammar.
	public void genBody(ParserGrammar g) throws IOException
	{
		// Open the output stream for the parser and set the currentOutput
		outputFile = grammar.getClassName() + ".cpp";
		outputLine = 1;
		currentOutput = antlrTool.openOutputFile(outputFile);

		genAST = grammar.buildAST;

		tabs = 0;

		// Generate the header common to all output files.
		genHeader(outputFile);

		printHeaderAction(preIncludeCpp);

		// Generate header for the parser
		println("#include \"" + grammar.getClassName() + ".hpp\"");
		println("#include <antlr/NoViableAltException.hpp>");
		println("#include <antlr/SemanticException.hpp>");
		println("#include <antlr/ASTFactory.hpp>");

		printHeaderAction(postIncludeCpp);

		if (nameSpace != null)
			nameSpace.emitDeclarations(currentOutput);

		// Output the user-defined parser preamble
		printAction(grammar.preambleAction);

		String sup=null;
		if ( grammar.superClass!=null )
			sup = grammar.superClass;
		else {
			sup = grammar.getSuperClass();
			if (sup.lastIndexOf('.') != -1)
				sup = sup.substring(sup.lastIndexOf('.')+1);
			sup = namespaceAntlr + sup;
		}

		// set up an array of all the rule names so the debugger can
		// keep track of them only by number -- less to store in tree...
		if (grammar.debuggingOutput) {
			println("const char* "+grammar.getClassName()+"::_ruleNames[] = {");
			tabs++;

			Enumeration ids = grammar.rules.elements();
			int ruleNum=0;
			while ( ids.hasMoreElements() ) {
				GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
				if ( sym instanceof RuleSymbol)
					println("\""+((RuleSymbol)sym).getId()+"\",");
			}
			println("0");
			tabs--;
			println("};");
		}

		// Generate _initialize function
		// disabled since it isn't used anymore..

//		println("void " + grammar.getClassName() + "::_initialize(void)");
//		println("{");
//		tabs++;

		// if debugging, set up arrays and call the user-overridable
		//   debugging setup method
//		if ( grammar.debuggingOutput ) {
//			println("setRuleNames(_ruleNames);");
//			println("setSemPredNames(_semPredNames);");
//			println("setupDebugging();");
//		}
//		tabs--;
//		println("}");
		if( noConstructors )
		{
			println("#if 0");
			println("// constructor creation turned of with 'noConstructor' option");
		}

		// Generate parser class constructor from TokenBuffer
		print(grammar.getClassName() + "::" + grammar.getClassName());
		println("("+namespaceAntlr+"TokenBuffer& tokenBuf, int k)");
		println(": " + sup + "(tokenBuf,k)");
		println("{");
//		tabs++;
//		println("_initialize();");
//		tabs--;
		println("}");
		println("");

		print(grammar.getClassName() + "::" + grammar.getClassName());
		println("("+namespaceAntlr+"TokenBuffer& tokenBuf)");
		println(": " + sup + "(tokenBuf," + grammar.maxk + ")");
		println("{");
//		tabs++;
//		println("_initialize();");
//		tabs--;
		println("}");
		println("");

		// Generate parser class constructor from TokenStream
		print(grammar.getClassName() + "::" + grammar.getClassName());
		println("("+namespaceAntlr+"TokenStream& lexer, int k)");
		println(": " + sup + "(lexer,k)");
		println("{");
//		tabs++;
//		println("_initialize();");
//		tabs--;
		println("}");
		println("");

		print(grammar.getClassName() + "::" + grammar.getClassName());
		println("("+namespaceAntlr+"TokenStream& lexer)");
		println(": " + sup + "(lexer," + grammar.maxk + ")");
		println("{");
//		tabs++;
//		println("_initialize();");
//		tabs--;
		println("}");
		println("");

		print(grammar.getClassName() + "::" + grammar.getClassName());
		println("(const "+namespaceAntlr+"ParserSharedInputState& state)");
		println(": " + sup + "(state," + grammar.maxk + ")");
		println("{");
//		tabs++;
//		println("_initialize();");
//		tabs--;
		println("}");
		println("");

		if( noConstructors )
		{
			println("// constructor creation turned of with 'noConstructor' option");
			println("#endif");
		}

		astTypes = new Vector();

		// Generate code for each rule in the grammar
		Enumeration ids = grammar.rules.elements();
		int ruleNum=0;
		while ( ids.hasMoreElements() ) {
			GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
			if ( sym instanceof RuleSymbol) {
				RuleSymbol rs = (RuleSymbol)sym;
				genRule(rs, rs.references.size()==0, ruleNum++, grammar.getClassName() + "::");
			}
			exitIfError();
		}

		genInitFactory( g );

		// Generate the token names
		genTokenStrings(grammar.getClassName() + "::");

		// Generate the bitsets used throughout the grammar
		genBitsets(bitsetsUsed, grammar.tokenManager.maxTokenType(), grammar.getClassName() + "::" );

		// Generate the semantic predicate map for debugging
		if (grammar.debuggingOutput)
			genSemPredMap(grammar.getClassName() + "::");

		// Close class definition
		println("");
		println("");
		if (nameSpace != null)
			nameSpace.emitClosures(currentOutput);

		// Close the parser output stream
		currentOutput.close();
		currentOutput = null;
	}
	public void genBody(TreeWalkerGrammar g) throws IOException
	{
		// Open the output stream for the parser and set the currentOutput
		outputFile = grammar.getClassName() + ".cpp";
		outputLine = 1;
		currentOutput = antlrTool.openOutputFile(outputFile);
		//SAS: changed for proper text file io

		genAST = grammar.buildAST;
		tabs = 0;

		// Generate the header common to all output files.
		genHeader(outputFile);

		printHeaderAction(preIncludeCpp);

		// Generate header for the parser
		println("#include \"" + grammar.getClassName() + ".hpp\"");
		println("#include <antlr/Token.hpp>");
		println("#include <antlr/AST.hpp>");
		println("#include <antlr/NoViableAltException.hpp>");
		println("#include <antlr/MismatchedTokenException.hpp>");
		println("#include <antlr/SemanticException.hpp>");
		println("#include <antlr/BitSet.hpp>");

		printHeaderAction(postIncludeCpp);

		if (nameSpace != null)
			nameSpace.emitDeclarations(currentOutput);

		// Output the user-defined parser premamble
		printAction(grammar.preambleAction);

		// Generate parser class definition
		String sup = null;
		if ( grammar.superClass!=null ) {
			sup = grammar.superClass;
		}
		else {
			sup = grammar.getSuperClass();
			if (sup.lastIndexOf('.') != -1)
				sup = sup.substring(sup.lastIndexOf('.')+1);
			sup = namespaceAntlr + sup;
		}
		if( noConstructors )
		{
			println("#if 0");
			println("// constructor creation turned of with 'noConstructor' option");
		}

		// Generate default parser class constructor
		println(grammar.getClassName() + "::" + grammar.getClassName() + "()");
		println("\t: "+namespaceAntlr+"TreeParser() {");
		tabs++;
//		println("setTokenNames(_tokenNames);");
		tabs--;
		println("}");

		if( noConstructors )
		{
			println("// constructor creation turned of with 'noConstructor' option");
			println("#endif");
		}
		println("");

		astTypes = new Vector();

		// Generate code for each rule in the grammar
		Enumeration ids = grammar.rules.elements();
		int ruleNum=0;
		String ruleNameInits = "";
		while ( ids.hasMoreElements() ) {
			GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
			if ( sym instanceof RuleSymbol) {
				RuleSymbol rs = (RuleSymbol)sym;
				genRule(rs, rs.references.size()==0, ruleNum++, grammar.getClassName() + "::");
			}
			exitIfError();
		}

		// Generate the ASTFactory initialization function
		genInitFactory( grammar );
		// Generate the token names
		genTokenStrings(grammar.getClassName() + "::");

		// Generate the bitsets used throughout the grammar
		genBitsets(bitsetsUsed, grammar.tokenManager.maxTokenType(), grammar.getClassName() + "::" );

		// Close class definition
		println("");
		println("");

		if (nameSpace != null)
			nameSpace.emitClosures(currentOutput);

		// Close the parser output stream
		currentOutput.close();
		currentOutput = null;
	}
	/** Generate a series of case statements that implement a BitSet test.
	 * @param p The Bitset for which cases are to be generated
	 */
	protected void genCases(BitSet p) {
		if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genCases("+p+")");
		int[] elems;

		elems = p.toArray();
		// Wrap cases four-per-line for lexer, one-per-line for parser
		int wrap = 1; //(grammar instanceof LexerGrammar) ? 4 : 1;
		int j=1;
		boolean startOfLine = true;
		for (int i = 0; i < elems.length; i++) {
			if (j==1) {
				print("");
			} else {
				_print("  ");
			}
			_print("case " + getValueString(elems[i]) + ":");

			if (j==wrap) {
				_println("");
				startOfLine = true;
				j=1;
			}
			else {
				j++;
				startOfLine = false;
			}
		}
		if (!startOfLine) {
			_println("");
		}
	}
	/** Generate common code for a block of alternatives; return a postscript
	 * that needs to be generated at the end of the block.  Other routines
	 * may append else-clauses and such for error checking before the postfix
	 * is generated.
	 * If the grammar is a lexer, then generate alternatives in an order where
	 * alternatives requiring deeper lookahead are generated first, and
	 * EOF in the lookahead set reduces the depth of the lookahead.
	 * @param blk The block to generate
	 * @param noTestForSingle If true, then it does not generate a test for a single alternative.
	 */
	public CppBlockFinishingInfo genCommonBlock(
		AlternativeBlock blk,
		boolean noTestForSingle )
	{
		int nIF=0;
		boolean createdLL1Switch = false;
		int closingBracesOfIFSequence = 0;
		CppBlockFinishingInfo finishingInfo = new CppBlockFinishingInfo();
		if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genCommonBlk("+blk+")");

		// Save the AST generation state, and set it to that of the block
		boolean savegenAST = genAST;
		genAST = genAST && blk.getAutoGen();

		boolean oldsaveTest = saveText;
		saveText = saveText && blk.getAutoGen();

		// Is this block inverted?  If so, generate special-case code
		if ( blk.not &&
			analyzer.subruleCanBeInverted(blk, grammar instanceof LexerGrammar) )
		{
			Lookahead p = analyzer.look(1, blk);
			// Variable assignment for labeled elements
			if (blk.getLabel() != null && syntacticPredLevel == 0) {
				println(blk.getLabel() + " = " + lt1Value + ";");
			}

			// AST
			genElementAST(blk);

			String astArgs="";
			if (grammar instanceof TreeWalkerGrammar) {
				if( usingCustomAST )
					astArgs=namespaceAntlr+"RefAST"+"(_t),";
				else
					astArgs="_t,";
			}

			// match the bitset for the alternative
			println("match(" + astArgs + getBitsetName(markBitsetForGen(p.fset)) + ");");

			// tack on tree cursor motion if doing a tree walker
			if (grammar instanceof TreeWalkerGrammar)
			{
				println("_t = _t->getNextSibling();");
			}
			return finishingInfo;
		}

		// Special handling for single alt
		if (blk.getAlternatives().size() == 1)
		{
			Alternative alt = blk.getAlternativeAt(0);
			// Generate a warning if there is a synPred for single alt.
			if (alt.synPred != null)
			{
				antlrTool.warning(
								 "Syntactic predicate superfluous for single alternative",
								 grammar.getFilename(),
								 blk.getAlternativeAt(0).synPred.getLine(),
								 blk.getAlternativeAt(0).synPred.getColumn()
				);
			}
			if (noTestForSingle)
			{
				if (alt.semPred != null)
				{
					// Generate validating predicate
					genSemPred(alt.semPred, blk.line);
				}
				genAlt(alt, blk);
				return finishingInfo;
			}
		}

		// count number of simple LL(1) cases; only do switch for
		// many LL(1) cases (no preds, no end of token refs)
		// We don't care about exit paths for (...)*, (...)+
		// because we don't explicitly have a test for them
		// as an alt in the loop.
		//
		// Also, we now count how many unicode lookahead sets
		// there are--they must be moved to DEFAULT or ELSE
		// clause.

		int nLL1 = 0;
		for (int i=0; i<blk.getAlternatives().size(); i++)
		{
			Alternative a = blk.getAlternativeAt(i);
			if ( suitableForCaseExpression(a) )
				nLL1++;
		}

		// do LL(1) cases
		if ( nLL1 >= makeSwitchThreshold )
		{
			// Determine the name of the item to be compared
			String testExpr = lookaheadString(1);
			createdLL1Switch = true;
			// when parsing trees, convert null to valid tree node with NULL lookahead
			if ( grammar instanceof TreeWalkerGrammar )
			{
				println("if (_t == "+labeledElementASTInit+" )");
				tabs++;
				println("_t = ASTNULL;");
				tabs--;
			}
			println("switch ( "+testExpr+") {");
			for (int i=0; i<blk.alternatives.size(); i++)
			{
				Alternative alt = blk.getAlternativeAt(i);
				// ignore any non-LL(1) alts, predicated alts or end-of-token alts
				// or end-of-token alts for case expressions
				if ( !suitableForCaseExpression(alt) )
				{
					continue;
				}
				Lookahead p = alt.cache[1];
				if (p.fset.degree() == 0 && !p.containsEpsilon())
				{
					antlrTool.warning("Alternate omitted due to empty prediction set",
						grammar.getFilename(),
						alt.head.getLine(), alt.head.getColumn());
				}
				else
				{
					genCases(p.fset);
					println("{");
					tabs++;
					genAlt(alt, blk);
					println("break;");
					tabs--;
					println("}");
				}
			}
			println("default:");
			tabs++;
		}

		// do non-LL(1) and nondeterministic cases
		// This is tricky in the lexer, because of cases like:
		//     STAR : '*' ;
		//     ASSIGN_STAR : "*=";
		// Since nextToken is generated without a loop, then the STAR will
		// have end-of-token as it's lookahead set for LA(2).  So, we must generate the
		// alternatives containing trailing end-of-token in their lookahead sets *after*
		// the alternatives without end-of-token.  This implements the usual
		// lexer convention that longer matches come before shorter ones, e.g.
		// "*=" matches ASSIGN_STAR not STAR
		//
		// For non-lexer grammars, this does not sort the alternates by depth
		// Note that alts whose lookahead is purely end-of-token at k=1 end up
		// as default or else clauses.
		int startDepth = (grammar instanceof LexerGrammar) ? grammar.maxk : 0;
		for (int altDepth = startDepth; altDepth >= 0; altDepth--) {
			if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("checking depth "+altDepth);
			for (int i=0; i<blk.alternatives.size(); i++) {
				Alternative alt = blk.getAlternativeAt(i);
				if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genAlt: "+i);
				// if we made a switch above, ignore what we already took care
				// of.  Specifically, LL(1) alts with no preds
				// that do not have end-of-token in their prediction set
				if ( createdLL1Switch &&
					 suitableForCaseExpression(alt) )
				{
					if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR )
						System.out.println("ignoring alt because it was in the switch");
					continue;
				}
				String e;

				boolean unpredicted = false;

				if (grammar instanceof LexerGrammar) {
					// Calculate the "effective depth" of the alt, which is the max
					// depth at which cache[depth]!=end-of-token
					int effectiveDepth = alt.lookaheadDepth;
					if (effectiveDepth == GrammarAnalyzer.NONDETERMINISTIC)
					{
						// use maximum lookahead
						effectiveDepth = grammar.maxk;
					}
					while ( effectiveDepth >= 1 &&
							 alt.cache[effectiveDepth].containsEpsilon() )
					{
						effectiveDepth--;
					}
					// Ignore alts whose effective depth is other than the ones we
					// are generating for this iteration.
					if (effectiveDepth != altDepth)
					{
						if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR )
							System.out.println("ignoring alt because effectiveDepth!=altDepth;"+effectiveDepth+"!="+altDepth);
						continue;
					}
					unpredicted = lookaheadIsEmpty(alt, effectiveDepth);
					e = getLookaheadTestExpression(alt, effectiveDepth);
				}
				else
				{
					unpredicted = lookaheadIsEmpty(alt, grammar.maxk);
					e = getLookaheadTestExpression(alt, grammar.maxk);
				}

				// Was it a big unicode range that forced unsuitability
				// for a case expression?
				if ( alt.cache[1].fset.degree() > caseSizeThreshold &&
					  suitableForCaseExpression(alt))
				{
					if ( nIF==0 )
					{
						// generate this only for the first if the elseif's
						// are covered by this one
						if ( grammar instanceof TreeWalkerGrammar ) {
							println("if (_t == "+labeledElementASTInit+" )");
							tabs++;
							println("_t = ASTNULL;");
							tabs--;
						}
						println("if " + e + " {");
					}
					else
						println("else if " + e + " {");
				}
				else if (unpredicted &&
							alt.semPred==null &&
							alt.synPred==null)
				{
					// The alt has empty prediction set and no
					// predicate to help out.  if we have not
					// generated a previous if, just put {...} around
					// the end-of-token clause
					if ( nIF==0 ) {
						println("{");
					}
					else {
						println("else {");
					}
					finishingInfo.needAnErrorClause = false;
				}
				else
				{
					// check for sem and syn preds
					// Add any semantic predicate expression to the lookahead test
					if ( alt.semPred != null ) {
						// if debugging, wrap the evaluation of the predicate in a method
						//
						// translate $ and # references
						ActionTransInfo tInfo = new ActionTransInfo();
						String actionStr = processActionForSpecialSymbols(alt.semPred,
																		  blk.line,
																		  currentRule,
																		  tInfo);
						// ignore translation info...we don't need to do anything with it.

						// call that will inform SemanticPredicateListeners of the
						// result
						if ( grammar.debuggingOutput &&
							  ((grammar instanceof ParserGrammar) || (grammar instanceof LexerGrammar))
							 )
							e = "("+e+"&& fireSemanticPredicateEvaluated(antlr.debug.SemanticPredicateEvent.PREDICTING,"+ //FIXME
									addSemPred(charFormatter.escapeString(actionStr))+","+actionStr+"))";
						else
							e = "("+e+"&&("+actionStr +"))";
					}

					// Generate any syntactic predicates
					if ( nIF>0 ) {
						if ( alt.synPred != null ) {
							println("else {");
							tabs++;
							genSynPred( alt.synPred, e );
							closingBracesOfIFSequence++;
						}
						else {
							println("else if " + e + " {");
						}
					}
					else {
						if ( alt.synPred != null ) {
							genSynPred( alt.synPred, e );
						}
						else {
							// when parsing trees, convert null to valid tree node
							// with NULL lookahead.
							if ( grammar instanceof TreeWalkerGrammar ) {
								println("if (_t == "+labeledElementASTInit+" )");
								tabs++;
								println("_t = ASTNULL;");
								tabs--;
							}
							println("if " + e + " {");
						}
					}

				}

				nIF++;
				tabs++;
				genAlt(alt, blk);
				tabs--;
				println("}");
			}
		}
		String ps = "";
		for (int i=1; i<=closingBracesOfIFSequence; i++) {
			tabs--; // does JavaCodeGenerator need this?
			ps+="}";
		}

		// Restore the AST generation state
		genAST = savegenAST;

		// restore save text state
		saveText=oldsaveTest;

		// Return the finishing info.
		if ( createdLL1Switch ) {
			tabs--;
			finishingInfo.postscript = ps+"}";
			finishingInfo.generatedSwitch = true;
			finishingInfo.generatedAnIf = nIF>0;
			//return new CppBlockFinishingInfo(ps+"}",true,nIF>0); // close up switch statement

		}
		else {
			finishingInfo.postscript = ps;
			finishingInfo.generatedSwitch = false;
			finishingInfo.generatedAnIf = nIF>0;
			//return new CppBlockFinishingInfo(ps, false,nIF>0);
		}
		return finishingInfo;
	}

	private static boolean suitableForCaseExpression(Alternative a) {
		return a.lookaheadDepth == 1 &&
			a.semPred == null &&
			!a.cache[1].containsEpsilon() &&
			a.cache[1].fset.degree()<=caseSizeThreshold;
	}

	/** Generate code to link an element reference into the AST
	 */
	private void genElementAST(AlternativeElement el) {

		// handle case where you're not building trees, but are in tree walker.
		// Just need to get labels set up.
		if ( grammar instanceof TreeWalkerGrammar && !grammar.buildAST )
		{
			String elementRef;
			String astName;

			// Generate names and declarations of the AST variable(s)
			if (el.getLabel() == null)
			{
				elementRef = lt1Value;
				// Generate AST variables for unlabeled stuff
				astName = "tmp" + astVarNumber + "_AST";
				astVarNumber++;
				// Map the generated AST variable in the alternate
				mapTreeVariable(el, astName);
				// Generate an "input" AST variable also
				println(labeledElementASTType+" "+astName+"_in = "+elementRef+";");
			}
			return;
		}

		if (grammar.buildAST && syntacticPredLevel == 0)
		{
			boolean needASTDecl =
				( genAST && (el.getLabel() != null ||
				  el.getAutoGenType() != GrammarElement.AUTO_GEN_BANG ));

			// RK: if we have a grammar element always generate the decl
			// since some guy can access it from an action and we can't
			// peek ahead (well not without making a mess).
			// I'd prefer taking this out.
			if( el.getAutoGenType() != GrammarElement.AUTO_GEN_BANG &&
				 (el instanceof TokenRefElement) )
				needASTDecl = true;

			boolean doNoGuessTest =
				( grammar.hasSyntacticPredicate && needASTDecl );

			String elementRef;
			String astNameBase;

			// Generate names and declarations of the AST variable(s)
			if (el.getLabel() != null)
			{
				// if the element is labeled use that name...
				elementRef = el.getLabel();
				astNameBase = el.getLabel();
			}
			else
			{
				// else generate a temporary name...
				elementRef = lt1Value;
				// Generate AST variables for unlabeled stuff
				astNameBase = "tmp" + astVarNumber;
				astVarNumber++;
			}

			// Generate the declaration if required.
			if ( needASTDecl )
			{
				if ( el instanceof GrammarAtom )
				{
					GrammarAtom ga = (GrammarAtom)el;
					if ( ga.getASTNodeType()!=null )
					{
						genASTDeclaration( el, astNameBase, "Ref"+ga.getASTNodeType() );
//						println("Ref"+ga.getASTNodeType()+" " + astName + ";");
					}
					else
					{
						genASTDeclaration( el, astNameBase, labeledElementASTType );
//						println(labeledElementASTType+" " + astName + " = "+labeledElementASTInit+";");
					}
				}
				else
				{
					genASTDeclaration( el, astNameBase, labeledElementASTType );
//					println(labeledElementASTType+" " + astName + " = "+labeledElementASTInit+";");
				}
			}

			// for convenience..
			String astName = astNameBase + "_AST";

			// Map the generated AST variable in the alternate
			mapTreeVariable(el, astName);
			if (grammar instanceof TreeWalkerGrammar)
			{
				// Generate an "input" AST variable also
				println(labeledElementASTType+" " + astName + "_in = "+labeledElementASTInit+";");
			}

			// Enclose actions with !guessing
			if (doNoGuessTest) {
				println("if ( inputState->guessing == 0 ) {");
				tabs++;
			}

			// if something has a label assume it will be used
			// so we must initialize the RefAST
			if (el.getLabel() != null)
			{
				if ( el instanceof GrammarAtom )
				{
					println(astName + " = "+
							  getASTCreateString((GrammarAtom)el,elementRef) + ";");
				}
				else
				{
					println(astName + " = "+
							  getASTCreateString(elementRef) + ";");
				}
			}

			// if it has no label but a declaration exists initialize it.
			if( el.getLabel() == null && needASTDecl )
			{
				elementRef = lt1Value;
				if ( el instanceof GrammarAtom )
				{
					println(astName + " = "+
							  getASTCreateString((GrammarAtom)el,elementRef) + ";");
				}
				else
				{
					println(astName + " = "+
							  getASTCreateString(elementRef) + ";");
				}
				// Map the generated AST variable in the alternate
				if (grammar instanceof TreeWalkerGrammar)
				{
					// set "input" AST variable also
					println(astName + "_in = " + elementRef + ";");
				}
			}

			if (genAST)
			{
				switch (el.getAutoGenType())
				{
				case GrammarElement.AUTO_GEN_NONE:
					if( usingCustomAST ||
						 (el instanceof GrammarAtom &&
						  ((GrammarAtom)el).getASTNodeType() != null) )
						println("astFactory->addASTChild(currentAST, "+namespaceAntlr+"RefAST("+ astName + "));");
					else
						println("astFactory->addASTChild(currentAST, "+ astName + ");");
					//						println("astFactory.addASTChild(currentAST, "+namespaceAntlr+"RefAST(" + astName + "));");
					break;
				case GrammarElement.AUTO_GEN_CARET:
					if( usingCustomAST ||
						 (el instanceof GrammarAtom &&
						 ((GrammarAtom)el).getASTNodeType() != null) )
						println("astFactory->makeASTRoot(currentAST, "+namespaceAntlr+"RefAST(" + astName + "));");
					else
						println("astFactory->makeASTRoot(currentAST, " + astName + ");");
					break;
				default:
					break;
				}
			}
			if (doNoGuessTest)
			{
				tabs--;
				println("}");
			}
		}
	}
	/** Close the try block and generate catch phrases
	 * if the element has a labeled handler in the rule
	 */
	private void genErrorCatchForElement(AlternativeElement el) {
		if (el.getLabel() == null) return;
		String r = el.enclosingRuleName;
		if ( grammar instanceof LexerGrammar ) {
			r = CodeGenerator.encodeLexerRuleName(el.enclosingRuleName);
		}
		RuleSymbol rs = (RuleSymbol)grammar.getSymbol(r);
		if (rs == null) {
			antlrTool.panic("Enclosing rule not found!");
		}
		ExceptionSpec ex = rs.block.findExceptionSpec(el.getLabel());
		if (ex != null) {
			tabs--;
			println("}");
			genErrorHandler(ex);
		}
	}
	/** Generate the catch phrases for a user-specified error handler */
	private void genErrorHandler(ExceptionSpec ex)
	{
		// Each ExceptionHandler in the ExceptionSpec is a separate catch
		for (int i = 0; i < ex.handlers.size(); i++)
		{
			ExceptionHandler handler = (ExceptionHandler)ex.handlers.elementAt(i);
			// Generate catch phrase
			println("catch (" + handler.exceptionTypeAndName.getText() + ") {");
			tabs++;
			if (grammar.hasSyntacticPredicate) {
				println("if (inputState->guessing==0) {");
				tabs++;
			}

			// When not guessing, execute user handler action
			ActionTransInfo tInfo = new ActionTransInfo();
			genLineNo(handler.action);
			printAction(
				processActionForSpecialSymbols( handler.action.getText(),
														 handler.action.getLine(),
														 currentRule, tInfo )
			);
			genLineNo2();

			if (grammar.hasSyntacticPredicate)
			{
				tabs--;
				println("} else {");
				tabs++;
				// When guessing, rethrow exception
				println("throw;");
				tabs--;
				println("}");
			}
			// Close catch phrase
			tabs--;
			println("}");
		}
	}
	/** Generate a try { opening if the element has a labeled handler in the rule */
	private void genErrorTryForElement(AlternativeElement el) {
		if (el.getLabel() == null) return;
		String r = el.enclosingRuleName;
		if ( grammar instanceof LexerGrammar ) {
			r = CodeGenerator.encodeLexerRuleName(el.enclosingRuleName);
		}
		RuleSymbol rs = (RuleSymbol)grammar.getSymbol(r);
		if (rs == null) {
			antlrTool.panic("Enclosing rule not found!");
		}
		ExceptionSpec ex = rs.block.findExceptionSpec(el.getLabel());
		if (ex != null) {
			println("try { // for error handling");
			tabs++;
		}
	}
	/** Generate a header that is common to all C++ files */
	protected void genHeader(String fileName)
	{
		println("/* $ANTLR "+antlrTool.version+": "+
				"\""+antlrTool.fileMinusPath(antlrTool.grammarFile)+"\""+
				" -> "+
				"\""+fileName+"\"$ */");
	}

	// these are unique to C++ mode
	public void genInclude(LexerGrammar g) throws IOException
	{
		outputFile = grammar.getClassName() + ".hpp";
		outputLine = 1;
		currentOutput = antlrTool.openOutputFile(outputFile);
		//SAS: changed for proper text file io

		genAST = false;	// no way to gen trees.
		saveText = true;	// save consumed characters.

		tabs=0;

		// Generate a guard wrapper
		println("#ifndef INC_"+grammar.getClassName()+"_hpp_");
		println("#define INC_"+grammar.getClassName()+"_hpp_");
		println("");

		printHeaderAction(preIncludeHpp);

		println("#include <antlr/config.hpp>");

		// Generate header common to all C++ output files
		genHeader(outputFile);

		// Generate header specific to lexer header file
		println("#include <antlr/CommonToken.hpp>");
		println("#include <antlr/InputBuffer.hpp>");
		println("#include <antlr/BitSet.hpp>");
		println("#include \"" + grammar.tokenManager.getName() + TokenTypesFileSuffix+".hpp\"");

		// Find the name of the super class
		String sup=null;
		if ( grammar.superClass!=null ) {
			sup = grammar.superClass;

			println("\n// Include correct superclass header with a header statement for example:");
			println("// header \"post_include_hpp\" {");
			println("// #include \""+sup+".hpp\"");
			println("// }");
			println("// Or....");
			println("// header {");
			println("// #include \""+sup+".hpp\"");
			println("// }\n");
		}
		else {
			sup = grammar.getSuperClass();
			if (sup.lastIndexOf('.') != -1)
				sup = sup.substring(sup.lastIndexOf('.')+1);
			println("#include <antlr/"+sup+".hpp>");
			sup = namespaceAntlr + sup;
		}

		// Do not use printAction because we assume tabs==0
		printHeaderAction(postIncludeHpp);

		if (nameSpace != null)
			   nameSpace.emitDeclarations(currentOutput);

		printHeaderAction("");

		// print javadoc comment if any
		if ( grammar.comment!=null ) {
			_println(grammar.comment);
		}

		// Generate lexer class definition
		print("class CUSTOM_API " + grammar.getClassName() + " : public " + sup);
		println(", public " + grammar.tokenManager.getName() + TokenTypesFileSuffix);

		Token tsuffix = (Token)grammar.options.get("classHeaderSuffix");
		if ( tsuffix != null ) {
			String suffix = StringUtils.stripFrontBack(tsuffix.getText(),"\"","\"");
			if ( suffix != null ) {
				print(", "+suffix);  // must be an interface name for Java
			}
		}
		println("{");

		// Generate user-defined lexer class members
		if (grammar.classMemberAction != null) {
			genLineNo(grammar.classMemberAction);
			print(
				processActionForSpecialSymbols(grammar.classMemberAction.getText(),
														 grammar.classMemberAction.getLine(),
														 currentRule, null)
			);
			genLineNo2();
		}

		// Generate initLiterals() method
		tabs=0;
		println("private:");
		tabs=1;
		println("void initLiterals();");

		// Generate getCaseSensitiveLiterals() method
		tabs=0;
		println("public:");
		tabs=1;
		println("bool getCaseSensitiveLiterals() const");
		println("{");
		tabs++;
		println("return "+g.caseSensitiveLiterals + ";");
		tabs--;
		println("}");

		// Make constructors public
		tabs=0;
		println("public:");
		tabs=1;

		if( noConstructors )
		{
			tabs = 0;
			println("#if 0");
			println("// constructor creation turned of with 'noConstructor' option");
			tabs = 1;
		}

		// Generate the constructor from std::istream
		println(grammar.getClassName() + "(" + namespaceStd + "istream& in);");

		// Generate the constructor from InputBuffer
		println(grammar.getClassName() + "("+namespaceAntlr+"InputBuffer& ib);");

		println(grammar.getClassName() + "(const "+namespaceAntlr+"LexerSharedInputState& state);");
		if( noConstructors )
		{
			tabs = 0;
			println("// constructor creation turned of with 'noConstructor' option");
			println("#endif");
			tabs = 1;
		}

		// Generate nextToken() rule.
		// nextToken() is a synthetic lexer rule that is the implicit OR of all
		// user-defined lexer rules.
		println(namespaceAntlr+"RefToken nextToken();");

		// Generate code for each rule in the lexer
		Enumeration ids = grammar.rules.elements();
		while ( ids.hasMoreElements() ) {
			RuleSymbol sym = (RuleSymbol) ids.nextElement();
			// Don't generate the synthetic rules
			if (!sym.getId().equals("mnextToken")) {
				genRuleHeader(sym, false);
			}
			exitIfError();
		}

		// Make the rest private
		tabs=0;
		println("private:");
		tabs=1;

		// generate the rule name array for debugging
		if ( grammar.debuggingOutput ) {
			println("static const char* _ruleNames[];");
		}

		// Generate the semantic predicate map for debugging
		if (grammar.debuggingOutput)
			println("static const char* _semPredNames[];");

		// Generate the bitsets used throughout the lexer
		genBitsetsHeader(bitsetsUsed, ((LexerGrammar)grammar).charVocabulary.size());

		tabs=0;
		println("};");
		println("");
		if (nameSpace != null)
			nameSpace.emitClosures(currentOutput);

		// Generate a guard wrapper
		println("#endif /*INC_"+grammar.getClassName()+"_hpp_*/");

		// Close the lexer output stream
		currentOutput.close();
		currentOutput = null;
	}
	public void genInclude(ParserGrammar g) throws IOException
	{
		// Open the output stream for the parser and set the currentOutput
		outputFile = grammar.getClassName() + ".hpp";
		outputLine = 1;
		currentOutput = antlrTool.openOutputFile(outputFile);
		//SAS: changed for proper text file io

		genAST = grammar.buildAST;

		tabs = 0;

		// Generate a guard wrapper
		println("#ifndef INC_"+grammar.getClassName()+"_hpp_");
		println("#define INC_"+grammar.getClassName()+"_hpp_");
		println("");
		printHeaderAction(preIncludeHpp);
		println("#include <antlr/config.hpp>");

		// Generate the header common to all output files.
		genHeader(outputFile);

		// Generate header for the parser
		println("#include <antlr/TokenStream.hpp>");
		println("#include <antlr/TokenBuffer.hpp>");
		println("#include \"" + grammar.tokenManager.getName() + TokenTypesFileSuffix+".hpp\"");

		// Generate parser class definition
		String sup=null;
		if ( grammar.superClass!=null ) {
			sup = grammar.superClass;
			println("\n// Include correct superclass header with a header statement for example:");
			println("// header \"post_include_hpp\" {");
			println("// #include \""+sup+".hpp\"");
			println("// }");
			println("// Or....");
			println("// header {");
			println("// #include \""+sup+".hpp\"");
			println("// }\n");
		}
		else {
			sup = grammar.getSuperClass();
			if (sup.lastIndexOf('.') != -1)
				sup = sup.substring(sup.lastIndexOf('.')+1);
			println("#include <antlr/"+sup+".hpp>");
			sup = namespaceAntlr + sup;
		}
		println("");

		// Do not use printAction because we assume tabs==0
		printHeaderAction(postIncludeHpp);

		if (nameSpace != null)
			nameSpace.emitDeclarations(currentOutput);

		printHeaderAction("");

		// print javadoc comment if any
		if ( grammar.comment!=null ) {
			_println(grammar.comment);
		}

		// generate the actual class definition
		print("class CUSTOM_API " + grammar.getClassName() + " : public " + sup);
		println(", public " + grammar.tokenManager.getName() + TokenTypesFileSuffix);

		Token tsuffix = (Token)grammar.options.get("classHeaderSuffix");
		if ( tsuffix != null ) {
			String suffix = StringUtils.stripFrontBack(tsuffix.getText(),"\"","\"");
			if ( suffix != null )
				print(", "+suffix);  // must be an interface name for Java
		}
		println("{");

		// set up an array of all the rule names so the debugger can
		// keep track of them only by number -- less to store in tree...
		if (grammar.debuggingOutput) {
			println("public: static const char* _ruleNames[];");
		}
		// Generate user-defined parser class members
		if (grammar.classMemberAction != null) {
			genLineNo(grammar.classMemberAction.getLine());
			print(
				processActionForSpecialSymbols(grammar.classMemberAction.getText(),
														 grammar.classMemberAction.getLine(),
														 currentRule, null)
			);
			genLineNo2();
		}
		println("public:");
		tabs = 1;
		println("void initializeASTFactory( "+namespaceAntlr+"ASTFactory& factory );");
//		println("// called from constructors");
//		println("void _initialize( void );");

		// Generate parser class constructor from TokenBuffer
		tabs=0;
		if( noConstructors )
		{
			println("#if 0");
			println("// constructor creation turned of with 'noConstructor' option");
		}
		println("protected:");
		tabs=1;
		println(grammar.getClassName() + "("+namespaceAntlr+"TokenBuffer& tokenBuf, int k);");
		tabs=0;
		println("public:");
		tabs=1;
		println(grammar.getClassName() + "("+namespaceAntlr+"TokenBuffer& tokenBuf);");

		// Generate parser class constructor from TokenStream
		tabs=0;
		println("protected:");
		tabs=1;
		println(grammar.getClassName()+"("+namespaceAntlr+"TokenStream& lexer, int k);");
		tabs=0;
		println("public:");
		tabs=1;
		println(grammar.getClassName()+"("+namespaceAntlr+"TokenStream& lexer);");

		println(grammar.getClassName()+"(const "+namespaceAntlr+"ParserSharedInputState& state);");
		if( noConstructors )
		{
			tabs = 0;
			println("// constructor creation turned of with 'noConstructor' option");
			println("#endif");
			tabs = 1;
		}

		println("int getNumTokens() const");
		println("{"); tabs++;
		println("return "+grammar.getClassName()+"::NUM_TOKENS;");
		tabs--; println("}");
		println("const char* getTokenName( int type ) const");
		println("{"); tabs++;
		println("if( type > getNumTokens() ) return 0;");
		println("return "+grammar.getClassName()+"::tokenNames[type];");
		tabs--; println("}");
		println("const char* const* getTokenNames() const");
		println("{"); tabs++;
		println("return "+grammar.getClassName()+"::tokenNames;");
		tabs--; println("}");

		// Generate code for each rule in the grammar
		Enumeration ids = grammar.rules.elements();
		while ( ids.hasMoreElements() ) {
			GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
			if ( sym instanceof RuleSymbol) {
				RuleSymbol rs = (RuleSymbol)sym;
				genRuleHeader(rs, rs.references.size()==0);
			}
			exitIfError();
		}

		// RK: when we are using a custom ast override Parser::getAST to return
		// the custom AST type. Ok, this does not work anymore with newer
		// compilers gcc 3.2.x and up. The reference counter is probably
		// getting in the way.
		// So now we just patch the return type back to RefAST
		tabs = 0; println("public:"); tabs = 1;
		println(namespaceAntlr+"RefAST getAST()");
		println("{");
		if( usingCustomAST )
		{
			tabs++;
			println("return "+namespaceAntlr+"RefAST(returnAST);");
			tabs--;
		}
		else
		{
			tabs++;
			println("return returnAST;");
			tabs--;
		}
		println("}");
		println("");

		tabs=0; println("protected:"); tabs=1;
		println(labeledElementASTType+" returnAST;");

		// Make the rest private
		tabs=0;
		println("private:");
		tabs=1;

		// Generate the token names
		println("static const char* tokenNames[];");
		// and how many there are of them
		_println("#ifndef NO_STATIC_CONSTS");
		println("static const int NUM_TOKENS = "+grammar.tokenManager.getVocabulary().size()+";");
		_println("#else");
		println("enum {");
		println("\tNUM_TOKENS = "+grammar.tokenManager.getVocabulary().size());
		println("};");
		_println("#endif");

		// Generate the bitsets used throughout the grammar
		genBitsetsHeader(bitsetsUsed, grammar.tokenManager.maxTokenType());

		// Generate the semantic predicate map for debugging
		if (grammar.debuggingOutput)
			println("static const char* _semPredNames[];");

		// Close class definition
		tabs=0;
		println("};");
		println("");
		if (nameSpace != null)
			nameSpace.emitClosures(currentOutput);

		// Generate a guard wrapper
		println("#endif /*INC_"+grammar.getClassName()+"_hpp_*/");

		// Close the parser output stream
		currentOutput.close();
		currentOutput = null;
	}
	public void genInclude(TreeWalkerGrammar g) throws IOException
	{
		// Open the output stream for the parser and set the currentOutput
		outputFile = grammar.getClassName() + ".hpp";
		outputLine = 1;
		currentOutput = antlrTool.openOutputFile(outputFile);
		//SAS: changed for proper text file io

		genAST = grammar.buildAST;
		tabs = 0;

		// Generate a guard wrapper
		println("#ifndef INC_"+grammar.getClassName()+"_hpp_");
		println("#define INC_"+grammar.getClassName()+"_hpp_");
		println("");
		printHeaderAction(preIncludeHpp);
		println("#include <antlr/config.hpp>");
		println("#include \"" + grammar.tokenManager.getName() + TokenTypesFileSuffix+".hpp\"");

		// Generate the header common to all output files.
		genHeader(outputFile);

		// Find the name of the super class
		String sup=null;
		if ( grammar.superClass!=null ) {
			sup = grammar.superClass;
			println("\n// Include correct superclass header with a header statement for example:");
			println("// header \"post_include_hpp\" {");
			println("// #include \""+sup+".hpp\"");
			println("// }");
			println("// Or....");
			println("// header {");
			println("// #include \""+sup+".hpp\"");
			println("// }\n");
		}
		else {
			sup = grammar.getSuperClass();
			if (sup.lastIndexOf('.') != -1)
				sup = sup.substring(sup.lastIndexOf('.')+1);
			println("#include <antlr/"+sup+".hpp>");
			sup = namespaceAntlr + sup;
		}
		println("");

		// Generate header for the parser
		//
		// Do not use printAction because we assume tabs==0
		printHeaderAction(postIncludeHpp);

		if (nameSpace != null)
			nameSpace.emitDeclarations(currentOutput);

		printHeaderAction("");

		// print javadoc comment if any
		if ( grammar.comment!=null ) {
			_println(grammar.comment);
		}

		// Generate parser class definition
		print("class CUSTOM_API " + grammar.getClassName() + " : public "+sup);
		println(", public " + grammar.tokenManager.getName() + TokenTypesFileSuffix);

		Token tsuffix = (Token)grammar.options.get("classHeaderSuffix");
		if ( tsuffix != null ) {
			String suffix = StringUtils.stripFrontBack(tsuffix.getText(),"\"","\"");
			if ( suffix != null ) {
				print(", "+suffix);  // must be an interface name for Java
			}
		}
		println("{");

		// Generate user-defined parser class members
		if (grammar.classMemberAction != null) {
			genLineNo(grammar.classMemberAction.getLine());
			print(
					processActionForSpecialSymbols(grammar.classMemberAction.getText(),
															 grammar.classMemberAction.getLine(),
															 currentRule, null)
					);
			genLineNo2();
		}

		// Generate default parser class constructor
		tabs=0;
		println("public:");

		if( noConstructors )
		{
			println("#if 0");
			println("// constructor creation turned of with 'noConstructor' option");
		}
		tabs=1;
		println(grammar.getClassName() + "();");
		if( noConstructors )
		{
			tabs = 0;
			println("#endif");
			tabs = 1;
		}

		// Generate declaration for the initializeFactory method
		println("static void initializeASTFactory( "+namespaceAntlr+"ASTFactory& factory );");

		println("int getNumTokens() const");
		println("{"); tabs++;
		println("return "+grammar.getClassName()+"::NUM_TOKENS;");
		tabs--; println("}");
		println("const char* getTokenName( int type ) const");
		println("{"); tabs++;
		println("if( type > getNumTokens() ) return 0;");
		println("return "+grammar.getClassName()+"::tokenNames[type];");
		tabs--; println("}");
		println("const char* const* getTokenNames() const");
		println("{"); tabs++;
		println("return "+grammar.getClassName()+"::tokenNames;");
		tabs--; println("}");

		// Generate code for each rule in the grammar
		Enumeration ids = grammar.rules.elements();
		String ruleNameInits = "";
		while ( ids.hasMoreElements() ) {
			GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
			if ( sym instanceof RuleSymbol) {
				RuleSymbol rs = (RuleSymbol)sym;
				genRuleHeader(rs, rs.references.size()==0);
			}
			exitIfError();
		}
		tabs = 0; println("public:"); tabs = 1;
		println(namespaceAntlr+"RefAST getAST()");
		println("{");
		if( usingCustomAST )
		{
			tabs++;
			println("return "+namespaceAntlr+"RefAST(returnAST);");
			tabs--;
		}
		else
		{
			tabs++;
			println("return returnAST;");
			tabs--;
		}
		println("}");
		println("");

		tabs=0; println("protected:"); tabs=1;
		println(labeledElementASTType+" returnAST;");
		println(labeledElementASTType+" _retTree;");

		// Make the rest private
		tabs=0;
		println("private:");
		tabs=1;

		// Generate the token names
		println("static const char* tokenNames[];");
		// and how many there are of them
		_println("#ifndef NO_STATIC_CONSTS");
		println("static const int NUM_TOKENS = "+grammar.tokenManager.getVocabulary().size()+";");
		_println("#else");
		println("enum {");
		println("\tNUM_TOKENS = "+grammar.tokenManager.getVocabulary().size());
		println("};");
		_println("#endif");

		// Generate the bitsets used throughout the grammar
		genBitsetsHeader(bitsetsUsed, grammar.tokenManager.maxTokenType());

		// Close class definition
		tabs=0;
		println("};");
		println("");
		if (nameSpace != null)
			nameSpace.emitClosures(currentOutput);

		// Generate a guard wrapper
		println("#endif /*INC_"+grammar.getClassName()+"_hpp_*/");

		// Close the parser output stream
		currentOutput.close();
		currentOutput = null;
	}
	/// for convenience
	protected void genASTDeclaration( AlternativeElement el ) {
		genASTDeclaration( el, labeledElementASTType );
	}
	/// for convenience
	protected void genASTDeclaration( AlternativeElement el, String node_type ) {
		genASTDeclaration( el, el.getLabel(), node_type );
	}
	/// Generate (if not already done) a declaration for the AST for el.
	protected void genASTDeclaration( AlternativeElement el, String var_name, String node_type ) {
		// already declared?
		if( declaredASTVariables.contains(el) )
			return;

		String init = labeledElementASTInit;

		if (el instanceof GrammarAtom &&
			 ((GrammarAtom)el).getASTNodeType() != null )
			init = "Ref"+((GrammarAtom)el).getASTNodeType()+"("+labeledElementASTInit+")";

		// emit code
		println(node_type+" " + var_name + "_AST = "+init+";");

		// mark as declared
		declaredASTVariables.put(el, el);
	}
	private void genLiteralsTest() {
		println("_ttype = testLiteralsTable(_ttype);");
	}
	private void genLiteralsTestForPartialToken() {
		println("_ttype = testLiteralsTable(text.substr(_begin, text.length()-_begin),_ttype);");
	}
	protected void genMatch(BitSet b) {
	}
	protected void genMatch(GrammarAtom atom) {
		if ( atom instanceof StringLiteralElement ) {
			if ( grammar instanceof LexerGrammar ) {
				genMatchUsingAtomText(atom);
			}
			else {
				genMatchUsingAtomTokenType(atom);
			}
		}
		else if ( atom instanceof CharLiteralElement ) {
			// Lexer case is handled in the gen( CharLiteralElement x )
			antlrTool.error("cannot ref character literals in grammar: "+atom);
		}
		else if ( atom instanceof TokenRefElement ) {
			genMatchUsingAtomTokenType(atom);
		} else if (atom instanceof WildcardElement) {
			gen((WildcardElement)atom);
		}
	}
	protected void genMatchUsingAtomText(GrammarAtom atom) {
		// match() for trees needs the _t cursor
		String astArgs="";
		if (grammar instanceof TreeWalkerGrammar) {
			if( usingCustomAST )
				astArgs=namespaceAntlr+"RefAST"+"(_t),";
			else
				astArgs="_t,";
		}

		// if in lexer and ! on element, save buffer index to kill later
		if ( grammar instanceof LexerGrammar && (!saveText||atom.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
			println("_saveIndex = text.length();");
		}

		print(atom.not ? "matchNot(" : "match(");
		_print(astArgs);

		// print out what to match
		if (atom.atomText.equals("EOF")) {
			// horrible hack to handle EOF case
			_print(namespaceAntlr+"Token::EOF_TYPE");
		}
		else
		{
			if( grammar instanceof LexerGrammar )	// lexer needs special handling
			{
				String cppstring = convertJavaToCppString( atom.atomText, false );
				_print(cppstring);
			}
			else
				_print(atom.atomText);
		}

		_println(");");

		if ( grammar instanceof LexerGrammar && (!saveText||atom.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
			println("text.erase(_saveIndex);");      // kill text atom put in buffer
		}
	}
	protected void genMatchUsingAtomTokenType(GrammarAtom atom) {
		// match() for trees needs the _t cursor
		String astArgs="";
		if (grammar instanceof TreeWalkerGrammar) {
			if( usingCustomAST )
				astArgs=namespaceAntlr+"RefAST"+"(_t),";
			else
				astArgs="_t,";
		}

		// If the literal can be mangled, generate the symbolic constant instead
		String s = astArgs + getValueString(atom.getType());

		// matching
		println( (atom.not ? "matchNot(" : "match(") + s + ");");
	}
	/** Generate the nextToken() rule.
	 * nextToken() is a synthetic lexer rule that is the implicit OR of all
	 * user-defined lexer rules.
	 * @param RuleBlock
	 */
	public void genNextToken() {
		// Are there any public rules?  If not, then just generate a
		// fake nextToken().
		boolean hasPublicRules = false;
		for (int i = 0; i < grammar.rules.size(); i++) {
			RuleSymbol rs = (RuleSymbol)grammar.rules.elementAt(i);
			if ( rs.isDefined() && rs.access.equals("public") ) {
				hasPublicRules = true;
				break;
			}
		}
		if (!hasPublicRules) {
			println("");
			println(namespaceAntlr+"RefToken "+grammar.getClassName()+"::nextToken() { return "+namespaceAntlr+"RefToken(new "+namespaceAntlr+"CommonToken("+namespaceAntlr+"Token::EOF_TYPE, \"\")); }");
			println("");
			return;
		}

		// Create the synthesized nextToken() rule
		RuleBlock nextTokenBlk = MakeGrammar.createNextTokenRule(grammar, grammar.rules, "nextToken");
		// Define the nextToken rule symbol
		RuleSymbol nextTokenRs = new RuleSymbol("mnextToken");
		nextTokenRs.setDefined();
		nextTokenRs.setBlock(nextTokenBlk);
		nextTokenRs.access = "private";
		grammar.define(nextTokenRs);
		// Analyze the nextToken rule
		boolean ok = grammar.theLLkAnalyzer.deterministic(nextTokenBlk);

		// Generate the next token rule
		String filterRule=null;
		if ( ((LexerGrammar)grammar).filterMode ) {
			filterRule = ((LexerGrammar)grammar).filterRule;
		}

		println("");
		println(namespaceAntlr+"RefToken "+grammar.getClassName()+"::nextToken()");
		println("{");
		tabs++;
		println(namespaceAntlr+"RefToken theRetToken;");
		println("for (;;) {");
		tabs++;
		println(namespaceAntlr+"RefToken theRetToken;");
		println("int _ttype = "+namespaceAntlr+"Token::INVALID_TYPE;");
		if ( ((LexerGrammar)grammar).filterMode ) {
			println("setCommitToPath(false);");
			if ( filterRule!=null ) {
				// Here's a good place to ensure that the filter rule actually exists
				if ( !grammar.isDefined(CodeGenerator.encodeLexerRuleName(filterRule)) ) {
					grammar.antlrTool.error("Filter rule "+filterRule+" does not exist in this lexer");
				}
				else {
					RuleSymbol rs = (RuleSymbol)grammar.getSymbol(CodeGenerator.encodeLexerRuleName(filterRule));
					if ( !rs.isDefined() ) {
						grammar.antlrTool.error("Filter rule "+filterRule+" does not exist in this lexer");
					}
					else if ( rs.access.equals("public") ) {
						grammar.antlrTool.error("Filter rule "+filterRule+" must be protected");
					}
				}
				println("int _m;");
				println("_m = mark();");
			}
		}
		println("resetText();");

		// Generate try around whole thing to trap scanner errors
		println("try {   // for lexical and char stream error handling");
		tabs++;

		// Test for public lexical rules with empty paths
		for (int i=0; i<nextTokenBlk.getAlternatives().size(); i++) {
			Alternative a = nextTokenBlk.getAlternativeAt(i);
			if ( a.cache[1].containsEpsilon() ) {
				antlrTool.warning("found optional path in nextToken()");
			}
		}

		// Generate the block
		String newline = System.getProperty("line.separator");
		CppBlockFinishingInfo howToFinish = genCommonBlock(nextTokenBlk, false);
		String errFinish = "if (LA(1)==EOF_CHAR)"+newline+
			"\t\t\t\t{"+newline+"\t\t\t\t\tuponEOF();"+newline+
			"\t\t\t\t\t_returnToken = makeToken("+namespaceAntlr+"Token::EOF_TYPE);"+
			newline+"\t\t\t\t}";
		errFinish += newline+"\t\t\t\t";
		if ( ((LexerGrammar)grammar).filterMode ) {
			if ( filterRule==null ) {
				errFinish += "else {consume(); goto tryAgain;}";
			}
			else {
				errFinish += "else {"+newline+
						"\t\t\t\t\tcommit();"+newline+
						"\t\t\t\t\ttry {m"+filterRule+"(false);}"+newline+
						"\t\t\t\t\tcatch("+namespaceAntlr+"RecognitionException& e) {"+newline+
						"\t\t\t\t\t	// catastrophic failure"+newline+
						"\t\t\t\t\t	reportError(e);"+newline+
						"\t\t\t\t\t	consume();"+newline+
						"\t\t\t\t\t}"+newline+
 						"\t\t\t\t\tgoto tryAgain;"+newline+
 						"\t\t\t\t}";
			}
		}
		else {
			errFinish += "else {"+throwNoViable+"}";
		}
		genBlockFinish(howToFinish, errFinish);

		// at this point a valid token has been matched, undo "mark" that was done
		if ( ((LexerGrammar)grammar).filterMode && filterRule!=null ) {
			println("commit();");
		}

		// Generate literals test if desired
		// make sure _ttype is set first; note _returnToken must be
		// non-null as the rule was required to create it.
		println("if ( !_returnToken )"+newline+
				  "\t\t\t\tgoto tryAgain; // found SKIP token"+newline);
		println("_ttype = _returnToken->getType();");
		if ( ((LexerGrammar)grammar).getTestLiterals()) {
			genLiteralsTest();
		}

		// return token created by rule reference in switch
		println("_returnToken->setType(_ttype);");
		println("return _returnToken;");

		// Close try block
		tabs--;
		println("}");
		println("catch ("+namespaceAntlr+"RecognitionException& e) {");
		tabs++;
		if ( ((LexerGrammar)grammar).filterMode ) {
			if ( filterRule==null ) {
				println("if ( !getCommitToPath() ) {");
				tabs++;
				println("consume();");
				println("goto tryAgain;");
				tabs--;
				println("}");
			}
			else {
				println("if ( !getCommitToPath() ) {");
				tabs++;
				println("rewind(_m);");
				println("resetText();");
				println("try {m"+filterRule+"(false);}");
				println("catch("+namespaceAntlr+"RecognitionException& ee) {");
				println("	// horrendous failure: error in filter rule");
				println("	reportError(ee);");
				println("	consume();");
				println("}");
				// println("goto tryAgain;");
				tabs--;
				println("}");
				println("else");
			}
		}
		if ( nextTokenBlk.getDefaultErrorHandler() ) {
			println("{");
			tabs++;
			println("reportError(e);");
			println("consume();");
			tabs--;
			println("}");
		}
		else {
		    // pass on to invoking routine
          tabs++;
		    println("throw "+namespaceAntlr+"TokenStreamRecognitionException(e);");
			 tabs--;
		}

		// close CharStreamException try
		tabs--;
		println("}");
		println("catch ("+namespaceAntlr+"CharStreamIOException& csie) {");
		println("\tthrow "+namespaceAntlr+"TokenStreamIOException(csie.io);");
		println("}");
		println("catch ("+namespaceAntlr+"CharStreamException& cse) {");
		println("\tthrow "+namespaceAntlr+"TokenStreamException(cse.getMessage());");
		println("}");

		// close for-loop
		_println("tryAgain:;");
		tabs--;
		println("}");

		// close method nextToken
		tabs--;
		println("}");
		println("");
	}
	/** Gen a named rule block.
	 * ASTs are generated for each element of an alternative unless
	 * the rule or the alternative have a '!' modifier.
	 *
	 * If an alternative defeats the default tree construction, it
	 * must set <rule>_AST to the root of the returned AST.
	 *
	 * Each alternative that does automatic tree construction, builds
	 * up root and child list pointers in an ASTPair structure.
	 *
	 * A rule finishes by setting the returnAST variable from the
	 * ASTPair.
	 *
	 * @param rule The name of the rule to generate
	 * @param startSymbol true if the rule is a start symbol (i.e., not referenced elsewhere)
	*/
	public void genRule(RuleSymbol s, boolean startSymbol, int ruleNum, String prefix) {
//		tabs=1; // JavaCodeGenerator needs this
		if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genRule("+ s.getId() +")");
		if ( !s.isDefined() ) {
			antlrTool.error("undefined rule: "+ s.getId());
			return;
		}

		// Generate rule return type, name, arguments
		RuleBlock rblk = s.getBlock();

		currentRule = rblk;
		currentASTResult = s.getId();

		// clear list of declared ast variables..
		declaredASTVariables.clear();

		// Save the AST generation state, and set it to that of the rule
		boolean savegenAST = genAST;
		genAST = genAST && rblk.getAutoGen();

		// boolean oldsaveTest = saveText;
		saveText = rblk.getAutoGen();

		// print javadoc comment if any
		if ( s.comment!=null ) {
			_println(s.comment);
		}

		// Gen method return type (note lexer return action set at rule creation)
		if (rblk.returnAction != null)
		{
			// Has specified return value
			_print(extractTypeOfAction(rblk.returnAction, rblk.getLine(), rblk.getColumn()) + " ");
		} else {
			// No specified return value
			_print("void ");
		}

		// Gen method name
		_print(prefix + s.getId() + "(");

		// Additional rule parameters common to all rules for this grammar
		_print(commonExtraParams);
		if (commonExtraParams.length() != 0 && rblk.argAction != null ) {
			_print(",");
		}

		// Gen arguments
		if (rblk.argAction != null)
		{
			// Has specified arguments
			_println("");
// FIXME: make argAction also a token? Hmmmmm
//			genLineNo(rblk);
			tabs++;

			// Process arguments for default arguments
			// newer gcc's don't accept these in two places (header/cpp)
			//
			// Old appraoch with StringBuffer gave trouble with gcj.
			//
			// RK: Actually this breaks with string default arguments containing
			// a comma's or equal signs. Then again the old StringBuffer method
			// suffered from the same.
			String oldarg = rblk.argAction;
			String newarg = "";

			String comma = "";
			int eqpos = oldarg.indexOf( '=' );
			if( eqpos != -1 )
			{
				int cmpos = 0;
				while( cmpos != -1 && eqpos != -1 )
				{
					newarg = newarg + comma + oldarg.substring( 0, eqpos ).trim();
					comma = ", ";
					cmpos = oldarg.indexOf( ',', eqpos );
					if( cmpos != -1 )
					{
						// cut off part we just handled
						oldarg = oldarg.substring( cmpos+1 ).trim();
						eqpos = oldarg.indexOf( '=' );
						if( eqpos == -1 )
							newarg = newarg+comma+oldarg;
					}
				}
			}
			else
				newarg = oldarg;

			println( newarg );

//			println(rblk.argAction);
			tabs--;
			print(") ");
//			genLineNo2();	// gcc gives error on the brace... hope it works for the others too
		} else {
			// No specified arguments
			_print(") ");
		}
		_println("{");
		tabs++;

		if (grammar.traceRules) {
			if ( grammar instanceof TreeWalkerGrammar ) {
				if ( usingCustomAST )
					println("Tracer traceInOut(this,\""+ s.getId() +"\","+namespaceAntlr+"RefAST"+"(_t));");
				else
					println("Tracer traceInOut(this,\""+ s.getId() +"\",_t);");
			}
			else {
				println("Tracer traceInOut(this, \""+ s.getId() +"\");");
			}
		}

		// Convert return action to variable declaration
		if (rblk.returnAction != null)
		{
			genLineNo(rblk);
			println(rblk.returnAction + ";");
			genLineNo2();
		}

		// print out definitions needed by rules for various grammar types
		if (!commonLocalVars.equals(""))
			println(commonLocalVars);

		if ( grammar instanceof LexerGrammar ) {
			// RK: why is this here? It seems not supported in the rest of the
			// tool.
			// lexer rule default return value is the rule's token name
			// This is a horrible hack to support the built-in EOF lexer rule.
			if (s.getId().equals("mEOF"))
				println("_ttype = "+namespaceAntlr+"Token::EOF_TYPE;");
			else
				println("_ttype = "+ s.getId().substring(1)+";");
			println(namespaceStd+"string::size_type _saveIndex;");		// used for element! (so we can kill text matched for element)
/*
			println("boolean old_saveConsumedInput=saveConsumedInput;");
			if ( !rblk.getAutoGen() ) {      // turn off "save input" if ! on rule
				println("saveConsumedInput=false;");
			}
*/
		}

		// if debugging, write code to mark entry to the rule
		if ( grammar.debuggingOutput)
		    if (grammar instanceof ParserGrammar)
				println("fireEnterRule(" + ruleNum + ",0);");
			else if (grammar instanceof LexerGrammar)
				println("fireEnterRule(" + ruleNum + ",_ttype);");

		// Generate trace code if desired
//		if ( grammar.debuggingOutput || grammar.traceRules) {
//			println("try { // debugging");
//			tabs++;
//		}

		// Initialize AST variables
		if (grammar instanceof TreeWalkerGrammar) {
			// "Input" value for rule
//			println(labeledElementASTType+" " + s.getId() + "_AST_in = "+labeledElementASTType+"(_t);");
			println(labeledElementASTType+" " + s.getId() + "_AST_in = (_t == "+labeledElementASTType+"(ASTNULL)) ? "+labeledElementASTInit+" : _t;");
		}
		if (grammar.buildAST) {
			// Parser member used to pass AST returns from rule invocations
			println("returnAST = "+labeledElementASTInit+";");
			// Tracks AST construction
			println(namespaceAntlr+"ASTPair currentAST;"); // = new ASTPair();");
			// User-settable return value for rule.
			println(labeledElementASTType+" " + s.getId() + "_AST = "+labeledElementASTInit+";");
		}

		genBlockPreamble(rblk);
		genBlockInitAction(rblk);
		println("");

		// Search for an unlabeled exception specification attached to the rule
		ExceptionSpec unlabeledUserSpec = rblk.findExceptionSpec("");

		// Generate try block around the entire rule for  error handling
		if (unlabeledUserSpec != null || rblk.getDefaultErrorHandler() ) {
			println("try {      // for error handling");
			tabs++;
		}

		// Generate the alternatives
		if ( rblk.alternatives.size()==1 )
		{
			// One alternative -- use simple form
			Alternative alt = rblk.getAlternativeAt(0);
			String pred = alt.semPred;
			if ( pred!=null )
				genSemPred(pred, currentRule.line);
			if (alt.synPred != null) {
				antlrTool.warning(
					"Syntactic predicate ignored for single alternative",
					grammar.getFilename(),
					alt.synPred.getLine(),
					alt.synPred.getColumn()
				);
			}
			genAlt(alt, rblk);
		}
		else
		{
			// Multiple alternatives -- generate complex form
			boolean ok = grammar.theLLkAnalyzer.deterministic(rblk);

			CppBlockFinishingInfo howToFinish = genCommonBlock(rblk, false);
			genBlockFinish(howToFinish, throwNoViable);
		}

		// Generate catch phrase for error handling
		if (unlabeledUserSpec != null || rblk.getDefaultErrorHandler() ) {
			// Close the try block
			tabs--;
			println("}");
		}

		// Generate user-defined or default catch phrases
		if (unlabeledUserSpec != null)
		{
			genErrorHandler(unlabeledUserSpec);
		}
		else if (rblk.getDefaultErrorHandler())
		{
			// Generate default catch phrase
			println("catch (" + exceptionThrown + "& ex) {");
			tabs++;
			// Generate code to handle error if not guessing
			if (grammar.hasSyntacticPredicate) {
				println("if( inputState->guessing == 0 ) {");
				tabs++;
			}
			println("reportError(ex);");
			if ( !(grammar instanceof TreeWalkerGrammar) )
			{
				// Generate code to consume until token in k==1 follow set
				Lookahead follow = grammar.theLLkAnalyzer.FOLLOW(1, rblk.endNode);
				String followSetName = getBitsetName(markBitsetForGen(follow.fset));
				println("recover(ex," + followSetName + ");");
			}
			else
			{
				// Just consume one token
				println("if ( _t != "+labeledElementASTInit+" )");
				tabs++;
				println("_t = _t->getNextSibling();");
				tabs--;
			}
			if (grammar.hasSyntacticPredicate)
			{
				tabs--;
				// When guessing, rethrow exception
				println("} else {");
				tabs++;
				println("throw;");
				tabs--;
				println("}");
			}
			// Close catch phrase
			tabs--;
			println("}");
		}

		// Squirrel away the AST "return" value
		if (grammar.buildAST) {
			println("returnAST = " + s.getId() + "_AST;");
		}

		// Set return tree value for tree walkers
		if ( grammar instanceof TreeWalkerGrammar ) {
			println("_retTree = _t;");
		}

		// Generate literals test for lexer rules so marked
		if (rblk.getTestLiterals()) {
			if ( s.access.equals("protected") ) {
				genLiteralsTestForPartialToken();
			}
			else {
				genLiteralsTest();
			}
		}

		// if doing a lexer rule, dump code to create token if necessary
		if ( grammar instanceof LexerGrammar ) {
			println("if ( _createToken && _token=="+namespaceAntlr+"nullToken && _ttype!="+namespaceAntlr+"Token::SKIP ) {");
			println("   _token = makeToken(_ttype);");
			println("   _token->setText(text.substr(_begin, text.length()-_begin));");
			println("}");
			println("_returnToken = _token;");
			// It should be easy for an optimizing compiler to realize this does nothing
			// but it avoids the warning about the variable being unused.
			println("_saveIndex=0;");
		}

		// Gen the return statement if there is one (lexer has hard-wired return action)
		if (rblk.returnAction != null) {
			println("return " + extractIdOfAction(rblk.returnAction, rblk.getLine(), rblk.getColumn()) + ";");
		}

//		if ( grammar.debuggingOutput || grammar.traceRules) {
////			tabs--;
////			println("} finally { // debugging");
////			tabs++;
//
//			// Generate trace code if desired
//			if ( grammar.debuggingOutput)
//				if (grammar instanceof ParserGrammar)
//					println("fireExitRule(" + ruleNum + ",0);");
//				else if (grammar instanceof LexerGrammar)
//					println("fireExitRule(" + ruleNum + ",_ttype);");
//
////			if (grammar.traceRules) {
////				if ( grammar instanceof TreeWalkerGrammar ) {
////					println("traceOut(\""+ s.getId() +"\",_t);");
////				}
////				else {
////					println("traceOut(\""+ s.getId() +"\");");
////				}
////			}
////
////			tabs--;
////			println("}");
//		}

		tabs--;
		println("}");
		println("");

		// Restore the AST generation state
		genAST = savegenAST;

		// restore char save state
		// saveText = oldsaveTest;
	}
	public void genRuleHeader(RuleSymbol s, boolean startSymbol) {
		tabs=1;
		if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genRuleHeader("+ s.getId() +")");
		if ( !s.isDefined() ) {
			antlrTool.error("undefined rule: "+ s.getId());
			return;
		}

		// Generate rule return type, name, arguments
		RuleBlock rblk = s.getBlock();
		currentRule = rblk;
		currentASTResult = s.getId();

		// Save the AST generation state, and set it to that of the rule
		boolean savegenAST = genAST;
		genAST = genAST && rblk.getAutoGen();

		// boolean oldsaveTest = saveText;
		saveText = rblk.getAutoGen();

		// Gen method access
		print(s.access + ": ");

		// Gen method return type (note lexer return action set at rule creation)
		if (rblk.returnAction != null)
		{
			// Has specified return value
			_print(extractTypeOfAction(rblk.returnAction, rblk.getLine(), rblk.getColumn()) + " ");
		} else {
			// No specified return value
			_print("void ");
		}

		// Gen method name
		_print(s.getId() + "(");

		// Additional rule parameters common to all rules for this grammar
		_print(commonExtraParams);
		if (commonExtraParams.length() != 0 && rblk.argAction != null ) {
			_print(",");
		}

		// Gen arguments
		if (rblk.argAction != null)
		{
			// Has specified arguments
			_println("");
			tabs++;
			println(rblk.argAction);
			tabs--;
			print(")");
		} else {
			// No specified arguments
			_print(")");
		}
		_println(";");

		tabs--;

		// Restore the AST generation state
		genAST = savegenAST;

		// restore char save state
		// saveText = oldsaveTest;
	}
	private void GenRuleInvocation(RuleRefElement rr) {
		// dump rule name
		_print(rr.targetRule + "(");

		// lexers must tell rule if it should set _returnToken
		if ( grammar instanceof LexerGrammar ) {
			// if labeled, could access Token, so tell rule to create
			if ( rr.getLabel() != null ) {
				_print("true");
			}
			else {
				_print("false");
			}
			if (commonExtraArgs.length() != 0 || rr.args!=null ) {
				_print(",");
			}
		}

		// Extra arguments common to all rules for this grammar
		_print(commonExtraArgs);
		if (commonExtraArgs.length() != 0 && rr.args!=null ) {
			_print(",");
		}

		// Process arguments to method, if any
		RuleSymbol rs = (RuleSymbol)grammar.getSymbol(rr.targetRule);
		if (rr.args != null)
		{
			// When not guessing, execute user arg action
			ActionTransInfo tInfo = new ActionTransInfo();
			// FIXME: fix line number passed to processActionForTreeSpecifiers here..
			// this one might be a bit off..
			String args = processActionForSpecialSymbols(rr.args, rr.line,
																		currentRule, tInfo);
			if ( tInfo.assignToRoot || tInfo.refRuleRoot!=null )
			{
				antlrTool.error("Arguments of rule reference '" + rr.targetRule + "' cannot set or ref #"+
					currentRule.getRuleName()+" on line "+rr.getLine());
			}
			_print(args);

			// Warn if the rule accepts no arguments
			if (rs.block.argAction == null)
			{
				antlrTool.warning("Rule '" + rr.targetRule + "' accepts no arguments",
					grammar.getFilename(),
					rr.getLine(), rr.getColumn());
			}
		}
		else
		{
			// For C++, no warning if rule has parameters, because there may be default
			// values for all of the parameters
			//if (rs.block.argAction != null) {
			//	tool.warning("Missing parameters on reference to rule "+rr.targetRule, rr.getLine());
			//}
		}
		_println(");");

		// move down to the first child while parsing
		if ( grammar instanceof TreeWalkerGrammar ) {
			println("_t = _retTree;");
		}
	}
	protected void genSemPred(String pred, int line) {
		// translate $ and # references
		ActionTransInfo tInfo = new ActionTransInfo();
		pred = processActionForSpecialSymbols(pred, line, currentRule, tInfo);
		// ignore translation info...we don't need to do anything with it.
		String escapedPred = charFormatter.escapeString(pred);

		// if debugging, wrap the semantic predicate evaluation in a method
		// that can tell SemanticPredicateListeners the result
		if (grammar.debuggingOutput && ((grammar instanceof ParserGrammar) ||
			  (grammar instanceof LexerGrammar)))
			pred = "fireSemanticPredicateEvaluated(antlr.debug.SemanticPredicateEvent.VALIDATING," //FIXME
				+ addSemPred(escapedPred) + "," + pred + ")";
		println("if (!(" + pred + "))");
		tabs++;
		println("throw "+namespaceAntlr+"SemanticException(\"" + escapedPred + "\");");
		tabs--;
	}
	/** Write an array of Strings which are the semantic predicate
	 *  expressions.  The debugger will reference them by number only
	 */
	protected void genSemPredMap(String prefix) {
		Enumeration e = semPreds.elements();
		println("const char* " + prefix + "_semPredNames[] = {");
		tabs++;
		while(e.hasMoreElements())
			println("\""+e.nextElement()+"\",");
		println("0");
		tabs--;
		println("};");
	}
	protected void genSynPred(SynPredBlock blk, String lookaheadExpr) {
		if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("gen=>("+blk+")");

		// Dump synpred result variable
		println("bool synPredMatched" + blk.ID + " = false;");

		if( grammar instanceof TreeWalkerGrammar ) {
			println("if (_t == "+labeledElementASTInit+" )");
			tabs++;
			println("_t = ASTNULL;");
			tabs--;
		}

		// Gen normal lookahead test
		println("if (" + lookaheadExpr + ") {");
		tabs++;

		// Save input state
		if ( grammar instanceof TreeWalkerGrammar ) {
			println(labeledElementType + " __t" + blk.ID + " = _t;");
		}
		else {
			println("int _m" + blk.ID + " = mark();");
		}

		// Once inside the try, assume synpred works unless exception caught
		println("synPredMatched" + blk.ID + " = true;");
		println("inputState->guessing++;");

		// if debugging, tell listeners that a synpred has started
		if (grammar.debuggingOutput && ((grammar instanceof ParserGrammar) ||
			 (grammar instanceof LexerGrammar))) {
			println("fireSyntacticPredicateStarted();");
		}

		syntacticPredLevel++;
		println("try {");
		tabs++;
		gen((AlternativeBlock)blk);		// gen code to test predicate
		tabs--;
		//println("System.out.println(\"pred "+blk+" succeeded\");");
		println("}");
		println("catch (" + exceptionThrown + "& pe) {");
		tabs++;
		println("synPredMatched"+blk.ID+" = false;");
		//println("System.out.println(\"pred "+blk+" failed\");");
		tabs--;
		println("}");

		// Restore input state
		if ( grammar instanceof TreeWalkerGrammar ) {
			println("_t = __t"+blk.ID+";");
		}
		else {
			println("rewind(_m"+blk.ID+");");
		}

		println("inputState->guessing--;");

		// if debugging, tell listeners how the synpred turned out
		if (grammar.debuggingOutput && ((grammar instanceof ParserGrammar) ||
		     (grammar instanceof LexerGrammar))) {
			println("if (synPredMatched" + blk.ID +")");
			println("  fireSyntacticPredicateSucceeded();");
			println("else");
			println("  fireSyntacticPredicateFailed();");
		}

		syntacticPredLevel--;
		tabs--;

		// Close lookahead test
		println("}");

		// Test synpred result
		println("if ( synPredMatched"+blk.ID+" ) {");
	}
	/** Generate a static array containing the names of the tokens,
	 * indexed by the token type values.  This static array is used
	 * to format error messages so that the token identifers or literal
	 * strings are displayed instead of the token numbers.
	 *
	 * If a lexical rule has a paraphrase, use it rather than the
	 * token label.
	 */
	public void genTokenStrings(String prefix) {
		// Generate a string for each token.  This creates a static
		// array of Strings indexed by token type.
//		println("");
		println("const char* " + prefix + "tokenNames[] = {");
		tabs++;

		// Walk the token vocabulary and generate a Vector of strings
		// from the tokens.
		Vector v = grammar.tokenManager.getVocabulary();
		for (int i = 0; i < v.size(); i++)
		{
			String s = (String)v.elementAt(i);
			if (s == null)
			{
				s = "<"+String.valueOf(i)+">";
			}
			if ( !s.startsWith("\"") && !s.startsWith("<") ) {
				TokenSymbol ts = (TokenSymbol)grammar.tokenManager.getTokenSymbol(s);
				if ( ts!=null && ts.getParaphrase()!=null ) {
					s = StringUtils.stripFrontBack(ts.getParaphrase(), "\"", "\"");
				}
			}
			print(charFormatter.literalString(s));
			_println(",");
		}
		println("0");

		// Close the string array initailizer
		tabs--;
		println("};");
	}
	/** Generate the token types C++ file */
	protected void genTokenTypes(TokenManager tm) throws IOException {
		// Open the token output header file and set the currentOutput stream
		outputFile = tm.getName() + TokenTypesFileSuffix+".hpp";
		outputLine = 1;
		currentOutput = antlrTool.openOutputFile(outputFile);
		//SAS: changed for proper text file io

		tabs = 0;

		// Generate a guard wrapper
		println("#ifndef INC_"+tm.getName()+TokenTypesFileSuffix+"_hpp_");
		println("#define INC_"+tm.getName()+TokenTypesFileSuffix+"_hpp_");
		println("");

		if (nameSpace != null)
			nameSpace.emitDeclarations(currentOutput);

		// Generate the header common to all C++ files
		genHeader(outputFile);

		// Encapsulate the definitions in an interface.  This can be done
		// because they are all constants.
		println("");
		println("#ifndef CUSTOM_API");
		println("# define CUSTOM_API");
		println("#endif");
		println("");
		// In the case that the .hpp is included from C source (flexLexer!)
		// we just turn things into a plain enum
		println("#ifdef __cplusplus");
		println("struct CUSTOM_API " + tm.getName() + TokenTypesFileSuffix+" {");
		println("#endif");
		tabs++;
		println("enum {");
		tabs++;

		// Generate a definition for each token type
		Vector v = tm.getVocabulary();

		// Do special tokens manually
		println("EOF_ = " + Token.EOF_TYPE + ",");

		// Move the other special token to the end, so we can solve
		// the superfluous comma problem easily

		for (int i = Token.MIN_USER_TYPE; i < v.size(); i++) {
			String s = (String)v.elementAt(i);
			if (s != null) {
				if ( s.startsWith("\"") ) {
					// a string literal
					StringLiteralSymbol sl = (StringLiteralSymbol)tm.getTokenSymbol(s);
					if ( sl==null ) {
						antlrTool.panic("String literal "+s+" not in symbol table");
					}
					else if ( sl.label != null ) {
						println(sl.label + " = " + i + ",");
					}
					else {
						String mangledName = mangleLiteral(s);
						if (mangledName != null) {
							// We were able to create a meaningful mangled token name
							println(mangledName + " = " + i + ",");
							// if no label specified, make the label equal to the mangled name
							sl.label = mangledName;
						}
						else {
							println("// " + s + " = " + i);
						}
					}
				}
				else if ( !s.startsWith("<") ) {
					println(s + " = " + i + ",");
				}
			}
		}

		// Moved from above
		println("NULL_TREE_LOOKAHEAD = " + Token.NULL_TREE_LOOKAHEAD);

		// Close the enum
		tabs--;
		println("};");

		// Close the interface
		tabs--;
		println("#ifdef __cplusplus");
		println("};");
		println("#endif");

		if (nameSpace != null)
			nameSpace.emitClosures(currentOutput);

		// Generate a guard wrapper
		println("#endif /*INC_"+tm.getName()+TokenTypesFileSuffix+"_hpp_*/");

		// Close the tokens output file
		currentOutput.close();
		currentOutput = null;
		exitIfError();
	}
	/** Process a string for an simple expression for use in xx/action.g
	 * it is used to cast simple tokens/references to the right type for
	 * the generated language. Basically called for every element in
	 * the vector to getASTCreateString(vector V)
	 * @param str A String.
	 */
	public String processStringForASTConstructor( String str )
	{
		if( usingCustomAST &&
			((grammar instanceof TreeWalkerGrammar) ||
			 (grammar instanceof ParserGrammar))  &&
			!(grammar.tokenManager.tokenDefined(str) ) )
		{
//			System.out.println("processStringForASTConstructor: "+str+" with cast");
			return namespaceAntlr+"RefAST("+str+")";
		}
		else
		{
//			System.out.println("processStringForASTConstructor: "+str);
			return str;
		}
	}
	/** Get a string for an expression to generate creation of an AST subtree.
	  * @param v A Vector of String, where each element is an expression
	  * in the target language yielding an AST node.
	  */
	public String getASTCreateString(Vector v) {
		if (v.size() == 0) {
			return "";
		}
		StringBuffer buf = new StringBuffer();
		// the labeledElementASTType here can probably be a cast or nothing
		// in the case of ! usingCustomAST
		buf.append(labeledElementASTType+
					"(astFactory->make((new "+namespaceAntlr+
					  "ASTArray("+v.size()+"))");
		for (int i = 0; i < v.size(); i++) {
			buf.append("->add("+ v.elementAt(i) + ")");
		}
		buf.append("))");
		return buf.toString();
	}
	/** Get a string for an expression to generate creating of an AST node
	 * @param str The arguments to the AST constructor
	 */
	public String getASTCreateString(GrammarAtom atom, String str) {
		if ( atom!=null && atom.getASTNodeType() != null ) {

			// this atom is using a heterogeneous AST type. (and maybe a local
			// override we can't see at the TokenManager level)
			// make note of the factory needed to generate it..
			// later this is inserted into the initializeFactory method.
			astTypes.ensureCapacity(atom.getType());
			String type = (String)astTypes.elementAt(atom.getType());
			if( type == null )
				astTypes.setElementAt(atom.getASTNodeType(),atom.getType());
			else
			{
				// give a warning over action taken if the types are unequal
				if( ! atom.getASTNodeType().equals(type) )
				{
					antlrTool.warning("Attempt to redefine AST type for "+atom.getText(),grammar.getFilename(),atom.getLine(),atom.getColumn());
					antlrTool.warning(" from \""+type+"\" to \""+atom.getASTNodeType()+"\" sticking to \""+type+"\"",grammar.getFilename(),atom.getLine(),atom.getColumn());
				}
				else
					astTypes.setElementAt(atom.getASTNodeType(),atom.getType());
			}
			// after above init the factory knows what to generate...
			return "astFactory->create("+str+")";
		}
		else
		{
			// FIXME: This is *SO* ugly! but it will have to do for now...
			// 2.7.2 will have better I hope
			// this is due to the usage of getASTCreateString from inside
			// actions/cpp/action.g
			boolean is_constructor = false;
			if( str.indexOf(',') != -1 )
				is_constructor = grammar.tokenManager.tokenDefined(str.substring(0,str.indexOf(',')));

//			System.out.println("getAstCreateString(as): "+str+" "+grammar.tokenManager.tokenDefined(str));
			if( usingCustomAST &&
			   (grammar instanceof TreeWalkerGrammar) &&
				!(grammar.tokenManager.tokenDefined(str) ) &&
				! is_constructor )
				return "astFactory->create("+namespaceAntlr+"RefAST("+str+"))";
			else
				return "astFactory->create("+str+")";
		}
	}

	/** Get a string for an expression to generate creating of an AST node
	 * @param str The arguments to the AST constructor
	 */
	public String getASTCreateString(String str) {
//		System.out.println("getAstCreateString(str): "+str+" "+grammar.tokenManager.tokenDefined(str));
		if( usingCustomAST )
			return labeledElementASTType+"(astFactory->create("+namespaceAntlr+"RefAST("+str+")))";
		else
			return "astFactory->create("+str+")";
	}

	protected String getLookaheadTestExpression(Lookahead[] look, int k) {
		StringBuffer e = new StringBuffer(100);
		boolean first = true;

		e.append("(");
		for (int i = 1; i <= k; i++) {
			BitSet p = look[i].fset;
			if (!first) {
				e.append(") && (");
			}
			first = false;

			// Syn preds can yield <end-of-syn-pred> (epsilon) lookahead.
			// There is no way to predict what that token would be.  Just
			// allow anything instead.
			if (look[i].containsEpsilon()) {
				e.append("true");
			} else {
				e.append(getLookaheadTestTerm(i, p));
			}
		}
		e.append(")");

		return e.toString();
	}
	/** Generate a lookahead test expression for an alternate.  This
	 * will be a series of tests joined by '&&' and enclosed by '()',
	 * the number of such tests being determined by the depth of the lookahead.
	 */
	protected String getLookaheadTestExpression(Alternative alt, int maxDepth) {
		int depth = alt.lookaheadDepth;
		if ( depth == GrammarAnalyzer.NONDETERMINISTIC ) {
			// if the decision is nondeterministic, do the best we can: LL(k)
			// any predicates that are around will be generated later.
			depth = grammar.maxk;
		}

		if ( maxDepth==0 ) {
			// empty lookahead can result from alt with sem pred
			// that can see end of token.  E.g., A : {pred}? ('a')? ;
			return "true";
		}

/*
boolean first = true;
		for (int i=1; i<=depth && i<=maxDepth; i++) {
			BitSet p = alt.cache[i].fset;
			if (!first) {
				e.append(") && (");
			}
			first = false;

			// Syn preds can yield <end-of-syn-pred> (epsilon) lookahead.
			// There is no way to predict what that token would be.  Just
			// allow anything instead.
			if ( alt.cache[i].containsEpsilon() ) {
				e.append("true");
			}
			else {
				e.append(getLookaheadTestTerm(i, p));
			}
		}

		e.append(")");
*/

		return "(" + getLookaheadTestExpression(alt.cache,depth) + ")";
	}
	/**Generate a depth==1 lookahead test expression given the BitSet.
	 * This may be one of:
	 * 1) a series of 'x==X||' tests
	 * 2) a range test using >= && <= where possible,
	 * 3) a bitset membership test for complex comparisons
	 * @param k The lookahead level
	 * @param p The lookahead set for level k
	 */
	protected String getLookaheadTestTerm(int k, BitSet p) {
		// Determine the name of the item to be compared
		String ts = lookaheadString(k);

		// Generate a range expression if possible
		int[] elems = p.toArray();
		if (elementsAreRange(elems)) {
			return getRangeExpression(k, elems);
		}

		// Generate a bitset membership test if possible
		StringBuffer e;
		int degree = p.degree();
		if ( degree == 0 ) {
			return "true";
		}

		if (degree >= bitsetTestThreshold) {
			int bitsetIdx = markBitsetForGen(p);
			return getBitsetName(bitsetIdx) + ".member(" + ts + ")";
		}

		// Otherwise, generate the long-winded series of "x==X||" tests
		e = new StringBuffer();
		for (int i = 0; i < elems.length; i++) {
			// Get the compared-to item (token or character value)
			String cs = getValueString(elems[i]);

			// Generate the element comparison
			if( i > 0 ) e.append(" || ");
			e.append(ts);
			e.append(" == ");
			e.append(cs);
		}
		return e.toString();
	}
	/** Return an expression for testing a contiguous renage of elements
	 * @param k The lookahead level
	 * @param elems The elements representing the set, usually from BitSet.toArray().
	 * @return String containing test expression.
	 */
	public String getRangeExpression(int k, int[] elems) {
		if (!elementsAreRange(elems)) {
			antlrTool.panic("getRangeExpression called with non-range");
		}
		int begin = elems[0];
		int end = elems[elems.length-1];
		return
			"(" + lookaheadString(k) + " >= " + getValueString(begin) + " && " +
			  lookaheadString(k) + " <= " + getValueString(end) + ")";
	}
	/** getValueString: get a string representation of a token or char value
	 * @param value The token or char value
	 */
	private String getValueString(int value) {
		String cs;
		if ( grammar instanceof LexerGrammar ) {
			cs = charFormatter.literalChar(value);
		}
		else
		{
			TokenSymbol ts = grammar.tokenManager.getTokenSymbolAt(value);
			if ( ts == null ) {
				return ""+value; // return token type as string
				// tool.panic("vocabulary for token type " + value + " is null");
			}
			String tId = ts.getId();
			if ( ts instanceof StringLiteralSymbol ) {
				// if string literal, use predefined label if any
				// if no predefined, try to mangle into LITERAL_xxx.
				// if can't mangle, use int value as last resort
				StringLiteralSymbol sl = (StringLiteralSymbol)ts;
				String label = sl.getLabel();
				if ( label!=null ) {
					cs = label;
				}
				else {
					cs = mangleLiteral(tId);
					if (cs == null) {
						cs = String.valueOf(value);
					}
				}
			}
			else {
				if ( tId.equals("EOF") )
					cs = namespaceAntlr+"Token::EOF_TYPE";
				else
					cs = tId;
			}
		}
		return cs;
	}
	/**Is the lookahead for this alt empty? */
	protected boolean lookaheadIsEmpty(Alternative alt, int maxDepth) {
		int depth = alt.lookaheadDepth;
		if ( depth == GrammarAnalyzer.NONDETERMINISTIC ) {
			depth = grammar.maxk;
		}
		for (int i=1; i<=depth && i<=maxDepth; i++) {
			BitSet p = alt.cache[i].fset;
			if (p.degree() != 0) {
				return false;
			}
		}
		return true;
	}
	private String lookaheadString(int k) {
		if (grammar instanceof TreeWalkerGrammar) {
			return "_t->getType()";
		}
		return "LA(" + k + ")";
	}
	/** Mangle a string literal into a meaningful token name.  This is
	  * only possible for literals that are all characters.  The resulting
	  * mangled literal name is literalsPrefix with the text of the literal
	  * appended.
	  * @return A string representing the mangled literal, or null if not possible.
	  */
	private String mangleLiteral(String s) {
		String mangled = antlrTool.literalsPrefix;
		for (int i = 1; i < s.length()-1; i++) {
			if (!Character.isLetter(s.charAt(i)) &&
				 s.charAt(i) != '_') {
				return null;
			}
			mangled += s.charAt(i);
		}
		if ( antlrTool.upperCaseMangledLiterals ) {
			mangled = mangled.toUpperCase();
		}
		return mangled;
	}
	/** Map an identifier to it's corresponding tree-node variable.
	  * This is context-sensitive, depending on the rule and alternative
	  * being generated
	  * @param idParam The identifier name to map
	  * @return The mapped id (which may be the same as the input), or null if the mapping is invalid due to duplicates
	  */
	public String mapTreeId(String idParam, ActionTransInfo transInfo) {
		// if not in an action of a rule, nothing to map.
		if ( currentRule==null ) return idParam;
//		System.out.print("mapTreeId: "+idParam+" "+currentRule.getRuleName()+" ");

		boolean in_var = false;
		String id = idParam;
		if (grammar instanceof TreeWalkerGrammar)
		{
//			RK: hmmm this seems odd. If buildAST is false it translates
//			#rulename_in to 'rulename_in' else to 'rulename_AST_in' which indeed
//			exists. disabling for now.. and hope it doesn't blow up somewhere.
			if ( !grammar.buildAST )
			{
				in_var = true;
//				System.out.println("in_var1");
			}
			// If the id ends with "_in", then map it to the input variable
//			else
			if (id.length() > 3 && id.lastIndexOf("_in") == id.length()-3)
			{
				// Strip off the "_in"
				id = id.substring(0, id.length()-3);
				in_var = true;
//				System.out.println("in_var2");
			}
		}
//		System.out.print(in_var+"\t");

		// Check the rule labels.  If id is a label, then the output
		// variable is label_AST, and the input variable is plain label.
		for (int i = 0; i < currentRule.labeledElements.size(); i++)
		{
			AlternativeElement elt = (AlternativeElement)currentRule.labeledElements.elementAt(i);
			if (elt.getLabel().equals(id))
			{
//				if( in_var )
//					System.out.println("returning (vec) "+(in_var ? id : id + "_AST"));
				return in_var ? id : id + "_AST";
			}
		}

		// Failing that, check the id-to-variable map for the alternative.
		// If the id is in the map, then output variable is the name in the
		// map, and input variable is name_in
		String s = (String)treeVariableMap.get(id);
		if (s != null)
		{
			if (s == NONUNIQUE)
			{
//				if( in_var )
//					System.out.println("returning null (nonunique)");
				// There is more than one element with this id
				antlrTool.error("Ambiguous reference to AST element "+id+
								" in rule "+currentRule.getRuleName());
				return null;
			}
			else if (s.equals(currentRule.getRuleName()))
			{
				// a recursive call to the enclosing rule is
				// ambiguous with the rule itself.
//				if( in_var )
//					System.out.println("returning null (rulename)");
				antlrTool.error("Ambiguous reference to AST element "+id+
								" in rule "+currentRule.getRuleName());
				return null;
			}
			else
			{
//				if( in_var )
//				System.out.println("returning "+(in_var?s+"_in":s));
				return in_var ? s + "_in" : s;
			}
		}

//		System.out.println("Last check: "+id+" == "+currentRule.getRuleName());
		// Failing that, check the rule name itself.  Output variable
		// is rule_AST; input variable is rule_AST_in (treeparsers).
		if( id.equals(currentRule.getRuleName()) )
		{
			String r = in_var ? id + "_AST_in" : id + "_AST";
			if ( transInfo!=null ) {
				if ( !in_var ) {
					transInfo.refRuleRoot = r;
				}
			}
//			if( in_var )
//				System.out.println("returning (r) "+r);
			return r;
		}
		else
		{
//			if( in_var )
//			System.out.println("returning (last) "+id);
			// id does not map to anything -- return itself.
			return id;
		}
	}
	/** Given an element and the name of an associated AST variable,
	  * create a mapping between the element "name" and the variable name.
	  */
	private void mapTreeVariable(AlternativeElement e, String name)
	{
		// For tree elements, defer to the root
		if (e instanceof TreeElement) {
			mapTreeVariable( ((TreeElement)e).root, name);
			return;
		}

		// Determine the name of the element, if any, for mapping purposes
		String elName = null;

		// Don't map labeled items
		if (e.getLabel() == null) {
			if (e instanceof TokenRefElement) {
				// use the token id
				elName = ((TokenRefElement)e).atomText;
			}
			else if (e instanceof RuleRefElement) {
				// use the rule name
				elName = ((RuleRefElement)e).targetRule;
			}
		}
		// Add the element to the tree variable map if it has a name
		if (elName != null) {
			if (treeVariableMap.get(elName) != null) {
				// Name is already in the map -- mark it as duplicate
				treeVariableMap.remove(elName);
				treeVariableMap.put(elName, NONUNIQUE);
			}
			else {
				treeVariableMap.put(elName, name);
			}
		}
	}

	/** Lexically process tree-specifiers in the action.
	 * This will replace #id and #(...) with the appropriate
	 * function calls and/or variables.
	 */
	protected String processActionForSpecialSymbols(String actionStr,
																	int line,
																	RuleBlock currentRule,
																	ActionTransInfo tInfo)
	{
		if ( actionStr==null || actionStr.length()==0 )
			return null;

		// The action trans info tells us (at the moment) whether an
		// assignment was done to the rule's tree root.
		if (grammar==null)
			return actionStr;

		if ((grammar.buildAST && actionStr.indexOf('#') != -1) ||
			 grammar instanceof TreeWalkerGrammar ||
			 ((grammar instanceof LexerGrammar ||
				grammar instanceof ParserGrammar)
			  	&& actionStr.indexOf('$') != -1) )
		{
			// Create a lexer to read an action and return the translated version
			antlr.actions.cpp.ActionLexer lexer =
				new antlr.actions.cpp.ActionLexer(actionStr, currentRule, this, tInfo);
			lexer.setLineOffset(line);
			lexer.setFilename(grammar.getFilename());
			lexer.setTool(antlrTool);

			try {
				lexer.mACTION(true);
				actionStr = lexer.getTokenObject().getText();
				// System.out.println("action translated: "+actionStr);
				// System.out.println("trans info is "+tInfo);
			}
			catch (RecognitionException ex) {
				lexer.reportError(ex);
				return actionStr;
			}
			catch (TokenStreamException tex) {
				antlrTool.panic("Error reading action:"+actionStr);
				return actionStr;
			}
			catch (CharStreamException io) {
				antlrTool.panic("Error reading action:"+actionStr);
				return actionStr;
			}
		}
		return actionStr;
	}

	private String fixNameSpaceOption( String ns )
	{
		ns = StringUtils.stripFrontBack(ns,"\"","\"");
		if( ns.length() > 2 &&
			 !ns.substring(ns.length()-2, ns.length()).equals("::") )
		ns += "::";
		return ns;
	}

	private void setupGrammarParameters(Grammar g) {
		if (g instanceof ParserGrammar ||
			 g instanceof LexerGrammar  ||
			 g instanceof TreeWalkerGrammar
			)
		{
			/* RK: options also have to be added to Grammar.java and for options
			 * on the file level entries have to be defined in
			 * DefineGrammarSymbols.java and passed around via 'globals' in
			 * antlrTool.java
			 */
			if( antlrTool.nameSpace != null )
				nameSpace = antlrTool.nameSpace;

			if( antlrTool.namespaceStd != null )
				namespaceStd = fixNameSpaceOption(antlrTool.namespaceStd);

			if( antlrTool.namespaceAntlr != null )
				namespaceAntlr = fixNameSpaceOption(antlrTool.namespaceAntlr);

			genHashLines = antlrTool.genHashLines;

			/* let grammar level options override filelevel ones...
			 */
			if( g.hasOption("namespace") ) {
				Token t = g.getOption("namespace");
				if( t != null ) {
					nameSpace = new NameSpace(t.getText());
				}
			}
			if( g.hasOption("namespaceAntlr") ) {
				Token t = g.getOption("namespaceAntlr");
				if( t != null ) {
					String ns = StringUtils.stripFrontBack(t.getText(),"\"","\"");
					if ( ns != null ) {
						if( ns.length() > 2 &&
							 !ns.substring(ns.length()-2, ns.length()).equals("::") )
							ns += "::";
						namespaceAntlr = ns;
					}
				}
			}
			if( g.hasOption("namespaceStd") ) {
				Token t = g.getOption("namespaceStd");
				if( t != null ) {
					String ns = StringUtils.stripFrontBack(t.getText(),"\"","\"");
					if ( ns != null ) {
						if( ns.length() > 2 &&
							 !ns.substring(ns.length()-2, ns.length()).equals("::") )
							ns += "::";
						namespaceStd = ns;
					}
				}
			}
			if( g.hasOption("genHashLines") ) {
				Token t = g.getOption("genHashLines");
				if( t != null ) {
					String val = StringUtils.stripFrontBack(t.getText(),"\"","\"");
					genHashLines = val.equals("true");
				}
			}
			noConstructors = antlrTool.noConstructors;	// get the default
			if( g.hasOption("noConstructors") ) {
				Token t = g.getOption("noConstructors");
				if( (t != null) && !(t.getText().equals("true") || t.getText().equals("false")))
					antlrTool.error("noConstructors option must be true or false", antlrTool.getGrammarFile(), t.getLine(), t.getColumn());
				noConstructors = t.getText().equals("true");
			}
		}
		if (g instanceof ParserGrammar) {
			labeledElementASTType = namespaceAntlr+"RefAST";
			labeledElementASTInit = namespaceAntlr+"nullAST";
			if ( g.hasOption("ASTLabelType") ) {
				Token tsuffix = g.getOption("ASTLabelType");
				if ( tsuffix != null ) {
					String suffix = StringUtils.stripFrontBack(tsuffix.getText(),"\"","\"");
					if ( suffix != null ) {
						usingCustomAST = true;
						labeledElementASTType = suffix;
						labeledElementASTInit = suffix+"("+namespaceAntlr+"nullAST)";
					}
				}
			}
			labeledElementType = namespaceAntlr+"RefToken ";
			labeledElementInit = namespaceAntlr+"nullToken";
			commonExtraArgs = "";
			commonExtraParams = "";
			commonLocalVars = "";
			lt1Value = "LT(1)";
			exceptionThrown = namespaceAntlr+"RecognitionException";
			throwNoViable = "throw "+namespaceAntlr+"NoViableAltException(LT(1), getFilename());";
		}
		else if (g instanceof LexerGrammar) {
			labeledElementType = "char ";
			labeledElementInit = "'\\0'";
			commonExtraArgs = "";
			commonExtraParams = "bool _createToken";
			commonLocalVars = "int _ttype; "+namespaceAntlr+"RefToken _token; "+namespaceStd+"string::size_type _begin = text.length();";
			lt1Value = "LA(1)";
			exceptionThrown = namespaceAntlr+"RecognitionException";
			throwNoViable = "throw "+namespaceAntlr+"NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());";
		}
		else if (g instanceof TreeWalkerGrammar) {
			labeledElementInit = namespaceAntlr+"nullAST";
			labeledElementASTInit = namespaceAntlr+"nullAST";
			labeledElementASTType = namespaceAntlr+"RefAST";
			labeledElementType = namespaceAntlr+"RefAST";
			commonExtraParams = namespaceAntlr+"RefAST _t";
			throwNoViable = "throw "+namespaceAntlr+"NoViableAltException(_t);";
			lt1Value = "_t";
			if ( g.hasOption("ASTLabelType") ) {
				Token tsuffix = g.getOption("ASTLabelType");
				if ( tsuffix != null ) {
					String suffix = StringUtils.stripFrontBack(tsuffix.getText(),"\"","\"");
					if ( suffix != null ) {
						usingCustomAST = true;
						labeledElementASTType = suffix;
						labeledElementType = suffix;
						labeledElementInit = suffix+"("+namespaceAntlr+"nullAST)";
						labeledElementASTInit = labeledElementInit;
						commonExtraParams = suffix+" _t";
						throwNoViable = "throw "+namespaceAntlr+"NoViableAltException("+namespaceAntlr+"RefAST(_t));";
						lt1Value = "_t";
					}
				}
			}
			if ( !g.hasOption("ASTLabelType") ) {
				g.setOption("ASTLabelType", new Token(ANTLRTokenTypes.STRING_LITERAL,namespaceAntlr+"RefAST"));
			}
			commonExtraArgs = "_t";
			commonLocalVars = "";
			exceptionThrown = namespaceAntlr+"RecognitionException";
		}
		else {
			antlrTool.panic("Unknown grammar type");
		}
	}
}
