1	package antlr;
2	
3	/**
4	 * <b>SOFTWARE RIGHTS</b>
5	 * <p>
6	 * ANTLR 2.5.0 MageLang Institute, 1998
7	 * <p>
8	 * We reserve no legal rights to the ANTLR--it is fully in the
9	 * public domain. An individual or company may do whatever
10	 * they wish with source code distributed with ANTLR or the
11	 * code generated by ANTLR, including the incorporation of
12	 * ANTLR, or its output, into commerical software.
13	 * <p>
14	 * We encourage users to develop software with ANTLR. However,
15	 * we do ask that credit is given to us for developing
16	 * ANTLR. By "credit", we mean that if you use ANTLR or
17	 * incorporate any source code into one of your programs
18	 * (commercial product, research project, or otherwise) that
19	 * you acknowledge this fact somewhere in the documentation,
20	 * research report, etc... If you like ANTLR and have
21	 * developed a nice tool with the output, please mention that
22	 * you developed it using ANTLR. In addition, we ask that the
23	 * headers remain intact in our source code. As long as these
24	 * guidelines are kept, we expect to continue enhancing this
25	 * system and expect to make other tools available as they are
26	 * completed.
27	 * <p>
28	 * The ANTLR gang:
29	 * @version ANTLR 2.5.0 MageLang Institute, 1998
30	 * @author Terence Parr, <a href=http://www.MageLang.com>MageLang Institute</a>
31	 * @author <br>John Lilley, <a href=http://www.Empathy.com>Empathy Software</a>
32	 */
33	import java.util.Enumeration;
34	import antlr.collections.impl.BitSet;
35	import antlr.collections.impl.Vector;
36	import java.io.PrintWriter; //SAS: changed for proper text file io
37	import java.io.IOException;
38	import java.io.FileWriter;
39	
40	/**Generate P.html, a cross-linked representation of P with or without actions */
41	public class HTMLCodeGenerator extends CodeGenerator {
42		/** non-zero if inside syntactic predicate generation */
43		protected int syntacticPredLevel = 0;
44	
45		/** true during lexer generation, false during parser generation */
46		protected boolean doingLexRules = false;
47	
48		protected boolean firstElementInAlt;
49	
50		protected AlternativeElement prevAltElem = null;	// what was generated last?
51	
52		/** Create a Diagnostic code-generator using the given Grammar
53		 * The caller must still call setTool, setBehavior, and setAnalyzer
54		 * before generating code.
55		 */
56		public HTMLCodeGenerator() {
57			super();
58			charFormatter = new JavaCharFormatter();
59		}
60		public void gen() {
61	
62			// Do the code generation
63			try {
64				// Loop over all grammars
65				Enumeration grammarIter = behavior.grammars.elements();
66				while (grammarIter.hasMoreElements()) {
67					Grammar g = (Grammar)grammarIter.nextElement();
68	
69					// Connect all the components to each other
70					/*
71					g.setGrammarAnalyzer(analyzer);
72					analyzer.setGrammar(g);
73					*/
74					g.setCodeGenerator(this);
75	
76					// To get right overloading behavior across hetrogeneous grammars
77					g.generate();
78		
79					if (tool.hasError) {
80						System.out.println("Exiting due to errors.");
81						System.exit(1);
82					}
83	
84				}
85	
86				/*
87				// Loop over all token managers (some of which are lexers)
88				Enumeration tmIter = behavior.tokenManagers.elements();
89				while (tmIter.hasMoreElements()) {
90					TokenManager tm = (TokenManager)tmIter.nextElement();
91					if (!tm.isReadOnly()) {
92						// Write the token manager tokens as Java
93						genTokenTypes(tm);
94					}
95				}
96				*/
97			}
98			catch (IOException e) {
99				System.out.println(e.getMessage());
100			}
101		}
102		/** Generate code for the given grammar element.
103		 * @param blk The {...} action to generate
104		 */
105		public void gen(ActionElement action) {
106			/*
107			_print("{");
108			_printAction(action.actionText);
109			_print("} ");
110			*/
111		}
112	/** Generate code for the given grammar element.
113	 * @param blk The "x|y|z|..." block to generate
114	 */
115	public void gen(AlternativeBlock blk) {
116		genGenericBlock(blk, "");
117	}
118		/** Generate code for the given grammar element.
119		 * @param blk The block-end element to generate.  Block-end
120		 * elements are synthesized by the grammar parser to represent
121		 * the end of a block.
122		 */
123		public void gen(BlockEndElement end) {
124			// no-op
125		}
126		/** Generate code for the given grammar element.
127		 * @param blk The character literal reference to generate
128		 */
129		public void gen(CharLiteralElement atom) {
130			/*
131			if (atom.label != null) {
132				_print(atom.label+"=");
133			}
134			*/
135			if (atom.not) {
136				_print("~");
137			}
138			_print(atom.atomText+" ");
139		}
140		/** Generate code for the given grammar element.
141		 * @param blk The character-range reference to generate
142		 */
143		public void gen(CharRangeElement r) {
144			/*
145			if ( r.label!=null ) {
146				_print(r.label+"=");
147			}
148			*/
149			print(r.beginText + ".." + r.endText+" ");
150		}
151		/** Generate the lexer TXT file */
152		public void gen(LexerGrammar g) throws IOException {
153			setGrammar(g);
154			System.out.println("Generating " + grammar.getClassName() + ".txt");
155			currentOutput = antlr.Tool.openOutputFile(grammar.getClassName() + ".txt");
156			//SAS: changed for proper text file io
157			
158			tabs=0;
159			doingLexRules = true;
160	
161			// Generate header common to all TXT output files
162			genHeader();
163	
164			/*
165			// Output the user-defined lexer premamble
166			println(grammar.preambleAction);
167			*/
168			
169			// Generate lexer class definition
170			println("");
171	
172			// print javadoc comment if any
173			if ( grammar.comment!=null ) {
174				_println(grammar.comment);
175			}
176			
177			println("class " + grammar.getClassName() + " extends " + grammar.getSuperClass() + " {");
178	
179			// Generate user-defined parser class members
180			// printAction(grammar.classMemberAction);
181	
182			/*
183			// Generate string literals
184			println("");
185			println("*** String literals used in the parser");
186			println("The following string literals were used in the parser.");
187			println("An actual code generator would arrange to place these literals");
188			println("into a table in the generated lexer, so that actions in the");
189			println("generated lexer could match token text against the literals.");
190			println("String literals used in the lexer are not listed here, as they");
191			println("are incorporated into the mainstream lexer processing.");
192			tabs++;
193			// Enumerate all of the symbols and look for string literal symbols
194			Enumeration ids = grammar.getSymbols();
195			while ( ids.hasMoreElements() ) {
196				GrammarSymbol sym = (GrammarSymbol)ids.nextElement();
197				// Only processing string literals -- reject other symbol entries
198				if ( sym instanceof StringLiteralSymbol ) {
199					StringLiteralSymbol s = (StringLiteralSymbol)sym;
200					println(s.getId() + " = " + s.getTokenType());
201				}
202			}
203			tabs--;
204			println("*** End of string literals used by the parser");
205			*/
206			
207			// Generate nextToken() rule.
208			// nextToken() is a synthetic lexer rule that is the implicit OR of all
209			// user-defined lexer rules.
210			genNextToken();
211	
212			// Generate code for each rule in the lexer
213			
214			Enumeration ids = grammar.rules.elements();
215			while ( ids.hasMoreElements() ) {
216				RuleSymbol rs = (RuleSymbol)ids.nextElement();
217				if (!rs.id.equals("mnextToken")) {
218					genRule(rs);
219				}
220			}
221	
222			// Close the lexer output file
223			currentOutput.close();
224			currentOutput = null;
225			doingLexRules = false;
226		}
227	/** Generate code for the given grammar element.
228	 * @param blk The (...)+ block to generate
229	 */
230	public void gen(OneOrMoreBlock blk) {
231		genGenericBlock(blk, "+");
232	}
233		/** Generate the parser TXT file */
234		public void gen(ParserGrammar g) throws IOException {
235			setGrammar(g);
236			// Open the output stream for the parser and set the currentOutput
237			System.out.println("Generating " + grammar.getClassName() + ".html");
238			currentOutput = antlr.Tool.openOutputFile(grammar.getClassName()+".html");
239			
240			tabs = 0;
241	
242			// Generate the header common to all output files.
243			genHeader();
244			
245			/*
246			_print("{");
247			printAction(grammar.preambleAction);
248			_print("}");
249			*/
250	
251			// Generate parser class definition
252			println("");
253			
254			// print javadoc comment if any
255			if ( grammar.comment!=null ) {
256				_println(grammar.comment);
257			}
258			
259			println("class " + grammar.getClassName() + " extends " + grammar.getSuperClass());
260	
261			/*
262			// Generate user-defined parser class members
263			println("");
264			_print("{");
265			printAction(grammar.classMemberAction);
266			_print("}");
267			*/
268	
269			// Enumerate the parser rules
270			Enumeration rules = grammar.rules.elements();
271			while ( rules.hasMoreElements() ) {
272				println("");
273				// Get the rules from the list and downcast it to proper type
274				GrammarSymbol sym = (GrammarSymbol) rules.nextElement();
275				// Only process parser rules
276				if ( sym instanceof RuleSymbol) {
277					genRule((RuleSymbol)sym);
278				}
279			}
280			tabs--;
281			println("");
282	
283			genTail();
284			
285			// Close the parser output stream
286			currentOutput.close();
287			currentOutput = null;
288		}
289		/** Generate code for the given grammar element.
290		 * @param blk The rule-reference to generate
291		 */
292		public void gen(RuleRefElement rr) {
293			RuleSymbol rs = (RuleSymbol)grammar.getSymbol(rr.targetRule);
294	
295			// Generate the actual rule description
296			/*
297			if ( rr.idAssign!=null ) {
298				_print(rr.idAssign+"=");
299			}
300			*/
301			_print("<a href="+grammar.getClassName() + ".html#"+rr.targetRule+">");
302			_print(rr.targetRule);
303			_print("</a>");
304			if (rr.args != null) {
305				_print("["+rr.args+"]");
306			}
307			_print(" ");
308		}
309		/** Generate code for the given grammar element.
310		 * @param blk The string-literal reference to generate
311		 */
312		public void gen(StringLiteralElement atom) {
313			/*
314			if (atom.label != null) {
315				_print(atom.label+"=");
316			}
317			*/
318			if (atom.not) {
319				_print("~");
320			}
321			_print(atom.atomText);
322			_print(" ");
323		}
324		/** Generate code for the given grammar element.
325		 * @param blk The token-range reference to generate
326		 */
327		public void gen(TokenRangeElement r) {
328			/*
329			if ( r.label!=null ) {
330				_print(r.label+"=");
331			}
332			*/
333			print(r.beginText + ".." + r.endText+" ");
334		}
335		/** Generate code for the given grammar element.
336		 * @param blk The token-reference to generate
337		 */
338		public void gen(TokenRefElement atom) {
339			/*
340			if (atom.label != null) {
341				_print(atom.label+"=");
342			}
343			*/
344			if (atom.not) {
345				_print("~");
346			}
347			_print(atom.atomText);
348			_print(" ");
349		}
350		public void gen(TreeElement t) {
351			print(t+" ");
352		}
353		/** Generate the tree-walker TXT file */
354		public  void gen(TreeWalkerGrammar g) throws IOException {
355			setGrammar(g);
356			// Open the output stream for the parser and set the currentOutput
357			System.out.println("Generating " + grammar.getClassName() + ".txt");
358			currentOutput = antlr.Tool.openOutputFile(grammar.getClassName()+".txt");
359			//SAS: changed for proper text file io
360			
361			tabs = 0;
362	
363			// Generate the header common to all output files.
364			genHeader();
365			
366			// Output the user-defined parser premamble
367			println("");
368			println("*** Tree-walker Preamble Action.");
369			println("This action will appear before the declaration of your tree-walker class:");
370			tabs++;
371			println(grammar.preambleAction);
372			tabs--;
373			println("*** End of tree-walker Preamble Action");
374	
375			// Generate tree-walker class definition
376			println("");
377			
378			// print javadoc comment if any
379			if ( grammar.comment!=null ) {
380				_println(grammar.comment);
381			}
382			
383			println("class " + grammar.getClassName() + " extends " + grammar.getSuperClass() + "{");
384	
385			// Generate user-defined tree-walker class members
386			println("");
387			println("*** User-defined tree-walker class members:");
388			println("These are the member declarations that you defined for your class:");
389			tabs++;
390			printAction(grammar.classMemberAction);
391			tabs--;
392			println("*** End of user-defined tree-walker class members");
393	
394			// Generate code for each rule in the grammar
395			println("");
396			println("*** tree-walker rules:");
397			tabs++;
398	
399			// Enumerate the tree-walker rules
400			Enumeration rules = grammar.rules.elements();
401			while ( rules.hasMoreElements() ) {
402				println("");
403				// Get the rules from the list and downcast it to proper type
404				GrammarSymbol sym = (GrammarSymbol) rules.nextElement();
405				// Only process tree-walker rules
406				if ( sym instanceof RuleSymbol) {
407					genRule((RuleSymbol)sym);
408				}
409			}
410			tabs--;
411			println("");
412			println("*** End of tree-walker rules");
413	
414			println("");
415			println("*** End of tree-walker");
416	
417			// Close the tree-walker output stream
418			currentOutput.close();
419			currentOutput = null;
420		}
421		/** Generate a wildcard element */
422		public void gen(WildcardElement wc) {
423			/*
424			if ( wc.getLabel()!=null ) {
425				_print(wc.getLabel()+"=");
426			}
427			*/
428			_print(". ");
429		}
430	/** Generate code for the given grammar element.
431	 * @param blk The (...)* block to generate
432	 */
433	public void gen(ZeroOrMoreBlock blk) {
434		genGenericBlock(blk, "*");
435	}
436	protected void genAlt(Alternative alt) {
437		if (alt.getTreeSpecifier() != null) {
438			_print(alt.getTreeSpecifier().getText());
439		}
440		prevAltElem = null;
441		for (AlternativeElement elem = alt.head; !(elem instanceof BlockEndElement); elem = elem.next) {
442			elem.generate();
443			firstElementInAlt = false;
444			prevAltElem = elem;
445		}
446	}
447		/** Generate the header for a block, which may be a RuleBlock or a
448		 * plain AlternativeBLock.  This generates any variable declarations,
449		 * init-actions, and syntactic-predicate-testing variables.
450		 * @blk The block for which the preamble is to be generated.
451		 */
452		protected void genBlockPreamble(AlternativeBlock blk) {
453			// dump out init action
454			if ( blk.initAction!=null ) {
455				printAction("{" + blk.initAction + "}");
456			}
457		}
458	/**Generate common code for a block of alternatives; return a postscript
459	 * that needs to be generated at the end of the block.  Other routines
460	 * may append else-clauses and such for error checking before the postfix
461	 * is generated.
462	 */
463	public void genCommonBlock(AlternativeBlock blk) {
464		for (int i = 0; i < blk.alternatives.size(); i++) {
465			Alternative alt = blk.getAlternativeAt(i);
466			AlternativeElement elem = alt.head;
467	
468			// dump alt operator |
469			if ( i>0 && blk.alternatives.size()>1 ) {
470				/*
471				// only do newline if the last element wasn't a multi-line block
472				if ( prevAltElem==null ||
473					 !(prevAltElem instanceof AlternativeBlock) ||
474					 ((AlternativeBlock)prevAltElem).alternatives.size()==1 )
475				{
476					_println("");
477				}
478				*/
479				_println("");
480				print("|\t");
481			}
482	
483			// Dump the alternative, starting with predicates
484			
485			boolean save = firstElementInAlt;
486			firstElementInAlt = true;
487			tabs++;	// in case we do a newline in alt, increase the tab indent
488			// Dump semantic predicates
489			if (alt.semPred != null) {
490				println("{" + alt.semPred + "}?");
491			}
492			// Dump syntactic predicate
493			if (alt.synPred != null) {
494				genSynPred(alt.synPred);
495			}
496			genAlt(alt);
497			tabs--;
498			firstElementInAlt = save;
499		}
500	}
501		/** Generate a textual representation of the follow set
502		 * for a block.
503		 * @param blk  The rule block of interest
504		 */
505		public void genFollowSetForRuleBlock(RuleBlock blk)
506		{
507			Lookahead follow = grammar.theLLkAnalyzer.FOLLOW(1, blk.endNode);
508			printSet(grammar.maxk, 1, follow);
509		}
510	protected void genGenericBlock(AlternativeBlock blk, String blkOp) {
511		if (blk.alternatives.size() > 1) {
512			// make sure we start on a new line
513			if (!firstElementInAlt) {
514				// only do newline if the last element wasn't a multi-line block
515				if ( prevAltElem==null ||
516					 !(prevAltElem instanceof AlternativeBlock) ||
517					 ((AlternativeBlock)prevAltElem).alternatives.size()==1 )
518				{
519					_println("");
520					print("(\t");
521				}
522				else {
523					_print("(\t");
524				}
525				// _println("");
526				// print("(\t");
527			}
528			else {
529				_print("(\t");
530			}
531		} else {
532			_print("( ");
533		}
534		genBlockPreamble(blk);
535		genCommonBlock(blk);
536		if (blk.alternatives.size() > 1) {
537			_println("");
538			print(")" + blkOp + " ");
539			// if not last element of alt, need newline & to indent
540			if ( !(blk.next instanceof BlockEndElement) ) {
541				_println("");
542				print("");
543			}
544		} else {
545			_print(")" + blkOp + " ");
546		}
547	}
548		/** Generate a header that is common to all TXT files */
549		protected void genHeader() 
550		{
551			println("<HTML>");
552			println("<HEAD>");
553			println("<TITLE>Grammar "+tool.grammarFile+"</TITLE>");
554			println("</HEAD>");
555			println("<BODY>");
556			println("<table border=1 cellpadding=5>");
557			println("<tr>");
558			println("<td>");
559			println("<font size=+2>Grammar "+grammar.getClassName()+"</font><br>");
560			println("<a href=http://www.ANTLR.org>ANTLR</a>-generated HTML file from "+tool.grammarFile);
561			println("<p>");
562			println("Terence Parr, <a href=http://www.magelang.com>MageLang Institute</a>");
563			println("<br>ANTLR Version "+ANTLRParser.version+"; 1989-1998");
564			println("</td>");
565			println("</tr>");
566			println("</table>");
567			println("<PRE>");
568			tabs++;
569			printAction(behavior.headerAction);
570			tabs--;
571		}
572		/**Generate the lookahead set for an alternate. */
573		protected void genLookaheadSetForAlt(Alternative alt) {
574			if ( doingLexRules && alt.cache[1].containsEpsilon() ) {
575				println("MATCHES ALL");
576				return;
577			}
578			int depth = alt.lookaheadDepth;
579			if ( depth == GrammarAnalyzer.NONDETERMINISTIC ) {
580				// if the decision is nondeterministic, do the best we can: LL(k)
581				// any predicates that are around will be generated later.
582				depth = grammar.maxk;
583			}
584			for (int i = 1; i <= depth; i++)
585			{
586				Lookahead lookahead = alt.cache[i];
587				printSet(depth, i, lookahead);
588			}
589		}
590		/** Generate a textual representation of the lookahead set
591		 * for a block.
592		 * @param blk  The block of interest
593		 */
594		public void genLookaheadSetForBlock(AlternativeBlock blk)
595		{
596			// Find the maximal lookahead depth over all alternatives
597			int depth = 0;
598			for (int i=0; i<blk.alternatives.size(); i++) {
599				Alternative alt = blk.getAlternativeAt(i);
600				if (alt.lookaheadDepth == GrammarAnalyzer.NONDETERMINISTIC) {
601					depth = grammar.maxk;
602					break;
603				} 
604				else if (depth < alt.lookaheadDepth) {
605					depth = alt.lookaheadDepth;
606				}
607			}
608	
609			for (int i = 1; i <= depth; i++)
610			{
611				Lookahead lookahead = grammar.theLLkAnalyzer.look(i, blk);
612				printSet(depth, i, lookahead);
613			}
614		}
615		/** Generate the nextToken rule.
616		 * nextToken is a synthetic lexer rule that is the implicit OR of all
617		 * user-defined lexer rules.
618		 */
619		public void genNextToken() {
620			println("");
621			println("/** Lexer nextToken rule:");
622			println(" *  The lexer nextToken rule is synthesized from all of the user-defined");
623			println(" *  lexer rules.  It logically consists of one big alternative block with");
624			println(" *  each user-defined rule being an alternative.");
625			println(" */");
626	
627			// Create the synthesized rule block for nextToken consisting
628			// of an alternate block containing all the user-defined lexer rules.
629			RuleBlock blk = MakeGrammar.createNextTokenRule(grammar, grammar.rules, "nextToken");
630	
631			// Define the nextToken rule symbol
632			RuleSymbol nextTokenRs = new RuleSymbol("mnextToken");
633			nextTokenRs.setDefined();
634			nextTokenRs.setBlock(blk);
635			nextTokenRs.access = "private";
636			grammar.define(nextTokenRs);
637	
638			/*
639			// Analyze the synthesized block
640			if (!grammar.theLLkAnalyzer.deterministic(blk))
641			{
642				println("The grammar analyzer has determined that the synthesized");
643				println("nextToken rule is non-deterministic (i.e., it has ambiguities)");
644				println("This means that there is some overlap of the character");
645				println("lookahead for two or more of your lexer rules.");
646			}
647			*/
648	
649			genCommonBlock(blk);
650		}
651		/** Generate code for a named rule block
652		 * @param s The RuleSymbol describing the rule to generate
653		*/
654		public void genRule(RuleSymbol s) {
655			if ( s==null || !s.isDefined() ) return;	// undefined rule
656			println("");
657			if ( s.comment!=null ) {
658				_println(s.comment);
659			}
660			if (s.access.length() != 0) {
661				if ( !s.access.equals("public") ) {
662					_print(s.access+" ");
663				}
664			}
665			_print("<a name="+s.getId()+">");
666			_print(s.getId());
667			_print("</a>");
668			
669			// Get rule return type and arguments
670			RuleBlock rblk = s.getBlock();
671	
672			// Gen method return value(s)
673			if (rblk.returnAction != null) {
674				_print("["+rblk.returnAction+"]");
675			}
676			// Gen arguments
677			if (rblk.argAction != null) 
678			{
679				_print(" returns [" + rblk.argAction+"]");
680			}
681			_println("");
682			tabs++;
683			print(":\t");
684	
685			// Dump any init-action
686			// genBlockPreamble(rblk);
687	
688			// Dump the alternates of the rule
689			genCommonBlock(rblk);
690	
691			_println("");
692			println(";");
693			tabs--;
694		}
695		/** Generate the syntactic predicate.  This basically generates
696		 * the alternative block, buts tracks if we are inside a synPred
697		 * @param blk  The syntactic predicate block
698		 */
699		protected void genSynPred(SynPredBlock blk) {
700			syntacticPredLevel++;
701			genGenericBlock(blk, " =>");
702			syntacticPredLevel--;
703		}
704		public void genTail() {
705			println("</PRE>");
706			println("</BODY>");
707			println("</HTML>");
708		}
709		/** Generate the token types TXT file */
710		protected void genTokenTypes(TokenManager tm) throws IOException {
711			// Open the token output TXT file and set the currentOutput stream
712			System.out.println("Generating " + tm.getName() + "TokenTypes.txt");
713			currentOutput = antlr.Tool.openOutputFile(tm.getName() + "TokenTypes.txt");
714			//SAS: changed for proper text file io
715			tabs = 0;
716		
717			// Generate the header common to all diagnostic files
718			genHeader();
719	
720			// Generate a string for each token.  This creates a static
721			// array of Strings indexed by token type.
722			println("");
723			println("*** Tokens used by the parser");
724			println("This is a list of the token numeric values and the corresponding");
725			println("token identifiers.  Some tokens are literals, and because of that");
726			println("they have no identifiers.  Literals are double-quoted.");
727			tabs++;
728	
729			// Enumerate all the valid token types
730			Vector v = tm.getVocabulary();
731			for (int i = Token.MIN_USER_TYPE; i < v.size(); i++) {
732				String s = (String)v.elementAt(i);
733				if (s != null) {
734					println(s + " = " + i);
735				}
736			}
737	
738			// Close the interface
739			tabs--;
740			println("*** End of tokens used by the parser");
741	
742			// Close the tokens output file
743			currentOutput.close();
744			currentOutput = null;
745		}
746		/** Get a string for an expression to generate creation of an AST subtree.
747		  * @param v A Vector of String, where each element is an expression in the target language yielding an AST node.
748		  */
749		public String getASTCreateString(Vector v) {
750			return null;
751		}
752		/** Get a string for an expression to generate creating of an AST node
753		  * @param str The arguments to the AST constructor
754		  */
755		public String getASTCreateString(String str) {
756			return null;
757		}
758		/** Map an identifier to it's corresponding tree-node variable.
759		  * This is context-sensitive, depending on the rule and alternative
760		  * being generated
761		  * @param id The identifier name to map
762		  * @param forInput true if the input tree node variable is to be returned, otherwise the output variable is returned.
763		  */
764		public String mapTreeId(String id, ActionTransInfo tInfo) {
765			return id;
766		}
767		/** Format a lookahead or follow set.
768		 * @param depth The depth of the entire lookahead/follow
769		 * @param k The lookahead level to print
770		 * @param lookahead  The lookahead/follow set to print
771		 */
772		public void printSet(int depth, int k, Lookahead lookahead) {
773			int numCols = 5;
774	
775			int[] elems = lookahead.fset.toArray();
776	
777			if (depth != 1) {
778				print("k==" + k + ": {");
779			} else {
780				print("{ ");
781			}
782			if (elems.length > numCols) {
783				_println("");
784				tabs++;
785				print("");
786			}
787	
788			int column = 0;
789			for (int i = 0; i < elems.length; i++)
790			{
791				column++;
792				if (column > numCols) {
793					_println("");
794					print("");
795					column = 0;
796				}
797				if (doingLexRules) {
798					_print(charFormatter.literalChar(elems[i]));
799				} else {
800					_print((String)grammar.tokenManager.getVocabulary().elementAt(elems[i]));
801				}
802				if (i != elems.length-1) {
803					_print(", ");
804				}
805			}
806	
807			if (elems.length > numCols) {
808				_println("");
809				tabs--;
810				print("");
811			}
812			_println(" }");
813		}
814	}
815