source: trunk/yao/share/antlr-2.7.7/antlr/CppCodeGenerator.java @ 1

Last change on this file since 1 was 1, checked in by lnalod, 15 years ago

Initial import of YAO sources

File size: 144.4 KB
Line 
1package antlr;
2
3/* ANTLR Translator Generator
4 * Project led by Terence Parr at http://www.cs.usfca.edu
5 * Software rights: http://www.antlr.org/license.html
6 *
7 * $Id: //depot/code/org.antlr/release/antlr-2.7.7/antlr/CppCodeGenerator.java#2 $
8 */
9
10// C++ code generator by Pete Wells: pete@yamuna.demon.co.uk
11// #line generation contributed by: Ric Klaren <klaren@cs.utwente.nl>
12
13import java.util.Enumeration;
14import java.util.Hashtable;
15import antlr.collections.impl.BitSet;
16import antlr.collections.impl.Vector;
17import java.io.PrintWriter; //SAS: changed for proper text file io
18import java.io.IOException;
19import java.io.FileWriter;
20
21/** Generate MyParser.cpp, MyParser.hpp, MyLexer.cpp, MyLexer.hpp
22 * and MyParserTokenTypes.hpp
23 */
24public class CppCodeGenerator extends CodeGenerator {
25        boolean DEBUG_CPP_CODE_GENERATOR = false;
26        // non-zero if inside syntactic predicate generation
27        protected int syntacticPredLevel = 0;
28
29        // Are we generating ASTs (for parsers and tree parsers) right now?
30        protected boolean genAST = false;
31
32        // Are we saving the text consumed (for lexers) right now?
33        protected boolean saveText = false;
34
35        // Generate #line's
36        protected boolean genHashLines = true;
37        // Generate constructors or not
38        protected boolean noConstructors = false;
39
40        // Used to keep track of lineno in output
41        protected int outputLine;
42        protected String outputFile;
43
44        // Grammar parameters set up to handle different grammar classes.
45        // These are used to get instanceof tests out of code generation
46        boolean usingCustomAST = false;
47        String labeledElementType;
48        String labeledElementASTType; // mostly the same as labeledElementType except in parsers
49        String labeledElementASTInit;
50        String labeledElementInit;
51        String commonExtraArgs;
52        String commonExtraParams;
53        String commonLocalVars;
54        String lt1Value;
55        String exceptionThrown;
56        String throwNoViable;
57
58        // Tracks the rule being generated.  Used for mapTreeId
59        RuleBlock currentRule;
60        // Tracks the rule or labeled subrule being generated.  Used for AST generation.
61        String currentASTResult;
62        // Mapping between the ids used in the current alt, and the
63        // names of variables used to represent their AST values.
64        Hashtable treeVariableMap = new Hashtable();
65
66        /** Used to keep track of which AST variables have been defined in a rule
67         * (except for the #rule_name and #rule_name_in var's
68         */
69        Hashtable declaredASTVariables = new Hashtable();
70
71        // Count of unnamed generated variables
72        int astVarNumber = 1;
73        // Special value used to mark duplicate in treeVariableMap
74        protected static final String NONUNIQUE = new String();
75
76        public static final int caseSizeThreshold = 127; // ascii is max
77
78        private Vector semPreds;
79
80        // Used to keep track of which (heterogeneous AST types are used)
81        // which need to be set in the ASTFactory of the generated parser
82        private Vector astTypes;
83
84        private static String namespaceStd   = "ANTLR_USE_NAMESPACE(std)";
85        private static String namespaceAntlr = "ANTLR_USE_NAMESPACE(antlr)";
86        private static NameSpace nameSpace = null;
87
88        private static final String preIncludeCpp  = "pre_include_cpp";
89        private static final String preIncludeHpp  = "pre_include_hpp";
90        private static final String postIncludeCpp = "post_include_cpp";
91        private static final String postIncludeHpp = "post_include_hpp";
92
93        /** Create a C++ code-generator using the given Grammar.
94         * The caller must still call setTool, setBehavior, and setAnalyzer
95         * before generating code.
96         */
97        public CppCodeGenerator() {
98                super();
99                charFormatter = new CppCharFormatter();
100        }
101        /** Adds a semantic predicate string to the sem pred vector
102            These strings will be used to build an array of sem pred names
103            when building a debugging parser.  This method should only be
104            called when the debug option is specified
105         */
106        protected int addSemPred(String predicate) {
107                semPreds.appendElement(predicate);
108                return semPreds.size()-1;
109        }
110        public void exitIfError()
111        {
112                if (antlrTool.hasError())
113                {
114                        antlrTool.fatalError("Exiting due to errors.");
115                }
116        }
117        protected int countLines( String s )
118        {
119                int lines = 0;
120                for( int i = 0; i < s.length(); i++ )
121                {
122                        if( s.charAt(i) == '\n' )
123                                lines++;
124                }
125                return lines;
126        }
127        /** Output a String to the currentOutput stream.
128         * Ignored if string is null.
129         * @param s The string to output
130         */
131        protected void _print(String s)
132        {
133                if (s != null)
134                {
135                        outputLine += countLines(s);
136                        currentOutput.print(s);
137                }
138        }
139        /** Print an action without leading tabs, attempting to
140         * preserve the current indentation level for multi-line actions
141         * Ignored if string is null.
142         * @param s The action string to output
143         */
144        protected void _printAction(String s)
145        {
146                if (s != null)
147                {
148                        outputLine += countLines(s)+1;
149                        super._printAction(s);
150                }
151        }
152        /** Print an action stored in a token surrounded by #line stuff */
153        public void printAction(Token t)
154        {
155                if (t != null)
156                {
157                        genLineNo(t.getLine());
158                        printTabs();
159                        _printAction(processActionForSpecialSymbols(t.getText(), t.getLine(),
160                                                                                                                                null, null) );
161                        genLineNo2();
162                }
163        }
164        /** Print a header action by #line stuff also process any tree construction
165         * @param name The name of the header part
166         */
167        public void printHeaderAction(String name)
168        {
169                Token a = (antlr.Token)behavior.headerActions.get(name);
170                if (a != null)
171                {
172                        genLineNo(a.getLine());
173                        println(processActionForSpecialSymbols(a.getText(), a.getLine(),
174                                                                                                                                null, null) );
175                        genLineNo2();
176                }
177        }
178        /** Output a String followed by newline, to the currentOutput stream.
179         * Ignored if string is null.
180         * @param s The string to output
181         */
182        protected void _println(String s) {
183                if (s != null) {
184                        outputLine += countLines(s)+1;
185                        currentOutput.println(s);
186                }
187        }
188        /** Output tab indent followed by a String followed by newline,
189         * to the currentOutput stream.  Ignored if string is null.
190         * @param s The string to output
191         */
192        protected void println(String s) {
193                if (s != null) {
194                        printTabs();
195                        outputLine += countLines(s)+1;
196                        currentOutput.println(s);
197                }
198        }
199
200        /** Generate a #line or // line depending on options */
201        public void genLineNo(int line) {
202                if ( line == 0 ) {
203                        line++;
204                }
205                if( genHashLines )
206                        _println("#line "+line+" \""+antlrTool.fileMinusPath(antlrTool.grammarFile)+"\"");
207        }
208
209        /** Generate a #line or // line depending on options */
210        public void genLineNo(GrammarElement el)
211        {
212                if( el != null )
213                        genLineNo(el.getLine());
214        }
215        /** Generate a #line or // line depending on options */
216        public void genLineNo(Token t)
217        {
218                if (t != null)
219                        genLineNo(t.getLine());
220        }
221        /** Generate a #line or // line depending on options */
222        public void genLineNo2()
223        {
224                if( genHashLines )
225                {
226                        _println("#line "+(outputLine+1)+" \""+outputFile+"\"");
227                }
228        }
229        /// Bound safe isDigit
230        private boolean charIsDigit( String s, int i )
231        {
232                return (i < s.length()) && Character.isDigit(s.charAt(i));
233        }
234        /** Normalize a string coming from antlr's lexer. E.g. translate java
235         * escapes to values. Check their size (multibyte) bomb out if they are
236         * multibyte (bit crude). Then reescape to C++ style things.
237         * Used to generate strings for match() and matchRange()
238         * @param lit the literal string
239         * @param isCharLiteral if it's for a character literal
240         *                       (enforced to be one length) and enclosed in '
241         * FIXME: bombing out on mb chars. Should be done in Lexer.
242         * FIXME: this is another horrible hack.
243         * FIXME: life would be soooo much easier if the stuff from the lexer was
244         * normalized in some way.
245         */
246        private String convertJavaToCppString( String lit, boolean isCharLiteral )
247        {
248                // System.out.println("convertJavaToCppLiteral: "+lit);
249                String ret = new String();
250                String s = lit;
251
252                int i = 0;
253                int val = 0;
254
255                if( isCharLiteral )     // verify & strip off quotes
256                {
257                        if( ! lit.startsWith("'") || ! lit.endsWith("'") )
258                                antlrTool.error("Invalid character literal: '"+lit+"'");
259                }
260                else
261                {
262                        if( ! lit.startsWith("\"") || ! lit.endsWith("\"") )
263                                antlrTool.error("Invalid character string: '"+lit+"'");
264                }
265                s = lit.substring(1,lit.length()-1);
266
267                String prefix="";
268                int maxsize = 255;
269                if( grammar instanceof LexerGrammar )
270                {
271                        // vocab size seems to be 1 bigger than it actually is
272                        maxsize = ((LexerGrammar)grammar).charVocabulary.size() - 1;
273                        if( maxsize > 255 )
274                                prefix= "L";
275                }
276
277                // System.out.println("maxsize "+maxsize+" prefix "+prefix);
278
279                while ( i < s.length() )
280                {
281                        if( s.charAt(i) == '\\' )
282                        {
283                                if( s.length() == i+1 )
284                                        antlrTool.error("Invalid escape in char literal: '"+lit+"' looking at '"+s.substring(i)+"'");
285
286                                // deal with escaped junk
287                                switch ( s.charAt(i+1) ) {
288                                case 'a' :
289                                        val = 7;
290                                        i += 2;
291                                        break;
292                                case 'b' :
293                                        val = 8;
294                                        i += 2;
295                                        break;
296                                case 't' :
297                                        val = 9;
298                                        i += 2;
299                                        break;
300                                case 'n' :
301                                        val = 10;
302                                        i += 2;
303                                        break;
304                                case 'f' :
305                                        val = 12;
306                                        i += 2;
307                                        break;
308                                case 'r' :
309                                        val = 13;
310                                        i += 2;
311                                        break;
312                                case '"' :
313                                case '\'' :
314                                case '\\' :
315                                        val = s.charAt(i+1);
316                                        i += 2;
317                                        break;
318
319                                case 'u' :
320                                        // Unicode char \u1234
321                                        if( i+5 < s.length() )
322                                        {
323                                                val = Character.digit(s.charAt(i+2), 16) * 16 * 16 * 16 +
324                                                        Character.digit(s.charAt(i+3), 16) * 16 * 16 +
325                                                        Character.digit(s.charAt(i+4), 16) * 16 +
326                                                        Character.digit(s.charAt(i+5), 16);
327                                                i += 6;
328                                        }
329                                        else
330                                                antlrTool.error("Invalid escape in char literal: '"+lit+"' looking at '"+s.substring(i)+"'");
331                                        break;
332
333                                case '0' :                                      // \123
334                                case '1' :
335                                case '2' :
336                                case '3' :
337                                        if( charIsDigit(s, i+2) )
338                                        {
339                                                if( charIsDigit(s, i+3) )
340                                                {
341                                                        val = (s.charAt(i+1)-'0')*8*8 + (s.charAt(i+2)-'0')*8 +
342                                                                (s.charAt(i+3)-'0');
343                                                        i += 4;
344                                                }
345                                                else
346                                                {
347                                                        val = (s.charAt(i+1)-'0')*8 + (s.charAt(i+2)-'0');
348                                                        i += 3;
349                                                }
350                                        }
351                                        else
352                                        {
353                                                val = s.charAt(i+1)-'0';
354                                                i += 2;
355                                        }
356                                        break;
357
358                                case '4' :
359                                case '5' :
360                                case '6' :
361                                case '7' :
362                                        if ( charIsDigit(s, i+2) )
363                                        {
364                                                val = (s.charAt(i+1)-'0')*8 + (s.charAt(i+2)-'0');
365                                                i += 3;
366                                        }
367                                        else
368                                        {
369                                                val = s.charAt(i+1)-'0';
370                                                i += 2;
371                                        }
372                                default:
373                                        antlrTool.error("Unhandled escape in char literal: '"+lit+"' looking at '"+s.substring(i)+"'");
374                                        val = 0;
375                                }
376                        }
377                        else
378                                val = s.charAt(i++);
379
380                        if( grammar instanceof LexerGrammar )
381                        {
382                                if( val > maxsize )                     // abort if too big
383                                {
384                                        String offender;
385                                        if( ( 0x20 <= val ) && ( val < 0x7F ) )
386                                                offender = charFormatter.escapeChar(val,true);
387                                        else
388                                                offender = "0x"+Integer.toString(val,16);
389
390                                        antlrTool.error("Character out of range in "+(isCharLiteral?"char literal":"string constant")+": '"+s+"'");
391                                        antlrTool.error("Vocabulary size: "+maxsize+" Character "+offender);
392                                }
393                        }
394
395                        if( isCharLiteral )
396                        {
397                                // we should be at end of char literal here..
398                                if( i != s.length() )
399                                        antlrTool.error("Invalid char literal: '"+lit+"'");
400
401                                if( maxsize <= 255 )
402                                {
403                                        if ( (val <= 255) && (val & 0x80) != 0 )
404                                                // the joys of sign extension in the support lib *cough*
405                                                // actually the support lib needs to be fixed but that's a bit
406                                                // hairy too.
407                                                ret = "static_cast<unsigned char>('"+charFormatter.escapeChar(val,true)+"')";
408                                        else
409                                                ret = "'"+charFormatter.escapeChar(val,true)+"'";
410                                }
411                                else
412                                {
413                                        // so wchar_t is some implementation defined int like thing
414                                        // so this may even lead to having 16 bit or 32 bit cases...
415                                        // I smell some extra grammar options in the future :(
416                                        ret = "L'"+charFormatter.escapeChar(val,true)+"'";
417                                }
418                        }
419                        else
420                                ret += charFormatter.escapeChar(val,true);
421                }
422                if( !isCharLiteral )
423                        ret = prefix+"\""+ret+"\"";
424                return ret;
425        }
426        /** Generate the parser, lexer, treeparser, and token types in C++
427         */
428        public void gen() {
429                // Do the code generation
430                try {
431                        // Loop over all grammars
432                        Enumeration grammarIter = behavior.grammars.elements();
433                        while (grammarIter.hasMoreElements()) {
434                                Grammar g = (Grammar)grammarIter.nextElement();
435                                if ( g.debuggingOutput ) {
436                                        antlrTool.error(g.getFilename()+": C++ mode does not support -debug");
437                                }
438                                // Connect all the components to each other
439                                g.setGrammarAnalyzer(analyzer);
440                                g.setCodeGenerator(this);
441                                analyzer.setGrammar(g);
442                                // To get right overloading behavior across hetrogeneous grammars
443                                setupGrammarParameters(g);
444                                g.generate();
445                                exitIfError();
446                        }
447
448                        // Loop over all token managers (some of which are lexers)
449                        Enumeration tmIter = behavior.tokenManagers.elements();
450                        while (tmIter.hasMoreElements()) {
451                                TokenManager tm = (TokenManager)tmIter.nextElement();
452                                if (!tm.isReadOnly()) {
453                                        // Write the token manager tokens as C++
454                                        // this must appear before genTokenInterchange so that
455                                        // labels are set on string literals
456                                        genTokenTypes(tm);
457                                        // Write the token manager tokens as plain text
458                                        genTokenInterchange(tm);
459                                }
460                                exitIfError();
461                        }
462                }
463                catch (IOException e) {
464                        antlrTool.reportException(e, null);
465                }
466        }
467        /** Generate code for the given grammar element.
468         * @param blk The {...} action to generate
469         */
470        public void gen(ActionElement action) {
471                if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genAction("+action+")");
472                if ( action.isSemPred ) {
473                        genSemPred(action.actionText, action.line);
474                }
475                else {
476                        if ( grammar.hasSyntacticPredicate ) {
477                                println("if ( inputState->guessing==0 ) {");
478                                tabs++;
479                        }
480
481                        ActionTransInfo tInfo = new ActionTransInfo();
482                        String actionStr = processActionForSpecialSymbols(action.actionText,
483                                                                                                                                                          action.getLine(),
484                                                                                                                                                          currentRule, tInfo);
485
486                        if ( tInfo.refRuleRoot!=null ) {
487                                // Somebody referenced "#rule", make sure translated var is valid
488                                // assignment to #rule is left as a ref also, meaning that assignments
489                                // with no other refs like "#rule = foo();" still forces this code to be
490                                // generated (unnecessarily).
491                                println(tInfo.refRuleRoot + " = "+labeledElementASTType+"(currentAST.root);");
492                        }
493
494                        // dump the translated action
495                        genLineNo(action);
496                        printAction(actionStr);
497                        genLineNo2();
498
499                        if ( tInfo.assignToRoot ) {
500                                // Somebody did a "#rule=", reset internal currentAST.root
501                                println("currentAST.root = "+tInfo.refRuleRoot+";");
502                                // reset the child pointer too to be last sibling in sibling list
503                                // now use if else in stead of x ? y : z to shut CC 4.2 up.
504                                println("if ( "+tInfo.refRuleRoot+"!="+labeledElementASTInit+" &&");
505                                tabs++;
506                                println(tInfo.refRuleRoot+"->getFirstChild() != "+labeledElementASTInit+" )");
507                                println("  currentAST.child = "+tInfo.refRuleRoot+"->getFirstChild();");
508                                tabs--;
509                                println("else");
510                                tabs++;
511                                println("currentAST.child = "+tInfo.refRuleRoot+";");
512                                tabs--;
513                                println("currentAST.advanceChildToEnd();");
514                        }
515
516                        if ( grammar.hasSyntacticPredicate ) {
517                                tabs--;
518                                println("}");
519                        }
520                }
521        }
522
523        /** Generate code for the given grammar element.
524         * @param blk The "x|y|z|..." block to generate
525         */
526        public void gen(AlternativeBlock blk) {
527                if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("gen("+blk+")");
528                println("{");
529                genBlockPreamble(blk);
530                genBlockInitAction(blk);
531
532                // Tell AST generation to build subrule result
533                String saveCurrentASTResult = currentASTResult;
534                if (blk.getLabel() != null) {
535                        currentASTResult = blk.getLabel();
536                }
537
538                boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
539
540                CppBlockFinishingInfo howToFinish = genCommonBlock(blk, true);
541                genBlockFinish(howToFinish, throwNoViable);
542
543                println("}");
544
545                // Restore previous AST generation
546                currentASTResult = saveCurrentASTResult;
547        }
548        /** Generate code for the given grammar element.
549         * @param blk The block-end element to generate.  Block-end
550         * elements are synthesized by the grammar parser to represent
551         * the end of a block.
552         */
553        public void gen(BlockEndElement end) {
554                if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genRuleEnd("+end+")");
555        }
556        /** Generate code for the given grammar element.
557         * Only called from lexer grammars.
558         * @param blk The character literal reference to generate
559         */
560        public void gen(CharLiteralElement atom) {
561                if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR )
562                        System.out.println("genChar("+atom+")");
563
564                if ( ! (grammar instanceof LexerGrammar) )
565                        antlrTool.error("cannot ref character literals in grammar: "+atom);
566
567                if ( atom.getLabel() != null ) {
568                        println(atom.getLabel() + " = " + lt1Value + ";");
569                }
570
571                boolean oldsaveText = saveText;
572                saveText = saveText && atom.getAutoGenType() == GrammarElement.AUTO_GEN_NONE;
573
574                // if in lexer and ! on element, save buffer index to kill later
575                if ( !saveText||atom.getAutoGenType()==GrammarElement.AUTO_GEN_BANG )
576                        println("_saveIndex = text.length();");
577
578                print(atom.not ? "matchNot(" : "match(");
579                _print(convertJavaToCppString( atom.atomText, true ));
580                _println(" /* charlit */ );");
581
582                if ( !saveText || atom.getAutoGenType() == GrammarElement.AUTO_GEN_BANG )
583                        println("text.erase(_saveIndex);");      // kill text atom put in buffer
584
585                saveText = oldsaveText;
586        }
587        /** Generate code for the given grammar element.
588         * Only called from lexer grammars.
589         * @param blk The character-range reference to generate
590         */
591        public void gen(CharRangeElement r) {
592                if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR )
593                        System.out.println("genCharRangeElement("+r.beginText+".."+r.endText+")");
594
595                if ( ! (grammar instanceof LexerGrammar) )
596                        antlrTool.error("cannot ref character range in grammar: "+r);
597
598                if ( r.getLabel() != null && syntacticPredLevel == 0) {
599                        println(r.getLabel() + " = " + lt1Value + ";");
600                }
601                // Correctly take care of saveIndex stuff...
602                boolean save = ( grammar instanceof LexerGrammar &&
603                                                          ( !saveText ||
604                                                                 r.getAutoGenType() == GrammarElement.AUTO_GEN_BANG )
605                                                   );
606                if (save)
607         println("_saveIndex=text.length();");
608
609                println("matchRange("+convertJavaToCppString(r.beginText,true)+
610                                  ","+convertJavaToCppString(r.endText,true)+");");
611
612                if (save)
613         println("text.erase(_saveIndex);");
614        }
615        /** Generate the lexer C++ files */
616        public  void gen(LexerGrammar g) throws IOException {
617                // If debugging, create a new sempred vector for this grammar
618                if (g.debuggingOutput)
619                        semPreds = new Vector();
620
621                if( g.charVocabulary.size() > 256 )
622                        antlrTool.warning(g.getFilename()+": Vocabularies of this size still experimental in C++ mode (vocabulary size now: "+g.charVocabulary.size()+")");
623
624                setGrammar(g);
625                if (!(grammar instanceof LexerGrammar)) {
626                        antlrTool.panic("Internal error generating lexer");
627                }
628
629                genBody(g);
630                genInclude(g);
631        }
632        /** Generate code for the given grammar element.
633         * @param blk The (...)+ block to generate
634         */
635        public void gen(OneOrMoreBlock blk) {
636                if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("gen+("+blk+")");
637                String label;
638                String cnt;
639                println("{ // ( ... )+");
640                genBlockPreamble(blk);
641                if ( blk.getLabel() != null ) {
642                        cnt = "_cnt_"+blk.getLabel();
643                }
644                else {
645                        cnt = "_cnt" + blk.ID;
646                }
647                println("int "+cnt+"=0;");
648                if ( blk.getLabel() != null ) {
649                        label = blk.getLabel();
650                }
651                else {
652                        label = "_loop" + blk.ID;
653                }
654
655                println("for (;;) {");
656                tabs++;
657                // generate the init action for ()+ ()* inside the loop
658                // this allows us to do usefull EOF checking...
659                genBlockInitAction(blk);
660
661                // Tell AST generation to build subrule result
662                String saveCurrentASTResult = currentASTResult;
663                if (blk.getLabel() != null) {
664                        currentASTResult = blk.getLabel();
665                }
666
667                boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
668
669                // generate exit test if greedy set to false
670                // and an alt is ambiguous with exit branch
671                // or when lookahead derived purely from end-of-file
672                // Lookahead analysis stops when end-of-file is hit,
673                // returning set {epsilon}.  Since {epsilon} is not
674                // ambig with any real tokens, no error is reported
675                // by deterministic() routines and we have to check
676                // for the case where the lookahead depth didn't get
677                // set to NONDETERMINISTIC (this only happens when the
678                // FOLLOW contains real atoms + epsilon).
679                boolean generateNonGreedyExitPath = false;
680                int nonGreedyExitDepth = grammar.maxk;
681
682                if ( !blk.greedy &&
683                         blk.exitLookaheadDepth<=grammar.maxk &&
684                         blk.exitCache[blk.exitLookaheadDepth].containsEpsilon() )
685                {
686                        generateNonGreedyExitPath = true;
687                        nonGreedyExitDepth = blk.exitLookaheadDepth;
688                }
689                else if ( !blk.greedy &&
690                                  blk.exitLookaheadDepth==LLkGrammarAnalyzer.NONDETERMINISTIC )
691                {
692                        generateNonGreedyExitPath = true;
693                }
694
695                // generate exit test if greedy set to false
696                // and an alt is ambiguous with exit branch
697                if ( generateNonGreedyExitPath ) {
698                        if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) {
699                                System.out.println("nongreedy (...)+ loop; exit depth is "+
700                                                                   blk.exitLookaheadDepth);
701                        }
702                        String predictExit =
703                                getLookaheadTestExpression(blk.exitCache,
704                                                                                   nonGreedyExitDepth);
705                        println("// nongreedy exit test");
706                        println("if ( "+cnt+">=1 && "+predictExit+") goto "+label+";");
707                }
708
709                CppBlockFinishingInfo howToFinish = genCommonBlock(blk, false);
710                genBlockFinish(
711                        howToFinish,
712                        "if ( "+cnt+">=1 ) { goto "+label+"; } else {" + throwNoViable + "}"
713                );
714
715                println(cnt+"++;");
716                tabs--;
717                println("}");
718                println(label+":;");
719                println("}  // ( ... )+");
720
721                // Restore previous AST generation
722                currentASTResult = saveCurrentASTResult;
723        }
724        /** Generate the parser C++ file */
725        public void gen(ParserGrammar g) throws IOException {
726
727                // if debugging, set up a new vector to keep track of sempred
728                //   strings for this grammar
729                if (g.debuggingOutput)
730                        semPreds = new Vector();
731
732                setGrammar(g);
733                if (!(grammar instanceof ParserGrammar)) {
734                        antlrTool.panic("Internal error generating parser");
735                }
736
737                genBody(g);
738                genInclude(g);
739        }
740        /** Generate code for the given grammar element.
741         * @param blk The rule-reference to generate
742         */
743        public void gen(RuleRefElement rr)
744        {
745                if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genRR("+rr+")");
746                RuleSymbol rs = (RuleSymbol)grammar.getSymbol(rr.targetRule);
747                if (rs == null || !rs.isDefined())
748                {
749                        // Is this redundant???
750                        antlrTool.error("Rule '" + rr.targetRule + "' is not defined", grammar.getFilename(), rr.getLine(), rr.getColumn());
751                        return;
752                }
753                if (!(rs instanceof RuleSymbol))
754                {
755                        // Is this redundant???
756                        antlrTool.error("'" + rr.targetRule + "' does not name a grammar rule", grammar.getFilename(), rr.getLine(), rr.getColumn());
757                        return;
758                }
759
760                genErrorTryForElement(rr);
761
762                // AST value for labeled rule refs in tree walker.
763                // This is not AST construction;  it is just the input tree node value.
764                if ( grammar instanceof TreeWalkerGrammar &&
765                        rr.getLabel() != null &&
766                        syntacticPredLevel == 0 )
767                {
768                        println(rr.getLabel() + " = (_t == ASTNULL) ? "+labeledElementASTInit+" : "+lt1Value+";");
769                }
770
771                // if in lexer and ! on rule ref or alt or rule, save buffer index to
772                // kill later
773                if ( grammar instanceof LexerGrammar && (!saveText||rr.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) )
774                {
775                        println("_saveIndex = text.length();");
776                }
777
778                // Process return value assignment if any
779                printTabs();
780                if (rr.idAssign != null)
781                {
782                        // Warn if the rule has no return type
783                        if (rs.block.returnAction == null)
784                        {
785                                antlrTool.warning("Rule '" + rr.targetRule + "' has no return type", grammar.getFilename(), rr.getLine(), rr.getColumn());
786                        }
787                        _print(rr.idAssign + "=");
788                } else {
789                        // Warn about return value if any, but not inside syntactic predicate
790                        if ( !(grammar instanceof LexerGrammar) && syntacticPredLevel == 0 && rs.block.returnAction != null)
791                        {
792                                antlrTool.warning("Rule '" + rr.targetRule + "' returns a value", grammar.getFilename(), rr.getLine(), rr.getColumn());
793                        }
794                }
795
796                // Call the rule
797                GenRuleInvocation(rr);
798
799                // if in lexer and ! on element or alt or rule, save buffer index to kill later
800                if ( grammar instanceof LexerGrammar && (!saveText||rr.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
801                        println("text.erase(_saveIndex);");
802                }
803
804                // if not in a syntactic predicate
805                if (syntacticPredLevel == 0)
806                {
807                        boolean doNoGuessTest = (
808                                grammar.hasSyntacticPredicate &&
809                                (
810                                        grammar.buildAST && rr.getLabel() != null ||
811                                        (genAST && rr.getAutoGenType() == GrammarElement.AUTO_GEN_NONE)
812                                )
813                        );
814
815                        if (doNoGuessTest) {
816                                println("if (inputState->guessing==0) {");
817                                tabs++;
818                        }
819
820                        if (grammar.buildAST && rr.getLabel() != null)
821                        {
822                                // always gen variable for rule return on labeled rules
823                                // RK: hmm do I know here if the returnAST needs a cast ?
824                                println(rr.getLabel() + "_AST = returnAST;");
825                        }
826
827                        if (genAST)
828                        {
829                                switch (rr.getAutoGenType())
830                                {
831                                case GrammarElement.AUTO_GEN_NONE:
832                                        if( usingCustomAST )
833                                                println("astFactory->addASTChild(currentAST, "+namespaceAntlr+"RefAST(returnAST));");
834                                        else
835                                                println("astFactory->addASTChild( currentAST, returnAST );");
836                                        break;
837                                case GrammarElement.AUTO_GEN_CARET:
838                                        // FIXME: RK: I'm not so sure this should be an error..
839                                        // I think it might actually work and be usefull at times.
840                                        antlrTool.error("Internal: encountered ^ after rule reference");
841                                        break;
842                                default:
843                                        break;
844                                }
845                        }
846
847                        // if a lexer and labeled, Token label defined at rule level, just set it here
848                        if ( grammar instanceof LexerGrammar && rr.getLabel() != null )
849                        {
850                                println(rr.getLabel()+"=_returnToken;");
851                        }
852
853                        if (doNoGuessTest)
854                        {
855                                tabs--;
856                                println("}");
857                        }
858                }
859                genErrorCatchForElement(rr);
860        }
861        /** Generate code for the given grammar element.
862         * @param blk The string-literal reference to generate
863         */
864        public void gen(StringLiteralElement atom) {
865                if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genString("+atom+")");
866
867                // Variable declarations for labeled elements
868                if (atom.getLabel()!=null && syntacticPredLevel == 0) {
869                        println(atom.getLabel() + " = " + lt1Value + ";");
870                }
871
872                // AST
873                genElementAST(atom);
874
875                // is there a bang on the literal?
876                boolean oldsaveText = saveText;
877                saveText = saveText && atom.getAutoGenType()==GrammarElement.AUTO_GEN_NONE;
878
879                // matching
880                genMatch(atom);
881
882                saveText = oldsaveText;
883
884                // tack on tree cursor motion if doing a tree walker
885                if (grammar instanceof TreeWalkerGrammar) {
886                        println("_t = _t->getNextSibling();");
887                }
888        }
889        /** Generate code for the given grammar element.
890         * @param blk The token-range reference to generate
891         */
892        public void gen(TokenRangeElement r) {
893                genErrorTryForElement(r);
894                if ( r.getLabel()!=null  && syntacticPredLevel == 0) {
895                        println(r.getLabel() + " = " + lt1Value + ";");
896                }
897
898                // AST
899                genElementAST(r);
900
901                // match
902                println("matchRange("+r.beginText+","+r.endText+");");
903                genErrorCatchForElement(r);
904        }
905        /** Generate code for the given grammar element.
906         * @param blk The token-reference to generate
907         */
908        public void gen(TokenRefElement atom) {
909                if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genTokenRef("+atom+")");
910                if ( grammar instanceof LexerGrammar ) {
911                        antlrTool.panic("Token reference found in lexer");
912                }
913                genErrorTryForElement(atom);
914                // Assign Token value to token label variable
915                if ( atom.getLabel()!=null && syntacticPredLevel == 0) {
916                        println(atom.getLabel() + " = " + lt1Value + ";");
917                }
918
919                // AST
920                genElementAST(atom);
921                // matching
922                genMatch(atom);
923                genErrorCatchForElement(atom);
924
925                // tack on tree cursor motion if doing a tree walker
926                if (grammar instanceof TreeWalkerGrammar) {
927                        println("_t = _t->getNextSibling();");
928                }
929        }
930        public void gen(TreeElement t) {
931                // save AST cursor
932                println(labeledElementType+" __t" + t.ID + " = _t;");
933
934                // If there is a label on the root, then assign that to the variable
935                if (t.root.getLabel() != null) {
936                        println(t.root.getLabel() + " = (_t == "+labeledElementType+"(ASTNULL)) ? "+labeledElementASTInit+" : _t;");
937                }
938
939                // check for invalid modifiers ! and ^ on tree element roots
940                if ( t.root.getAutoGenType() == GrammarElement.AUTO_GEN_BANG ) {
941                        antlrTool.error("Suffixing a root node with '!' is not implemented",
942                                                  grammar.getFilename(), t.getLine(), t.getColumn());
943                        t.root.setAutoGenType(GrammarElement.AUTO_GEN_NONE);
944                }
945                if ( t.root.getAutoGenType() == GrammarElement.AUTO_GEN_CARET ) {
946                        antlrTool.warning("Suffixing a root node with '^' is redundant; already a root",
947                                                         grammar.getFilename(), t.getLine(), t.getColumn());
948                        t.root.setAutoGenType(GrammarElement.AUTO_GEN_NONE);
949                }
950
951                // Generate AST variables
952                genElementAST(t.root);
953                if (grammar.buildAST) {
954                        // Save the AST construction state
955                        println(namespaceAntlr+"ASTPair __currentAST" + t.ID + " = currentAST;");
956                        // Make the next item added a child of the TreeElement root
957                        println("currentAST.root = currentAST.child;");
958                        println("currentAST.child = "+labeledElementASTInit+";");
959                }
960
961                // match root
962                if ( t.root instanceof WildcardElement ) {
963                        println("if ( _t == ASTNULL ) throw "+namespaceAntlr+"MismatchedTokenException();");
964                }
965                else {
966                        genMatch(t.root);
967                }
968                // move to list of children
969                println("_t = _t->getFirstChild();");
970
971                // walk list of children, generating code for each
972                for (int i=0; i<t.getAlternatives().size(); i++) {
973                        Alternative a = t.getAlternativeAt(i);
974                        AlternativeElement e = a.head;
975                        while ( e != null ) {
976                                e.generate();
977                                e = e.next;
978                        }
979                }
980
981                if (grammar.buildAST) {
982                        // restore the AST construction state to that just after the
983                        // tree root was added
984                        println("currentAST = __currentAST" + t.ID + ";");
985                }
986                // restore AST cursor
987                println("_t = __t" + t.ID + ";");
988                // move cursor to sibling of tree just parsed
989                println("_t = _t->getNextSibling();");
990        }
991        /** Generate the tree-parser C++ files */
992        public void gen(TreeWalkerGrammar g) throws IOException {
993                setGrammar(g);
994                if (!(grammar instanceof TreeWalkerGrammar)) {
995                        antlrTool.panic("Internal error generating tree-walker");
996                }
997
998                genBody(g);
999                genInclude(g);
1000        }
1001        /** Generate code for the given grammar element.
1002         * @param wc The wildcard element to generate
1003         */
1004        public void gen(WildcardElement wc) {
1005                // Variable assignment for labeled elements
1006                if (wc.getLabel()!=null && syntacticPredLevel == 0) {
1007                        println(wc.getLabel() + " = " + lt1Value + ";");
1008                }
1009
1010                // AST
1011                genElementAST(wc);
1012                // Match anything but EOF
1013                if (grammar instanceof TreeWalkerGrammar) {
1014                        println("if ( _t == "+labeledElementASTInit+" ) throw "+namespaceAntlr+"MismatchedTokenException();");
1015                }
1016                else if (grammar instanceof LexerGrammar) {
1017                        if ( grammar instanceof LexerGrammar &&
1018                                        (!saveText||wc.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
1019                                println("_saveIndex = text.length();");
1020                        }
1021                        println("matchNot(EOF/*_CHAR*/);");
1022                        if ( grammar instanceof LexerGrammar &&
1023                                        (!saveText||wc.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
1024                                println("text.erase(_saveIndex);");      // kill text atom put in buffer
1025                        }
1026                }
1027                else {
1028                        println("matchNot(" + getValueString(Token.EOF_TYPE) + ");");
1029                }
1030
1031                // tack on tree cursor motion if doing a tree walker
1032                if (grammar instanceof TreeWalkerGrammar) {
1033                        println("_t = _t->getNextSibling();");
1034                }
1035        }
1036        /** Generate code for the given grammar element.
1037         * @param blk The (...)* block to generate
1038         */
1039        public void gen(ZeroOrMoreBlock blk) {
1040                if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("gen*("+blk+")");
1041                println("{ // ( ... )*");
1042                genBlockPreamble(blk);
1043                String label;
1044                if ( blk.getLabel() != null ) {
1045                        label = blk.getLabel();
1046                }
1047                else {
1048                        label = "_loop" + blk.ID;
1049                }
1050                println("for (;;) {");
1051                tabs++;
1052                // generate the init action for ()+ ()* inside the loop
1053                // this allows us to do usefull EOF checking...
1054                genBlockInitAction(blk);
1055
1056                // Tell AST generation to build subrule result
1057                String saveCurrentASTResult = currentASTResult;
1058                if (blk.getLabel() != null) {
1059                        currentASTResult = blk.getLabel();
1060                }
1061
1062                boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
1063
1064                // generate exit test if greedy set to false
1065                // and an alt is ambiguous with exit branch
1066                // or when lookahead derived purely from end-of-file
1067                // Lookahead analysis stops when end-of-file is hit,
1068                // returning set {epsilon}.  Since {epsilon} is not
1069                // ambig with any real tokens, no error is reported
1070                // by deterministic() routines and we have to check
1071                // for the case where the lookahead depth didn't get
1072                // set to NONDETERMINISTIC (this only happens when the
1073                // FOLLOW contains real atoms + epsilon).
1074                boolean generateNonGreedyExitPath = false;
1075                int nonGreedyExitDepth = grammar.maxk;
1076
1077                if ( !blk.greedy &&
1078                         blk.exitLookaheadDepth<=grammar.maxk &&
1079                         blk.exitCache[blk.exitLookaheadDepth].containsEpsilon() )
1080                {
1081                        generateNonGreedyExitPath = true;
1082                        nonGreedyExitDepth = blk.exitLookaheadDepth;
1083                }
1084                else if ( !blk.greedy &&
1085                                  blk.exitLookaheadDepth==LLkGrammarAnalyzer.NONDETERMINISTIC )
1086                {
1087                        generateNonGreedyExitPath = true;
1088                }
1089                if ( generateNonGreedyExitPath ) {
1090                        if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) {
1091                                System.out.println("nongreedy (...)* loop; exit depth is "+
1092                                                                   blk.exitLookaheadDepth);
1093                        }
1094                        String predictExit =
1095                                getLookaheadTestExpression(blk.exitCache,
1096                                                                                   nonGreedyExitDepth);
1097                        println("// nongreedy exit test");
1098                        println("if ("+predictExit+") goto "+label+";");
1099                }
1100
1101                CppBlockFinishingInfo howToFinish = genCommonBlock(blk, false);
1102                genBlockFinish(howToFinish, "goto " + label + ";");
1103
1104                tabs--;
1105                println("}");
1106                println(label+":;");
1107                println("} // ( ... )*");
1108
1109                // Restore previous AST generation
1110                currentASTResult = saveCurrentASTResult;
1111        }
1112        /** Generate an alternative.
1113          * @param alt  The alternative to generate
1114          * @param blk The block to which the alternative belongs
1115          */
1116        protected void genAlt(Alternative alt, AlternativeBlock blk)
1117        {
1118                // Save the AST generation state, and set it to that of the alt
1119                boolean savegenAST = genAST;
1120                genAST = genAST && alt.getAutoGen();
1121
1122                boolean oldsaveTest = saveText;
1123                saveText = saveText && alt.getAutoGen();
1124
1125                // Reset the variable name map for the alternative
1126                Hashtable saveMap = treeVariableMap;
1127                treeVariableMap = new Hashtable();
1128
1129                // Generate try block around the alt for  error handling
1130                if (alt.exceptionSpec != null) {
1131                        println("try {      // for error handling");
1132                        tabs++;
1133                }
1134
1135                AlternativeElement elem = alt.head;
1136                while ( !(elem instanceof BlockEndElement) ) {
1137                        elem.generate(); // alt can begin with anything. Ask target to gen.
1138                        elem = elem.next;
1139                }
1140
1141                if ( genAST)
1142                {
1143                        if (blk instanceof RuleBlock)
1144                        {
1145                                // Set the AST return value for the rule
1146                                RuleBlock rblk = (RuleBlock)blk;
1147                                if( usingCustomAST )
1148                                        println(rblk.getRuleName() + "_AST = "+labeledElementASTType+"(currentAST.root);");
1149                                else
1150                                        println(rblk.getRuleName() + "_AST = currentAST.root;");
1151                        }
1152                        else if (blk.getLabel() != null) {
1153                                // ### future: also set AST value for labeled subrules.
1154                                // println(blk.getLabel() + "_AST = "+labeledElementASTType+"(currentAST.root);");
1155                                antlrTool.warning("Labeled subrules are not implemented", grammar.getFilename(), blk.getLine(), blk.getColumn());
1156                        }
1157                }
1158
1159                if (alt.exceptionSpec != null)
1160                {
1161                        // close try block
1162                        tabs--;
1163                        println("}");
1164                        genErrorHandler(alt.exceptionSpec);
1165                }
1166
1167                genAST = savegenAST;
1168                saveText = oldsaveTest;
1169
1170                treeVariableMap = saveMap;
1171        }
1172        /** Generate all the bitsets to be used in the parser or lexer
1173         * Generate the raw bitset data like "long _tokenSet1_data[] = {...};"
1174         * and the BitSet object declarations like
1175         * "BitSet _tokenSet1 = new BitSet(_tokenSet1_data);"
1176         * Note that most languages do not support object initialization inside a
1177         * class definition, so other code-generators may have to separate the
1178         * bitset declarations from the initializations (e.g., put the
1179         * initializations in the generated constructor instead).
1180         * @param bitsetList The list of bitsets to generate.
1181         * @param maxVocabulary Ensure that each generated bitset can contain at
1182         *        least this value.
1183         * @param prefix string glued in from of bitset names used for namespace
1184         *        qualifications.
1185         */
1186        protected void genBitsets(
1187                Vector bitsetList,
1188                int maxVocabulary,
1189                String prefix
1190        )
1191        {
1192                TokenManager tm = grammar.tokenManager;
1193
1194                println("");
1195
1196                for (int i = 0; i < bitsetList.size(); i++)
1197                {
1198                        BitSet p = (BitSet)bitsetList.elementAt(i);
1199                        // Ensure that generated BitSet is large enough for vocabulary
1200                        p.growToInclude(maxVocabulary);
1201
1202                        // initialization data
1203                        println(
1204                                "const unsigned long " + prefix + getBitsetName(i) + "_data_" + "[] = { " +
1205                                p.toStringOfHalfWords() +
1206                                " };"
1207                        );
1208
1209                        // Dump the contents of the bitset in readable format...
1210                        String t = "// ";
1211
1212                        for( int j = 0; j < tm.getVocabulary().size(); j++ )
1213                        {
1214                                if ( p.member( j ) )
1215                                {
1216                                        if ( (grammar instanceof LexerGrammar) )
1217                                        {
1218                                                // only dump out for pure printable ascii.
1219                                                if( ( 0x20 <= j ) && ( j < 0x7F ) && (j != '\\') )
1220                                                        t += charFormatter.escapeChar(j,true)+" ";
1221                                                else
1222                                                        t += "0x"+Integer.toString(j,16)+" ";
1223                                        }
1224                                        else
1225                                                t += tm.getTokenStringAt(j)+" ";
1226
1227                                        if( t.length() > 70 )
1228                                        {
1229                                                println(t);
1230                                                t = "// ";
1231                                        }
1232                                }
1233                        }
1234                        if ( t != "// " )
1235                                println(t);
1236
1237                        // BitSet object
1238                        println(
1239                                "const "+namespaceAntlr+"BitSet " + prefix + getBitsetName(i) + "(" +
1240                                getBitsetName(i) + "_data_," + p.size()/32 +
1241                                ");"
1242                        );
1243                }
1244        }
1245        protected void genBitsetsHeader(
1246                Vector bitsetList,
1247                int maxVocabulary
1248        ) {
1249                println("");
1250                for (int i = 0; i < bitsetList.size(); i++)
1251                {
1252                        BitSet p = (BitSet)bitsetList.elementAt(i);
1253                        // Ensure that generated BitSet is large enough for vocabulary
1254                        p.growToInclude(maxVocabulary);
1255                        // initialization data
1256                        println("static const unsigned long " + getBitsetName(i) + "_data_" + "[];");
1257                        // BitSet object
1258                        println("static const "+namespaceAntlr+"BitSet " + getBitsetName(i) + ";");
1259                }
1260        }
1261        /** Generate the finish of a block, using a combination of the info
1262         * returned from genCommonBlock() and the action to perform when
1263         * no alts were taken
1264         * @param howToFinish The return of genCommonBlock()
1265         * @param noViableAction What to generate when no alt is taken
1266         */
1267        private void genBlockFinish(CppBlockFinishingInfo howToFinish, String noViableAction)
1268        {
1269                if (howToFinish.needAnErrorClause &&
1270                         (howToFinish.generatedAnIf || howToFinish.generatedSwitch)) {
1271                        if ( howToFinish.generatedAnIf ) {
1272                                println("else {");
1273                        }
1274                        else {
1275                                println("{");
1276                        }
1277                        tabs++;
1278                        println(noViableAction);
1279                        tabs--;
1280                        println("}");
1281                }
1282
1283                if ( howToFinish.postscript!=null ) {
1284                        println(howToFinish.postscript);
1285                }
1286        }
1287        /** Generate the initaction for a block, which may be a RuleBlock or a
1288         * plain AlternativeBLock.
1289         * @blk The block for which the preamble is to be generated.
1290         */
1291        protected void genBlockInitAction( AlternativeBlock blk )
1292        {
1293                // dump out init action
1294                if ( blk.initAction!=null ) {
1295                        genLineNo(blk);
1296                        printAction(processActionForSpecialSymbols(blk.initAction, blk.line,
1297                                                                                                                                         currentRule, null) );
1298                        genLineNo2();
1299                }
1300        }
1301        /** Generate the header for a block, which may be a RuleBlock or a
1302         * plain AlternativeBlock. This generates any variable declarations
1303         * and syntactic-predicate-testing variables.
1304         * @blk The block for which the preamble is to be generated.
1305         */
1306        protected void genBlockPreamble(AlternativeBlock blk) {
1307                // define labels for rule blocks.
1308                if ( blk instanceof RuleBlock ) {
1309                        RuleBlock rblk = (RuleBlock)blk;
1310                        if ( rblk.labeledElements!=null ) {
1311                                for (int i=0; i<rblk.labeledElements.size(); i++) {
1312
1313                                        AlternativeElement a = (AlternativeElement)rblk.labeledElements.elementAt(i);
1314                                        //System.out.println("looking at labeled element: "+a);
1315                                        // Variables for labeled rule refs and subrules are different than
1316                                        // variables for grammar atoms.  This test is a little tricky because
1317                                        // we want to get all rule refs and ebnf, but not rule blocks or
1318                                        // syntactic predicates
1319                                        if (
1320                                                a instanceof RuleRefElement ||
1321                                                a instanceof AlternativeBlock &&
1322                                                !(a instanceof RuleBlock) &&
1323                                                !(a instanceof SynPredBlock) )
1324                                        {
1325                                                if ( !(a instanceof RuleRefElement) &&
1326                                                          ((AlternativeBlock)a).not &&
1327                                                          analyzer.subruleCanBeInverted(((AlternativeBlock)a), grammar instanceof LexerGrammar)
1328                                                ) {
1329                                                        // Special case for inverted subrules that will be
1330                                                        // inlined. Treat these like token or char literal
1331                                                        // references
1332                                                        println(labeledElementType + " " + a.getLabel() + " = " + labeledElementInit + ";");
1333                                                        if (grammar.buildAST) {
1334                                                                genASTDeclaration( a );
1335                                                        }
1336                                                }
1337                                                else
1338                                                {
1339                                                        if (grammar.buildAST)
1340                                                        {
1341                                                                // Always gen AST variables for labeled elements,
1342                                                                // even if the element itself is marked with !
1343                                                                genASTDeclaration( a );
1344                                                        }
1345                                                        if ( grammar instanceof LexerGrammar )
1346                                                                println(namespaceAntlr+"RefToken "+a.getLabel()+";");
1347
1348                                                        if (grammar instanceof TreeWalkerGrammar) {
1349                                                                // always generate rule-ref variables for tree walker
1350                                                                println(labeledElementType + " " + a.getLabel() + " = " + labeledElementInit + ";");
1351                                                        }
1352                                                }
1353                                        }
1354                                        else
1355                                        {
1356                                                // It is a token or literal reference.  Generate the
1357                                                // correct variable type for this grammar
1358                                                println(labeledElementType + " " + a.getLabel() + " = " + labeledElementInit + ";");
1359                                                // In addition, generate *_AST variables if building ASTs
1360                                                if (grammar.buildAST)
1361                                                {
1362                                                        if (a instanceof GrammarAtom &&
1363                                                                 ((GrammarAtom)a).getASTNodeType() != null )
1364                                                        {
1365                                                                GrammarAtom ga = (GrammarAtom)a;
1366                                                                genASTDeclaration( a, "Ref"+ga.getASTNodeType() );
1367                                                        }
1368                                                        else
1369                                                        {
1370                                                                genASTDeclaration( a );
1371                                                        }
1372                                                }
1373                                        }
1374                                }
1375                        }
1376                }
1377        }
1378        public void genBody(LexerGrammar g) throws IOException
1379        {
1380                outputFile = grammar.getClassName() + ".cpp";
1381                outputLine = 1;
1382                currentOutput = antlrTool.openOutputFile(outputFile);
1383                //SAS: changed for proper text file io
1384
1385                genAST = false; // no way to gen trees.
1386                saveText = true;        // save consumed characters.
1387
1388                tabs=0;
1389
1390                // Generate header common to all C++ output files
1391                genHeader(outputFile);
1392
1393                printHeaderAction(preIncludeCpp);
1394                // Generate header specific to lexer C++ file
1395                println("#include \"" + grammar.getClassName() + ".hpp\"");
1396                println("#include <antlr/CharBuffer.hpp>");
1397                println("#include <antlr/TokenStreamException.hpp>");
1398                println("#include <antlr/TokenStreamIOException.hpp>");
1399                println("#include <antlr/TokenStreamRecognitionException.hpp>");
1400                println("#include <antlr/CharStreamException.hpp>");
1401                println("#include <antlr/CharStreamIOException.hpp>");
1402                println("#include <antlr/NoViableAltForCharException.hpp>");
1403                if (grammar.debuggingOutput)
1404                        println("#include <antlr/DebuggingInputBuffer.hpp>");
1405                println("");
1406                printHeaderAction(postIncludeCpp);
1407
1408                if (nameSpace != null)
1409                        nameSpace.emitDeclarations(currentOutput);
1410
1411                // Generate user-defined lexer file preamble
1412                printAction(grammar.preambleAction);
1413
1414                // Generate lexer class definition
1415                String sup=null;
1416                if ( grammar.superClass!=null ) {
1417                        sup = grammar.superClass;
1418                }
1419                else {
1420                        sup = grammar.getSuperClass();
1421                        if (sup.lastIndexOf('.') != -1)
1422                                sup = sup.substring(sup.lastIndexOf('.')+1);
1423                        sup = namespaceAntlr + sup;
1424                }
1425
1426                if( noConstructors )
1427                {
1428                        println("#if 0");
1429                        println("// constructor creation turned of with 'noConstructor' option");
1430                }
1431                //
1432                // Generate the constructor from InputStream
1433                //
1434                println(grammar.getClassName() + "::" + grammar.getClassName() + "(" + namespaceStd + "istream& in)");
1435                tabs++;
1436                // if debugging, wrap the input buffer in a debugger
1437                if (grammar.debuggingOutput)
1438                        println(": " + sup + "(new "+namespaceAntlr+"DebuggingInputBuffer(new "+namespaceAntlr+"CharBuffer(in)),"+g.caseSensitive+")");
1439                else
1440                        println(": " + sup + "(new "+namespaceAntlr+"CharBuffer(in),"+g.caseSensitive+")");
1441                tabs--;
1442                println("{");
1443                tabs++;
1444
1445                // if debugging, set up array variables and call user-overridable
1446                //   debugging setup method
1447                if ( grammar.debuggingOutput ) {
1448                        println("setRuleNames(_ruleNames);");
1449                        println("setSemPredNames(_semPredNames);");
1450                        println("setupDebugging();");
1451                }
1452
1453//              println("setCaseSensitive("+g.caseSensitive+");");
1454                println("initLiterals();");
1455                tabs--;
1456                println("}");
1457                println("");
1458
1459                // Generate the constructor from InputBuffer
1460                println(grammar.getClassName() + "::" + grammar.getClassName() + "("+namespaceAntlr+"InputBuffer& ib)");
1461                tabs++;
1462                // if debugging, wrap the input buffer in a debugger
1463                if (grammar.debuggingOutput)
1464                        println(": " + sup + "(new "+namespaceAntlr+"DebuggingInputBuffer(ib),"+g.caseSensitive+")");
1465                else
1466                        println(": " + sup + "(ib,"+g.caseSensitive+")");
1467                tabs--;
1468                println("{");
1469                tabs++;
1470
1471                // if debugging, set up array variables and call user-overridable
1472                //   debugging setup method
1473                if ( grammar.debuggingOutput ) {
1474                        println("setRuleNames(_ruleNames);");
1475                        println("setSemPredNames(_semPredNames);");
1476                        println("setupDebugging();");
1477                }
1478
1479//              println("setCaseSensitive("+g.caseSensitive+");");
1480                println("initLiterals();");
1481                tabs--;
1482                println("}");
1483                println("");
1484
1485                // Generate the constructor from LexerSharedInputState
1486                println(grammar.getClassName() + "::" + grammar.getClassName() + "(const "+namespaceAntlr+"LexerSharedInputState& state)");
1487                tabs++;
1488                println(": " + sup + "(state,"+g.caseSensitive+")");
1489                tabs--;
1490                println("{");
1491                tabs++;
1492
1493                // if debugging, set up array variables and call user-overridable
1494                //   debugging setup method
1495                if ( grammar.debuggingOutput ) {
1496                        println("setRuleNames(_ruleNames);");
1497                        println("setSemPredNames(_semPredNames);");
1498                        println("setupDebugging();");
1499                }
1500
1501//              println("setCaseSensitive("+g.caseSensitive+");");
1502                println("initLiterals();");
1503                tabs--;
1504                println("}");
1505                println("");
1506
1507                if( noConstructors )
1508                {
1509                        println("// constructor creation turned of with 'noConstructor' option");
1510                        println("#endif");
1511                }
1512
1513                println("void " + grammar.getClassName() + "::initLiterals()");
1514                println("{");
1515                tabs++;
1516                // Generate the initialization of the map
1517                // containing the string literals used in the lexer
1518                // The literals variable itself is in CharScanner
1519                Enumeration keys = grammar.tokenManager.getTokenSymbolKeys();
1520                while ( keys.hasMoreElements() ) {
1521                        String key = (String)keys.nextElement();
1522                        if ( key.charAt(0) != '"' ) {
1523                                continue;
1524                        }
1525                        TokenSymbol sym = grammar.tokenManager.getTokenSymbol(key);
1526                        if ( sym instanceof StringLiteralSymbol ) {
1527                                StringLiteralSymbol s = (StringLiteralSymbol)sym;
1528                                println("literals["+s.getId()+"] = "+s.getTokenType()+";");
1529                        }
1530                }
1531
1532                // Generate the setting of various generated options.
1533                tabs--;
1534                println("}");
1535
1536                Enumeration ids;
1537                // generate the rule name array for debugging
1538                if (grammar.debuggingOutput) {
1539                        println("const char* "+grammar.getClassName()+"::_ruleNames[] = {");
1540                        tabs++;
1541
1542                        ids = grammar.rules.elements();
1543                        int ruleNum=0;
1544                        while ( ids.hasMoreElements() ) {
1545                                GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
1546                                if ( sym instanceof RuleSymbol)
1547                                        println("\""+((RuleSymbol)sym).getId()+"\",");
1548                        }
1549                        println("0");
1550                        tabs--;
1551                        println("};");
1552                }
1553
1554                // Generate nextToken() rule.
1555                // nextToken() is a synthetic lexer rule that is the implicit OR of all
1556                // user-defined lexer rules.
1557                genNextToken();
1558
1559                // Generate code for each rule in the lexer
1560                ids = grammar.rules.elements();
1561                int ruleNum=0;
1562                while ( ids.hasMoreElements() ) {
1563                        RuleSymbol sym = (RuleSymbol) ids.nextElement();
1564                        // Don't generate the synthetic rules
1565                        if (!sym.getId().equals("mnextToken")) {
1566                                genRule(sym, false, ruleNum++, grammar.getClassName() + "::");
1567                        }
1568                        exitIfError();
1569                }
1570
1571                // Generate the semantic predicate map for debugging
1572                if (grammar.debuggingOutput)
1573                        genSemPredMap(grammar.getClassName() + "::");
1574
1575                // Generate the bitsets used throughout the lexer
1576                genBitsets(bitsetsUsed, ((LexerGrammar)grammar).charVocabulary.size(), grammar.getClassName() + "::" );
1577
1578                println("");
1579                if (nameSpace != null)
1580                        nameSpace.emitClosures(currentOutput);
1581
1582                // Close the lexer output stream
1583                currentOutput.close();
1584                currentOutput = null;
1585        }
1586        public void genInitFactory( Grammar g )
1587        {
1588                // Generate the method to initialize an ASTFactory when we're
1589                // building AST's
1590                String param_name = "factory ";
1591                if( ! g.buildAST )
1592                        param_name = "";
1593
1594                println("void "+ g.getClassName() + "::initializeASTFactory( "+namespaceAntlr+"ASTFactory& "+param_name+")");
1595                println("{");
1596                tabs++;
1597
1598                if( g.buildAST )
1599                {
1600                        // sort out custom AST types... synchronize token manager with token
1601                        // specs on rules (and other stuff we were able to see from
1602                        // action.g) (imperfect of course)
1603                        TokenManager tm = grammar.tokenManager;
1604                        Enumeration tokens = tm.getTokenSymbolKeys();
1605                        while( tokens.hasMoreElements() )
1606                        {
1607                                String tok = (String)tokens.nextElement();
1608                                TokenSymbol ts = tm.getTokenSymbol(tok);
1609                                // if we have a custom type and there's not a more local override
1610                                // of the tokentype then mark this as the type for the tokentype
1611                                if( ts.getASTNodeType() != null )
1612                                {
1613                                        // ensure capacity with this pseudo vector...
1614                                        astTypes.ensureCapacity(ts.getTokenType());
1615                                        String type = (String)astTypes.elementAt(ts.getTokenType());
1616                                        if( type == null )
1617                                                astTypes.setElementAt(ts.getASTNodeType(),ts.getTokenType());
1618                                        else
1619                                        {
1620                                                // give a warning over action taken if the types are unequal
1621                                                if( ! ts.getASTNodeType().equals(type) )
1622                                                {
1623                                                        antlrTool.warning("Token "+tok+" taking most specific AST type",grammar.getFilename(),1,1);
1624                                                        antlrTool.warning("  using "+type+" ignoring "+ts.getASTNodeType(),grammar.getFilename(),1,1);
1625                                                }
1626                                        }
1627                                }
1628                        }
1629                        // now actually write out all the registered types. (except the default
1630                        // type.
1631                        for( int i = 0; i < astTypes.size(); i++ )
1632                        {
1633                                String type = (String)astTypes.elementAt(i);
1634                                if( type != null )
1635                                {
1636                                        println("factory.registerFactory("+i
1637                                                  +", \""+type+"\", "+type+"::factory);");
1638                                }
1639                        }
1640                        println("factory.setMaxNodeType("+grammar.tokenManager.maxTokenType()+");");
1641                }
1642                tabs--;
1643                println("}");
1644        }
1645        // FIXME: and so why are we passing here a g param while inside
1646        // we merrily use the global grammar.
1647        public void genBody(ParserGrammar g) throws IOException
1648        {
1649                // Open the output stream for the parser and set the currentOutput
1650                outputFile = grammar.getClassName() + ".cpp";
1651                outputLine = 1;
1652                currentOutput = antlrTool.openOutputFile(outputFile);
1653
1654                genAST = grammar.buildAST;
1655
1656                tabs = 0;
1657
1658                // Generate the header common to all output files.
1659                genHeader(outputFile);
1660
1661                printHeaderAction(preIncludeCpp);
1662
1663                // Generate header for the parser
1664                println("#include \"" + grammar.getClassName() + ".hpp\"");
1665                println("#include <antlr/NoViableAltException.hpp>");
1666                println("#include <antlr/SemanticException.hpp>");
1667                println("#include <antlr/ASTFactory.hpp>");
1668
1669                printHeaderAction(postIncludeCpp);
1670
1671                if (nameSpace != null)
1672                        nameSpace.emitDeclarations(currentOutput);
1673
1674                // Output the user-defined parser preamble
1675                printAction(grammar.preambleAction);
1676
1677                String sup=null;
1678                if ( grammar.superClass!=null )
1679                        sup = grammar.superClass;
1680                else {
1681                        sup = grammar.getSuperClass();
1682                        if (sup.lastIndexOf('.') != -1)
1683                                sup = sup.substring(sup.lastIndexOf('.')+1);
1684                        sup = namespaceAntlr + sup;
1685                }
1686
1687                // set up an array of all the rule names so the debugger can
1688                // keep track of them only by number -- less to store in tree...
1689                if (grammar.debuggingOutput) {
1690                        println("const char* "+grammar.getClassName()+"::_ruleNames[] = {");
1691                        tabs++;
1692
1693                        Enumeration ids = grammar.rules.elements();
1694                        int ruleNum=0;
1695                        while ( ids.hasMoreElements() ) {
1696                                GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
1697                                if ( sym instanceof RuleSymbol)
1698                                        println("\""+((RuleSymbol)sym).getId()+"\",");
1699                        }
1700                        println("0");
1701                        tabs--;
1702                        println("};");
1703                }
1704
1705                // Generate _initialize function
1706                // disabled since it isn't used anymore..
1707
1708//              println("void " + grammar.getClassName() + "::_initialize(void)");
1709//              println("{");
1710//              tabs++;
1711
1712                // if debugging, set up arrays and call the user-overridable
1713                //   debugging setup method
1714//              if ( grammar.debuggingOutput ) {
1715//                      println("setRuleNames(_ruleNames);");
1716//                      println("setSemPredNames(_semPredNames);");
1717//                      println("setupDebugging();");
1718//              }
1719//              tabs--;
1720//              println("}");
1721                if( noConstructors )
1722                {
1723                        println("#if 0");
1724                        println("// constructor creation turned of with 'noConstructor' option");
1725                }
1726
1727                // Generate parser class constructor from TokenBuffer
1728                print(grammar.getClassName() + "::" + grammar.getClassName());
1729                println("("+namespaceAntlr+"TokenBuffer& tokenBuf, int k)");
1730                println(": " + sup + "(tokenBuf,k)");
1731                println("{");
1732//              tabs++;
1733//              println("_initialize();");
1734//              tabs--;
1735                println("}");
1736                println("");
1737
1738                print(grammar.getClassName() + "::" + grammar.getClassName());
1739                println("("+namespaceAntlr+"TokenBuffer& tokenBuf)");
1740                println(": " + sup + "(tokenBuf," + grammar.maxk + ")");
1741                println("{");
1742//              tabs++;
1743//              println("_initialize();");
1744//              tabs--;
1745                println("}");
1746                println("");
1747
1748                // Generate parser class constructor from TokenStream
1749                print(grammar.getClassName() + "::" + grammar.getClassName());
1750                println("("+namespaceAntlr+"TokenStream& lexer, int k)");
1751                println(": " + sup + "(lexer,k)");
1752                println("{");
1753//              tabs++;
1754//              println("_initialize();");
1755//              tabs--;
1756                println("}");
1757                println("");
1758
1759                print(grammar.getClassName() + "::" + grammar.getClassName());
1760                println("("+namespaceAntlr+"TokenStream& lexer)");
1761                println(": " + sup + "(lexer," + grammar.maxk + ")");
1762                println("{");
1763//              tabs++;
1764//              println("_initialize();");
1765//              tabs--;
1766                println("}");
1767                println("");
1768
1769                print(grammar.getClassName() + "::" + grammar.getClassName());
1770                println("(const "+namespaceAntlr+"ParserSharedInputState& state)");
1771                println(": " + sup + "(state," + grammar.maxk + ")");
1772                println("{");
1773//              tabs++;
1774//              println("_initialize();");
1775//              tabs--;
1776                println("}");
1777                println("");
1778
1779                if( noConstructors )
1780                {
1781                        println("// constructor creation turned of with 'noConstructor' option");
1782                        println("#endif");
1783                }
1784
1785                astTypes = new Vector();
1786
1787                // Generate code for each rule in the grammar
1788                Enumeration ids = grammar.rules.elements();
1789                int ruleNum=0;
1790                while ( ids.hasMoreElements() ) {
1791                        GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
1792                        if ( sym instanceof RuleSymbol) {
1793                                RuleSymbol rs = (RuleSymbol)sym;
1794                                genRule(rs, rs.references.size()==0, ruleNum++, grammar.getClassName() + "::");
1795                        }
1796                        exitIfError();
1797                }
1798
1799                genInitFactory( g );
1800
1801                // Generate the token names
1802                genTokenStrings(grammar.getClassName() + "::");
1803
1804                // Generate the bitsets used throughout the grammar
1805                genBitsets(bitsetsUsed, grammar.tokenManager.maxTokenType(), grammar.getClassName() + "::" );
1806
1807                // Generate the semantic predicate map for debugging
1808                if (grammar.debuggingOutput)
1809                        genSemPredMap(grammar.getClassName() + "::");
1810
1811                // Close class definition
1812                println("");
1813                println("");
1814                if (nameSpace != null)
1815                        nameSpace.emitClosures(currentOutput);
1816
1817                // Close the parser output stream
1818                currentOutput.close();
1819                currentOutput = null;
1820        }
1821        public void genBody(TreeWalkerGrammar g) throws IOException
1822        {
1823                // Open the output stream for the parser and set the currentOutput
1824                outputFile = grammar.getClassName() + ".cpp";
1825                outputLine = 1;
1826                currentOutput = antlrTool.openOutputFile(outputFile);
1827                //SAS: changed for proper text file io
1828
1829                genAST = grammar.buildAST;
1830                tabs = 0;
1831
1832                // Generate the header common to all output files.
1833                genHeader(outputFile);
1834
1835                printHeaderAction(preIncludeCpp);
1836
1837                // Generate header for the parser
1838                println("#include \"" + grammar.getClassName() + ".hpp\"");
1839                println("#include <antlr/Token.hpp>");
1840                println("#include <antlr/AST.hpp>");
1841                println("#include <antlr/NoViableAltException.hpp>");
1842                println("#include <antlr/MismatchedTokenException.hpp>");
1843                println("#include <antlr/SemanticException.hpp>");
1844                println("#include <antlr/BitSet.hpp>");
1845
1846                printHeaderAction(postIncludeCpp);
1847
1848                if (nameSpace != null)
1849                        nameSpace.emitDeclarations(currentOutput);
1850
1851                // Output the user-defined parser premamble
1852                printAction(grammar.preambleAction);
1853
1854                // Generate parser class definition
1855                String sup = null;
1856                if ( grammar.superClass!=null ) {
1857                        sup = grammar.superClass;
1858                }
1859                else {
1860                        sup = grammar.getSuperClass();
1861                        if (sup.lastIndexOf('.') != -1)
1862                                sup = sup.substring(sup.lastIndexOf('.')+1);
1863                        sup = namespaceAntlr + sup;
1864                }
1865                if( noConstructors )
1866                {
1867                        println("#if 0");
1868                        println("// constructor creation turned of with 'noConstructor' option");
1869                }
1870
1871                // Generate default parser class constructor
1872                println(grammar.getClassName() + "::" + grammar.getClassName() + "()");
1873                println("\t: "+namespaceAntlr+"TreeParser() {");
1874                tabs++;
1875//              println("setTokenNames(_tokenNames);");
1876                tabs--;
1877                println("}");
1878
1879                if( noConstructors )
1880                {
1881                        println("// constructor creation turned of with 'noConstructor' option");
1882                        println("#endif");
1883                }
1884                println("");
1885
1886                astTypes = new Vector();
1887
1888                // Generate code for each rule in the grammar
1889                Enumeration ids = grammar.rules.elements();
1890                int ruleNum=0;
1891                String ruleNameInits = "";
1892                while ( ids.hasMoreElements() ) {
1893                        GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
1894                        if ( sym instanceof RuleSymbol) {
1895                                RuleSymbol rs = (RuleSymbol)sym;
1896                                genRule(rs, rs.references.size()==0, ruleNum++, grammar.getClassName() + "::");
1897                        }
1898                        exitIfError();
1899                }
1900
1901                // Generate the ASTFactory initialization function
1902                genInitFactory( grammar );
1903                // Generate the token names
1904                genTokenStrings(grammar.getClassName() + "::");
1905
1906                // Generate the bitsets used throughout the grammar
1907                genBitsets(bitsetsUsed, grammar.tokenManager.maxTokenType(), grammar.getClassName() + "::" );
1908
1909                // Close class definition
1910                println("");
1911                println("");
1912
1913                if (nameSpace != null)
1914                        nameSpace.emitClosures(currentOutput);
1915
1916                // Close the parser output stream
1917                currentOutput.close();
1918                currentOutput = null;
1919        }
1920        /** Generate a series of case statements that implement a BitSet test.
1921         * @param p The Bitset for which cases are to be generated
1922         */
1923        protected void genCases(BitSet p) {
1924                if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genCases("+p+")");
1925                int[] elems;
1926
1927                elems = p.toArray();
1928                // Wrap cases four-per-line for lexer, one-per-line for parser
1929                int wrap = 1; //(grammar instanceof LexerGrammar) ? 4 : 1;
1930                int j=1;
1931                boolean startOfLine = true;
1932                for (int i = 0; i < elems.length; i++) {
1933                        if (j==1) {
1934                                print("");
1935                        } else {
1936                                _print("  ");
1937                        }
1938                        _print("case " + getValueString(elems[i]) + ":");
1939
1940                        if (j==wrap) {
1941                                _println("");
1942                                startOfLine = true;
1943                                j=1;
1944                        }
1945                        else {
1946                                j++;
1947                                startOfLine = false;
1948                        }
1949                }
1950                if (!startOfLine) {
1951                        _println("");
1952                }
1953        }
1954        /** Generate common code for a block of alternatives; return a postscript
1955         * that needs to be generated at the end of the block.  Other routines
1956         * may append else-clauses and such for error checking before the postfix
1957         * is generated.
1958         * If the grammar is a lexer, then generate alternatives in an order where
1959         * alternatives requiring deeper lookahead are generated first, and
1960         * EOF in the lookahead set reduces the depth of the lookahead.
1961         * @param blk The block to generate
1962         * @param noTestForSingle If true, then it does not generate a test for a single alternative.
1963         */
1964        public CppBlockFinishingInfo genCommonBlock(
1965                AlternativeBlock blk,
1966                boolean noTestForSingle )
1967        {
1968                int nIF=0;
1969                boolean createdLL1Switch = false;
1970                int closingBracesOfIFSequence = 0;
1971                CppBlockFinishingInfo finishingInfo = new CppBlockFinishingInfo();
1972                if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genCommonBlk("+blk+")");
1973
1974                // Save the AST generation state, and set it to that of the block
1975                boolean savegenAST = genAST;
1976                genAST = genAST && blk.getAutoGen();
1977
1978                boolean oldsaveTest = saveText;
1979                saveText = saveText && blk.getAutoGen();
1980
1981                // Is this block inverted?  If so, generate special-case code
1982                if ( blk.not &&
1983                        analyzer.subruleCanBeInverted(blk, grammar instanceof LexerGrammar) )
1984                {
1985                        Lookahead p = analyzer.look(1, blk);
1986                        // Variable assignment for labeled elements
1987                        if (blk.getLabel() != null && syntacticPredLevel == 0) {
1988                                println(blk.getLabel() + " = " + lt1Value + ";");
1989                        }
1990
1991                        // AST
1992                        genElementAST(blk);
1993
1994                        String astArgs="";
1995                        if (grammar instanceof TreeWalkerGrammar) {
1996                                if( usingCustomAST )
1997                                        astArgs=namespaceAntlr+"RefAST"+"(_t),";
1998                                else
1999                                        astArgs="_t,";
2000                        }
2001
2002                        // match the bitset for the alternative
2003                        println("match(" + astArgs + getBitsetName(markBitsetForGen(p.fset)) + ");");
2004
2005                        // tack on tree cursor motion if doing a tree walker
2006                        if (grammar instanceof TreeWalkerGrammar)
2007                        {
2008                                println("_t = _t->getNextSibling();");
2009                        }
2010                        return finishingInfo;
2011                }
2012
2013                // Special handling for single alt
2014                if (blk.getAlternatives().size() == 1)
2015                {
2016                        Alternative alt = blk.getAlternativeAt(0);
2017                        // Generate a warning if there is a synPred for single alt.
2018                        if (alt.synPred != null)
2019                        {
2020                                antlrTool.warning(
2021                                                                 "Syntactic predicate superfluous for single alternative",
2022                                                                 grammar.getFilename(),
2023                                                                 blk.getAlternativeAt(0).synPred.getLine(),
2024                                                                 blk.getAlternativeAt(0).synPred.getColumn()
2025                                );
2026                        }
2027                        if (noTestForSingle)
2028                        {
2029                                if (alt.semPred != null)
2030                                {
2031                                        // Generate validating predicate
2032                                        genSemPred(alt.semPred, blk.line);
2033                                }
2034                                genAlt(alt, blk);
2035                                return finishingInfo;
2036                        }
2037                }
2038
2039                // count number of simple LL(1) cases; only do switch for
2040                // many LL(1) cases (no preds, no end of token refs)
2041                // We don't care about exit paths for (...)*, (...)+
2042                // because we don't explicitly have a test for them
2043                // as an alt in the loop.
2044                //
2045                // Also, we now count how many unicode lookahead sets
2046                // there are--they must be moved to DEFAULT or ELSE
2047                // clause.
2048
2049                int nLL1 = 0;
2050                for (int i=0; i<blk.getAlternatives().size(); i++)
2051                {
2052                        Alternative a = blk.getAlternativeAt(i);
2053                        if ( suitableForCaseExpression(a) )
2054                                nLL1++;
2055                }
2056
2057                // do LL(1) cases
2058                if ( nLL1 >= makeSwitchThreshold )
2059                {
2060                        // Determine the name of the item to be compared
2061                        String testExpr = lookaheadString(1);
2062                        createdLL1Switch = true;
2063                        // when parsing trees, convert null to valid tree node with NULL lookahead
2064                        if ( grammar instanceof TreeWalkerGrammar )
2065                        {
2066                                println("if (_t == "+labeledElementASTInit+" )");
2067                                tabs++;
2068                                println("_t = ASTNULL;");
2069                                tabs--;
2070                        }
2071                        println("switch ( "+testExpr+") {");
2072                        for (int i=0; i<blk.alternatives.size(); i++)
2073                        {
2074                                Alternative alt = blk.getAlternativeAt(i);
2075                                // ignore any non-LL(1) alts, predicated alts or end-of-token alts
2076                                // or end-of-token alts for case expressions
2077                                if ( !suitableForCaseExpression(alt) )
2078                                {
2079                                        continue;
2080                                }
2081                                Lookahead p = alt.cache[1];
2082                                if (p.fset.degree() == 0 && !p.containsEpsilon())
2083                                {
2084                                        antlrTool.warning("Alternate omitted due to empty prediction set",
2085                                                grammar.getFilename(),
2086                                                alt.head.getLine(), alt.head.getColumn());
2087                                }
2088                                else
2089                                {
2090                                        genCases(p.fset);
2091                                        println("{");
2092                                        tabs++;
2093                                        genAlt(alt, blk);
2094                                        println("break;");
2095                                        tabs--;
2096                                        println("}");
2097                                }
2098                        }
2099                        println("default:");
2100                        tabs++;
2101                }
2102
2103                // do non-LL(1) and nondeterministic cases
2104                // This is tricky in the lexer, because of cases like:
2105                //     STAR : '*' ;
2106                //     ASSIGN_STAR : "*=";
2107                // Since nextToken is generated without a loop, then the STAR will
2108                // have end-of-token as it's lookahead set for LA(2).  So, we must generate the
2109                // alternatives containing trailing end-of-token in their lookahead sets *after*
2110                // the alternatives without end-of-token.  This implements the usual
2111                // lexer convention that longer matches come before shorter ones, e.g.
2112                // "*=" matches ASSIGN_STAR not STAR
2113                //
2114                // For non-lexer grammars, this does not sort the alternates by depth
2115                // Note that alts whose lookahead is purely end-of-token at k=1 end up
2116                // as default or else clauses.
2117                int startDepth = (grammar instanceof LexerGrammar) ? grammar.maxk : 0;
2118                for (int altDepth = startDepth; altDepth >= 0; altDepth--) {
2119                        if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("checking depth "+altDepth);
2120                        for (int i=0; i<blk.alternatives.size(); i++) {
2121                                Alternative alt = blk.getAlternativeAt(i);
2122                                if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genAlt: "+i);
2123                                // if we made a switch above, ignore what we already took care
2124                                // of.  Specifically, LL(1) alts with no preds
2125                                // that do not have end-of-token in their prediction set
2126                                if ( createdLL1Switch &&
2127                                         suitableForCaseExpression(alt) )
2128                                {
2129                                        if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR )
2130                                                System.out.println("ignoring alt because it was in the switch");
2131                                        continue;
2132                                }
2133                                String e;
2134
2135                                boolean unpredicted = false;
2136
2137                                if (grammar instanceof LexerGrammar) {
2138                                        // Calculate the "effective depth" of the alt, which is the max
2139                                        // depth at which cache[depth]!=end-of-token
2140                                        int effectiveDepth = alt.lookaheadDepth;
2141                                        if (effectiveDepth == GrammarAnalyzer.NONDETERMINISTIC)
2142                                        {
2143                                                // use maximum lookahead
2144                                                effectiveDepth = grammar.maxk;
2145                                        }
2146                                        while ( effectiveDepth >= 1 &&
2147                                                         alt.cache[effectiveDepth].containsEpsilon() )
2148                                        {
2149                                                effectiveDepth--;
2150                                        }
2151                                        // Ignore alts whose effective depth is other than the ones we
2152                                        // are generating for this iteration.
2153                                        if (effectiveDepth != altDepth)
2154                                        {
2155                                                if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR )
2156                                                        System.out.println("ignoring alt because effectiveDepth!=altDepth;"+effectiveDepth+"!="+altDepth);
2157                                                continue;
2158                                        }
2159                                        unpredicted = lookaheadIsEmpty(alt, effectiveDepth);
2160                                        e = getLookaheadTestExpression(alt, effectiveDepth);
2161                                }
2162                                else
2163                                {
2164                                        unpredicted = lookaheadIsEmpty(alt, grammar.maxk);
2165                                        e = getLookaheadTestExpression(alt, grammar.maxk);
2166                                }
2167
2168                                // Was it a big unicode range that forced unsuitability
2169                                // for a case expression?
2170                                if ( alt.cache[1].fset.degree() > caseSizeThreshold &&
2171                                          suitableForCaseExpression(alt))
2172                                {
2173                                        if ( nIF==0 )
2174                                        {
2175                                                // generate this only for the first if the elseif's
2176                                                // are covered by this one
2177                                                if ( grammar instanceof TreeWalkerGrammar ) {
2178                                                        println("if (_t == "+labeledElementASTInit+" )");
2179                                                        tabs++;
2180                                                        println("_t = ASTNULL;");
2181                                                        tabs--;
2182                                                }
2183                                                println("if " + e + " {");
2184                                        }
2185                                        else
2186                                                println("else if " + e + " {");
2187                                }
2188                                else if (unpredicted &&
2189                                                        alt.semPred==null &&
2190                                                        alt.synPred==null)
2191                                {
2192                                        // The alt has empty prediction set and no
2193                                        // predicate to help out.  if we have not
2194                                        // generated a previous if, just put {...} around
2195                                        // the end-of-token clause
2196                                        if ( nIF==0 ) {
2197                                                println("{");
2198                                        }
2199                                        else {
2200                                                println("else {");
2201                                        }
2202                                        finishingInfo.needAnErrorClause = false;
2203                                }
2204                                else
2205                                {
2206                                        // check for sem and syn preds
2207                                        // Add any semantic predicate expression to the lookahead test
2208                                        if ( alt.semPred != null ) {
2209                                                // if debugging, wrap the evaluation of the predicate in a method
2210                                                //
2211                                                // translate $ and # references
2212                                                ActionTransInfo tInfo = new ActionTransInfo();
2213                                                String actionStr = processActionForSpecialSymbols(alt.semPred,
2214                                                                                                                                                  blk.line,
2215                                                                                                                                                  currentRule,
2216                                                                                                                                                  tInfo);
2217                                                // ignore translation info...we don't need to do anything with it.
2218
2219                                                // call that will inform SemanticPredicateListeners of the
2220                                                // result
2221                                                if ( grammar.debuggingOutput &&
2222                                                          ((grammar instanceof ParserGrammar) || (grammar instanceof LexerGrammar))
2223                                                         )
2224                                                        e = "("+e+"&& fireSemanticPredicateEvaluated(antlr.debug.SemanticPredicateEvent.PREDICTING,"+ //FIXME
2225                                                                        addSemPred(charFormatter.escapeString(actionStr))+","+actionStr+"))";
2226                                                else
2227                                                        e = "("+e+"&&("+actionStr +"))";
2228                                        }
2229
2230                                        // Generate any syntactic predicates
2231                                        if ( nIF>0 ) {
2232                                                if ( alt.synPred != null ) {
2233                                                        println("else {");
2234                                                        tabs++;
2235                                                        genSynPred( alt.synPred, e );
2236                                                        closingBracesOfIFSequence++;
2237                                                }
2238                                                else {
2239                                                        println("else if " + e + " {");
2240                                                }
2241                                        }
2242                                        else {
2243                                                if ( alt.synPred != null ) {
2244                                                        genSynPred( alt.synPred, e );
2245                                                }
2246                                                else {
2247                                                        // when parsing trees, convert null to valid tree node
2248                                                        // with NULL lookahead.
2249                                                        if ( grammar instanceof TreeWalkerGrammar ) {
2250                                                                println("if (_t == "+labeledElementASTInit+" )");
2251                                                                tabs++;
2252                                                                println("_t = ASTNULL;");
2253                                                                tabs--;
2254                                                        }
2255                                                        println("if " + e + " {");
2256                                                }
2257                                        }
2258
2259                                }
2260
2261                                nIF++;
2262                                tabs++;
2263                                genAlt(alt, blk);
2264                                tabs--;
2265                                println("}");
2266                        }
2267                }
2268                String ps = "";
2269                for (int i=1; i<=closingBracesOfIFSequence; i++) {
2270                        tabs--; // does JavaCodeGenerator need this?
2271                        ps+="}";
2272                }
2273
2274                // Restore the AST generation state
2275                genAST = savegenAST;
2276
2277                // restore save text state
2278                saveText=oldsaveTest;
2279
2280                // Return the finishing info.
2281                if ( createdLL1Switch ) {
2282                        tabs--;
2283                        finishingInfo.postscript = ps+"}";
2284                        finishingInfo.generatedSwitch = true;
2285                        finishingInfo.generatedAnIf = nIF>0;
2286                        //return new CppBlockFinishingInfo(ps+"}",true,nIF>0); // close up switch statement
2287
2288                }
2289                else {
2290                        finishingInfo.postscript = ps;
2291                        finishingInfo.generatedSwitch = false;
2292                        finishingInfo.generatedAnIf = nIF>0;
2293                        //return new CppBlockFinishingInfo(ps, false,nIF>0);
2294                }
2295                return finishingInfo;
2296        }
2297
2298        private static boolean suitableForCaseExpression(Alternative a) {
2299                return a.lookaheadDepth == 1 &&
2300                        a.semPred == null &&
2301                        !a.cache[1].containsEpsilon() &&
2302                        a.cache[1].fset.degree()<=caseSizeThreshold;
2303        }
2304
2305        /** Generate code to link an element reference into the AST
2306         */
2307        private void genElementAST(AlternativeElement el) {
2308
2309                // handle case where you're not building trees, but are in tree walker.
2310                // Just need to get labels set up.
2311                if ( grammar instanceof TreeWalkerGrammar && !grammar.buildAST )
2312                {
2313                        String elementRef;
2314                        String astName;
2315
2316                        // Generate names and declarations of the AST variable(s)
2317                        if (el.getLabel() == null)
2318                        {
2319                                elementRef = lt1Value;
2320                                // Generate AST variables for unlabeled stuff
2321                                astName = "tmp" + astVarNumber + "_AST";
2322                                astVarNumber++;
2323                                // Map the generated AST variable in the alternate
2324                                mapTreeVariable(el, astName);
2325                                // Generate an "input" AST variable also
2326                                println(labeledElementASTType+" "+astName+"_in = "+elementRef+";");
2327                        }
2328                        return;
2329                }
2330
2331                if (grammar.buildAST && syntacticPredLevel == 0)
2332                {
2333                        boolean needASTDecl =
2334                                ( genAST && (el.getLabel() != null ||
2335                                  el.getAutoGenType() != GrammarElement.AUTO_GEN_BANG ));
2336
2337                        // RK: if we have a grammar element always generate the decl
2338                        // since some guy can access it from an action and we can't
2339                        // peek ahead (well not without making a mess).
2340                        // I'd prefer taking this out.
2341                        if( el.getAutoGenType() != GrammarElement.AUTO_GEN_BANG &&
2342                                 (el instanceof TokenRefElement) )
2343                                needASTDecl = true;
2344
2345                        boolean doNoGuessTest =
2346                                ( grammar.hasSyntacticPredicate && needASTDecl );
2347
2348                        String elementRef;
2349                        String astNameBase;
2350
2351                        // Generate names and declarations of the AST variable(s)
2352                        if (el.getLabel() != null)
2353                        {
2354                                // if the element is labeled use that name...
2355                                elementRef = el.getLabel();
2356                                astNameBase = el.getLabel();
2357                        }
2358                        else
2359                        {
2360                                // else generate a temporary name...
2361                                elementRef = lt1Value;
2362                                // Generate AST variables for unlabeled stuff
2363                                astNameBase = "tmp" + astVarNumber;
2364                                astVarNumber++;
2365                        }
2366
2367                        // Generate the declaration if required.
2368                        if ( needASTDecl )
2369                        {
2370                                if ( el instanceof GrammarAtom )
2371                                {
2372                                        GrammarAtom ga = (GrammarAtom)el;
2373                                        if ( ga.getASTNodeType()!=null )
2374                                        {
2375                                                genASTDeclaration( el, astNameBase, "Ref"+ga.getASTNodeType() );
2376//                                              println("Ref"+ga.getASTNodeType()+" " + astName + ";");
2377                                        }
2378                                        else
2379                                        {
2380                                                genASTDeclaration( el, astNameBase, labeledElementASTType );
2381//                                              println(labeledElementASTType+" " + astName + " = "+labeledElementASTInit+";");
2382                                        }
2383                                }
2384                                else
2385                                {
2386                                        genASTDeclaration( el, astNameBase, labeledElementASTType );
2387//                                      println(labeledElementASTType+" " + astName + " = "+labeledElementASTInit+";");
2388                                }
2389                        }
2390
2391                        // for convenience..
2392                        String astName = astNameBase + "_AST";
2393
2394                        // Map the generated AST variable in the alternate
2395                        mapTreeVariable(el, astName);
2396                        if (grammar instanceof TreeWalkerGrammar)
2397                        {
2398                                // Generate an "input" AST variable also
2399                                println(labeledElementASTType+" " + astName + "_in = "+labeledElementASTInit+";");
2400                        }
2401
2402                        // Enclose actions with !guessing
2403                        if (doNoGuessTest) {
2404                                println("if ( inputState->guessing == 0 ) {");
2405                                tabs++;
2406                        }
2407
2408                        // if something has a label assume it will be used
2409                        // so we must initialize the RefAST
2410                        if (el.getLabel() != null)
2411                        {
2412                                if ( el instanceof GrammarAtom )
2413                                {
2414                                        println(astName + " = "+
2415                                                          getASTCreateString((GrammarAtom)el,elementRef) + ";");
2416                                }
2417                                else
2418                                {
2419                                        println(astName + " = "+
2420                                                          getASTCreateString(elementRef) + ";");
2421                                }
2422                        }
2423
2424                        // if it has no label but a declaration exists initialize it.
2425                        if( el.getLabel() == null && needASTDecl )
2426                        {
2427                                elementRef = lt1Value;
2428                                if ( el instanceof GrammarAtom )
2429                                {
2430                                        println(astName + " = "+
2431                                                          getASTCreateString((GrammarAtom)el,elementRef) + ";");
2432                                }
2433                                else
2434                                {
2435                                        println(astName + " = "+
2436                                                          getASTCreateString(elementRef) + ";");
2437                                }
2438                                // Map the generated AST variable in the alternate
2439                                if (grammar instanceof TreeWalkerGrammar)
2440                                {
2441                                        // set "input" AST variable also
2442                                        println(astName + "_in = " + elementRef + ";");
2443                                }
2444                        }
2445
2446                        if (genAST)
2447                        {
2448                                switch (el.getAutoGenType())
2449                                {
2450                                case GrammarElement.AUTO_GEN_NONE:
2451                                        if( usingCustomAST ||
2452                                                 (el instanceof GrammarAtom &&
2453                                                  ((GrammarAtom)el).getASTNodeType() != null) )
2454                                                println("astFactory->addASTChild(currentAST, "+namespaceAntlr+"RefAST("+ astName + "));");
2455                                        else
2456                                                println("astFactory->addASTChild(currentAST, "+ astName + ");");
2457                                        //                                              println("astFactory.addASTChild(currentAST, "+namespaceAntlr+"RefAST(" + astName + "));");
2458                                        break;
2459                                case GrammarElement.AUTO_GEN_CARET:
2460                                        if( usingCustomAST ||
2461                                                 (el instanceof GrammarAtom &&
2462                                                 ((GrammarAtom)el).getASTNodeType() != null) )
2463                                                println("astFactory->makeASTRoot(currentAST, "+namespaceAntlr+"RefAST(" + astName + "));");
2464                                        else
2465                                                println("astFactory->makeASTRoot(currentAST, " + astName + ");");
2466                                        break;
2467                                default:
2468                                        break;
2469                                }
2470                        }
2471                        if (doNoGuessTest)
2472                        {
2473                                tabs--;
2474                                println("}");
2475                        }
2476                }
2477        }
2478        /** Close the try block and generate catch phrases
2479         * if the element has a labeled handler in the rule
2480         */
2481        private void genErrorCatchForElement(AlternativeElement el) {
2482                if (el.getLabel() == null) return;
2483                String r = el.enclosingRuleName;
2484                if ( grammar instanceof LexerGrammar ) {
2485                        r = CodeGenerator.encodeLexerRuleName(el.enclosingRuleName);
2486                }
2487                RuleSymbol rs = (RuleSymbol)grammar.getSymbol(r);
2488                if (rs == null) {
2489                        antlrTool.panic("Enclosing rule not found!");
2490                }
2491                ExceptionSpec ex = rs.block.findExceptionSpec(el.getLabel());
2492                if (ex != null) {
2493                        tabs--;
2494                        println("}");
2495                        genErrorHandler(ex);
2496                }
2497        }
2498        /** Generate the catch phrases for a user-specified error handler */
2499        private void genErrorHandler(ExceptionSpec ex)
2500        {
2501                // Each ExceptionHandler in the ExceptionSpec is a separate catch
2502                for (int i = 0; i < ex.handlers.size(); i++)
2503                {
2504                        ExceptionHandler handler = (ExceptionHandler)ex.handlers.elementAt(i);
2505                        // Generate catch phrase
2506                        println("catch (" + handler.exceptionTypeAndName.getText() + ") {");
2507                        tabs++;
2508                        if (grammar.hasSyntacticPredicate) {
2509                                println("if (inputState->guessing==0) {");
2510                                tabs++;
2511                        }
2512
2513                        // When not guessing, execute user handler action
2514                        ActionTransInfo tInfo = new ActionTransInfo();
2515                        genLineNo(handler.action);
2516                        printAction(
2517                                processActionForSpecialSymbols( handler.action.getText(),
2518                                                                                                                 handler.action.getLine(),
2519                                                                                                                 currentRule, tInfo )
2520                        );
2521                        genLineNo2();
2522
2523                        if (grammar.hasSyntacticPredicate)
2524                        {
2525                                tabs--;
2526                                println("} else {");
2527                                tabs++;
2528                                // When guessing, rethrow exception
2529                                println("throw;");
2530                                tabs--;
2531                                println("}");
2532                        }
2533                        // Close catch phrase
2534                        tabs--;
2535                        println("}");
2536                }
2537        }
2538        /** Generate a try { opening if the element has a labeled handler in the rule */
2539        private void genErrorTryForElement(AlternativeElement el) {
2540                if (el.getLabel() == null) return;
2541                String r = el.enclosingRuleName;
2542                if ( grammar instanceof LexerGrammar ) {
2543                        r = CodeGenerator.encodeLexerRuleName(el.enclosingRuleName);
2544                }
2545                RuleSymbol rs = (RuleSymbol)grammar.getSymbol(r);
2546                if (rs == null) {
2547                        antlrTool.panic("Enclosing rule not found!");
2548                }
2549                ExceptionSpec ex = rs.block.findExceptionSpec(el.getLabel());
2550                if (ex != null) {
2551                        println("try { // for error handling");
2552                        tabs++;
2553                }
2554        }
2555        /** Generate a header that is common to all C++ files */
2556        protected void genHeader(String fileName)
2557        {
2558                println("/* $ANTLR "+antlrTool.version+": "+
2559                                "\""+antlrTool.fileMinusPath(antlrTool.grammarFile)+"\""+
2560                                " -> "+
2561                                "\""+fileName+"\"$ */");
2562        }
2563
2564        // these are unique to C++ mode
2565        public void genInclude(LexerGrammar g) throws IOException
2566        {
2567                outputFile = grammar.getClassName() + ".hpp";
2568                outputLine = 1;
2569                currentOutput = antlrTool.openOutputFile(outputFile);
2570                //SAS: changed for proper text file io
2571
2572                genAST = false; // no way to gen trees.
2573                saveText = true;        // save consumed characters.
2574
2575                tabs=0;
2576
2577                // Generate a guard wrapper
2578                println("#ifndef INC_"+grammar.getClassName()+"_hpp_");
2579                println("#define INC_"+grammar.getClassName()+"_hpp_");
2580                println("");
2581
2582                printHeaderAction(preIncludeHpp);
2583
2584                println("#include <antlr/config.hpp>");
2585
2586                // Generate header common to all C++ output files
2587                genHeader(outputFile);
2588
2589                // Generate header specific to lexer header file
2590                println("#include <antlr/CommonToken.hpp>");
2591                println("#include <antlr/InputBuffer.hpp>");
2592                println("#include <antlr/BitSet.hpp>");
2593                println("#include \"" + grammar.tokenManager.getName() + TokenTypesFileSuffix+".hpp\"");
2594
2595                // Find the name of the super class
2596                String sup=null;
2597                if ( grammar.superClass!=null ) {
2598                        sup = grammar.superClass;
2599
2600                        println("\n// Include correct superclass header with a header statement for example:");
2601                        println("// header \"post_include_hpp\" {");
2602                        println("// #include \""+sup+".hpp\"");
2603                        println("// }");
2604                        println("// Or....");
2605                        println("// header {");
2606                        println("// #include \""+sup+".hpp\"");
2607                        println("// }\n");
2608                }
2609                else {
2610                        sup = grammar.getSuperClass();
2611                        if (sup.lastIndexOf('.') != -1)
2612                                sup = sup.substring(sup.lastIndexOf('.')+1);
2613                        println("#include <antlr/"+sup+".hpp>");
2614                        sup = namespaceAntlr + sup;
2615                }
2616
2617                // Do not use printAction because we assume tabs==0
2618                printHeaderAction(postIncludeHpp);
2619
2620                if (nameSpace != null)
2621                           nameSpace.emitDeclarations(currentOutput);
2622
2623                printHeaderAction("");
2624
2625                // print javadoc comment if any
2626                if ( grammar.comment!=null ) {
2627                        _println(grammar.comment);
2628                }
2629
2630                // Generate lexer class definition
2631                print("class CUSTOM_API " + grammar.getClassName() + " : public " + sup);
2632                println(", public " + grammar.tokenManager.getName() + TokenTypesFileSuffix);
2633
2634                Token tsuffix = (Token)grammar.options.get("classHeaderSuffix");
2635                if ( tsuffix != null ) {
2636                        String suffix = StringUtils.stripFrontBack(tsuffix.getText(),"\"","\"");
2637                        if ( suffix != null ) {
2638                                print(", "+suffix);  // must be an interface name for Java
2639                        }
2640                }
2641                println("{");
2642
2643                // Generate user-defined lexer class members
2644                if (grammar.classMemberAction != null) {
2645                        genLineNo(grammar.classMemberAction);
2646                        print(
2647                                processActionForSpecialSymbols(grammar.classMemberAction.getText(),
2648                                                                                                                 grammar.classMemberAction.getLine(),
2649                                                                                                                 currentRule, null)
2650                        );
2651                        genLineNo2();
2652                }
2653
2654                // Generate initLiterals() method
2655                tabs=0;
2656                println("private:");
2657                tabs=1;
2658                println("void initLiterals();");
2659
2660                // Generate getCaseSensitiveLiterals() method
2661                tabs=0;
2662                println("public:");
2663                tabs=1;
2664                println("bool getCaseSensitiveLiterals() const");
2665                println("{");
2666                tabs++;
2667                println("return "+g.caseSensitiveLiterals + ";");
2668                tabs--;
2669                println("}");
2670
2671                // Make constructors public
2672                tabs=0;
2673                println("public:");
2674                tabs=1;
2675
2676                if( noConstructors )
2677                {
2678                        tabs = 0;
2679                        println("#if 0");
2680                        println("// constructor creation turned of with 'noConstructor' option");
2681                        tabs = 1;
2682                }
2683
2684                // Generate the constructor from std::istream
2685                println(grammar.getClassName() + "(" + namespaceStd + "istream& in);");
2686
2687                // Generate the constructor from InputBuffer
2688                println(grammar.getClassName() + "("+namespaceAntlr+"InputBuffer& ib);");
2689
2690                println(grammar.getClassName() + "(const "+namespaceAntlr+"LexerSharedInputState& state);");
2691                if( noConstructors )
2692                {
2693                        tabs = 0;
2694                        println("// constructor creation turned of with 'noConstructor' option");
2695                        println("#endif");
2696                        tabs = 1;
2697                }
2698
2699                // Generate nextToken() rule.
2700                // nextToken() is a synthetic lexer rule that is the implicit OR of all
2701                // user-defined lexer rules.
2702                println(namespaceAntlr+"RefToken nextToken();");
2703
2704                // Generate code for each rule in the lexer
2705                Enumeration ids = grammar.rules.elements();
2706                while ( ids.hasMoreElements() ) {
2707                        RuleSymbol sym = (RuleSymbol) ids.nextElement();
2708                        // Don't generate the synthetic rules
2709                        if (!sym.getId().equals("mnextToken")) {
2710                                genRuleHeader(sym, false);
2711                        }
2712                        exitIfError();
2713                }
2714
2715                // Make the rest private
2716                tabs=0;
2717                println("private:");
2718                tabs=1;
2719
2720                // generate the rule name array for debugging
2721                if ( grammar.debuggingOutput ) {
2722                        println("static const char* _ruleNames[];");
2723                }
2724
2725                // Generate the semantic predicate map for debugging
2726                if (grammar.debuggingOutput)
2727                        println("static const char* _semPredNames[];");
2728
2729                // Generate the bitsets used throughout the lexer
2730                genBitsetsHeader(bitsetsUsed, ((LexerGrammar)grammar).charVocabulary.size());
2731
2732                tabs=0;
2733                println("};");
2734                println("");
2735                if (nameSpace != null)
2736                        nameSpace.emitClosures(currentOutput);
2737
2738                // Generate a guard wrapper
2739                println("#endif /*INC_"+grammar.getClassName()+"_hpp_*/");
2740
2741                // Close the lexer output stream
2742                currentOutput.close();
2743                currentOutput = null;
2744        }
2745        public void genInclude(ParserGrammar g) throws IOException
2746        {
2747                // Open the output stream for the parser and set the currentOutput
2748                outputFile = grammar.getClassName() + ".hpp";
2749                outputLine = 1;
2750                currentOutput = antlrTool.openOutputFile(outputFile);
2751                //SAS: changed for proper text file io
2752
2753                genAST = grammar.buildAST;
2754
2755                tabs = 0;
2756
2757                // Generate a guard wrapper
2758                println("#ifndef INC_"+grammar.getClassName()+"_hpp_");
2759                println("#define INC_"+grammar.getClassName()+"_hpp_");
2760                println("");
2761                printHeaderAction(preIncludeHpp);
2762                println("#include <antlr/config.hpp>");
2763
2764                // Generate the header common to all output files.
2765                genHeader(outputFile);
2766
2767                // Generate header for the parser
2768                println("#include <antlr/TokenStream.hpp>");
2769                println("#include <antlr/TokenBuffer.hpp>");
2770                println("#include \"" + grammar.tokenManager.getName() + TokenTypesFileSuffix+".hpp\"");
2771
2772                // Generate parser class definition
2773                String sup=null;
2774                if ( grammar.superClass!=null ) {
2775                        sup = grammar.superClass;
2776                        println("\n// Include correct superclass header with a header statement for example:");
2777                        println("// header \"post_include_hpp\" {");
2778                        println("// #include \""+sup+".hpp\"");
2779                        println("// }");
2780                        println("// Or....");
2781                        println("// header {");
2782                        println("// #include \""+sup+".hpp\"");
2783                        println("// }\n");
2784                }
2785                else {
2786                        sup = grammar.getSuperClass();
2787                        if (sup.lastIndexOf('.') != -1)
2788                                sup = sup.substring(sup.lastIndexOf('.')+1);
2789                        println("#include <antlr/"+sup+".hpp>");
2790                        sup = namespaceAntlr + sup;
2791                }
2792                println("");
2793
2794                // Do not use printAction because we assume tabs==0
2795                printHeaderAction(postIncludeHpp);
2796
2797                if (nameSpace != null)
2798                        nameSpace.emitDeclarations(currentOutput);
2799
2800                printHeaderAction("");
2801
2802                // print javadoc comment if any
2803                if ( grammar.comment!=null ) {
2804                        _println(grammar.comment);
2805                }
2806
2807                // generate the actual class definition
2808                print("class CUSTOM_API " + grammar.getClassName() + " : public " + sup);
2809                println(", public " + grammar.tokenManager.getName() + TokenTypesFileSuffix);
2810
2811                Token tsuffix = (Token)grammar.options.get("classHeaderSuffix");
2812                if ( tsuffix != null ) {
2813                        String suffix = StringUtils.stripFrontBack(tsuffix.getText(),"\"","\"");
2814                        if ( suffix != null )
2815                                print(", "+suffix);  // must be an interface name for Java
2816                }
2817                println("{");
2818
2819                // set up an array of all the rule names so the debugger can
2820                // keep track of them only by number -- less to store in tree...
2821                if (grammar.debuggingOutput) {
2822                        println("public: static const char* _ruleNames[];");
2823                }
2824                // Generate user-defined parser class members
2825                if (grammar.classMemberAction != null) {
2826                        genLineNo(grammar.classMemberAction.getLine());
2827                        print(
2828                                processActionForSpecialSymbols(grammar.classMemberAction.getText(),
2829                                                                                                                 grammar.classMemberAction.getLine(),
2830                                                                                                                 currentRule, null)
2831                        );
2832                        genLineNo2();
2833                }
2834                println("public:");
2835                tabs = 1;
2836                println("void initializeASTFactory( "+namespaceAntlr+"ASTFactory& factory );");
2837//              println("// called from constructors");
2838//              println("void _initialize( void );");
2839
2840                // Generate parser class constructor from TokenBuffer
2841                tabs=0;
2842                if( noConstructors )
2843                {
2844                        println("#if 0");
2845                        println("// constructor creation turned of with 'noConstructor' option");
2846                }
2847                println("protected:");
2848                tabs=1;
2849                println(grammar.getClassName() + "("+namespaceAntlr+"TokenBuffer& tokenBuf, int k);");
2850                tabs=0;
2851                println("public:");
2852                tabs=1;
2853                println(grammar.getClassName() + "("+namespaceAntlr+"TokenBuffer& tokenBuf);");
2854
2855                // Generate parser class constructor from TokenStream
2856                tabs=0;
2857                println("protected:");
2858                tabs=1;
2859                println(grammar.getClassName()+"("+namespaceAntlr+"TokenStream& lexer, int k);");
2860                tabs=0;
2861                println("public:");
2862                tabs=1;
2863                println(grammar.getClassName()+"("+namespaceAntlr+"TokenStream& lexer);");
2864
2865                println(grammar.getClassName()+"(const "+namespaceAntlr+"ParserSharedInputState& state);");
2866                if( noConstructors )
2867                {
2868                        tabs = 0;
2869                        println("// constructor creation turned of with 'noConstructor' option");
2870                        println("#endif");
2871                        tabs = 1;
2872                }
2873
2874                println("int getNumTokens() const");
2875                println("{"); tabs++;
2876                println("return "+grammar.getClassName()+"::NUM_TOKENS;");
2877                tabs--; println("}");
2878                println("const char* getTokenName( int type ) const");
2879                println("{"); tabs++;
2880                println("if( type > getNumTokens() ) return 0;");
2881                println("return "+grammar.getClassName()+"::tokenNames[type];");
2882                tabs--; println("}");
2883                println("const char* const* getTokenNames() const");
2884                println("{"); tabs++;
2885                println("return "+grammar.getClassName()+"::tokenNames;");
2886                tabs--; println("}");
2887
2888                // Generate code for each rule in the grammar
2889                Enumeration ids = grammar.rules.elements();
2890                while ( ids.hasMoreElements() ) {
2891                        GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
2892                        if ( sym instanceof RuleSymbol) {
2893                                RuleSymbol rs = (RuleSymbol)sym;
2894                                genRuleHeader(rs, rs.references.size()==0);
2895                        }
2896                        exitIfError();
2897                }
2898
2899                // RK: when we are using a custom ast override Parser::getAST to return
2900                // the custom AST type. Ok, this does not work anymore with newer
2901                // compilers gcc 3.2.x and up. The reference counter is probably
2902                // getting in the way.
2903                // So now we just patch the return type back to RefAST
2904                tabs = 0; println("public:"); tabs = 1;
2905                println(namespaceAntlr+"RefAST getAST()");
2906                println("{");
2907                if( usingCustomAST )
2908                {
2909                        tabs++;
2910                        println("return "+namespaceAntlr+"RefAST(returnAST);");
2911                        tabs--;
2912                }
2913                else
2914                {
2915                        tabs++;
2916                        println("return returnAST;");
2917                        tabs--;
2918                }
2919                println("}");
2920                println("");
2921
2922                tabs=0; println("protected:"); tabs=1;
2923                println(labeledElementASTType+" returnAST;");
2924
2925                // Make the rest private
2926                tabs=0;
2927                println("private:");
2928                tabs=1;
2929
2930                // Generate the token names
2931                println("static const char* tokenNames[];");
2932                // and how many there are of them
2933                _println("#ifndef NO_STATIC_CONSTS");
2934                println("static const int NUM_TOKENS = "+grammar.tokenManager.getVocabulary().size()+";");
2935                _println("#else");
2936                println("enum {");
2937                println("\tNUM_TOKENS = "+grammar.tokenManager.getVocabulary().size());
2938                println("};");
2939                _println("#endif");
2940
2941                // Generate the bitsets used throughout the grammar
2942                genBitsetsHeader(bitsetsUsed, grammar.tokenManager.maxTokenType());
2943
2944                // Generate the semantic predicate map for debugging
2945                if (grammar.debuggingOutput)
2946                        println("static const char* _semPredNames[];");
2947
2948                // Close class definition
2949                tabs=0;
2950                println("};");
2951                println("");
2952                if (nameSpace != null)
2953                        nameSpace.emitClosures(currentOutput);
2954
2955                // Generate a guard wrapper
2956                println("#endif /*INC_"+grammar.getClassName()+"_hpp_*/");
2957
2958                // Close the parser output stream
2959                currentOutput.close();
2960                currentOutput = null;
2961        }
2962        public void genInclude(TreeWalkerGrammar g) throws IOException
2963        {
2964                // Open the output stream for the parser and set the currentOutput
2965                outputFile = grammar.getClassName() + ".hpp";
2966                outputLine = 1;
2967                currentOutput = antlrTool.openOutputFile(outputFile);
2968                //SAS: changed for proper text file io
2969
2970                genAST = grammar.buildAST;
2971                tabs = 0;
2972
2973                // Generate a guard wrapper
2974                println("#ifndef INC_"+grammar.getClassName()+"_hpp_");
2975                println("#define INC_"+grammar.getClassName()+"_hpp_");
2976                println("");
2977                printHeaderAction(preIncludeHpp);
2978                println("#include <antlr/config.hpp>");
2979                println("#include \"" + grammar.tokenManager.getName() + TokenTypesFileSuffix+".hpp\"");
2980
2981                // Generate the header common to all output files.
2982                genHeader(outputFile);
2983
2984                // Find the name of the super class
2985                String sup=null;
2986                if ( grammar.superClass!=null ) {
2987                        sup = grammar.superClass;
2988                        println("\n// Include correct superclass header with a header statement for example:");
2989                        println("// header \"post_include_hpp\" {");
2990                        println("// #include \""+sup+".hpp\"");
2991                        println("// }");
2992                        println("// Or....");
2993                        println("// header {");
2994                        println("// #include \""+sup+".hpp\"");
2995                        println("// }\n");
2996                }
2997                else {
2998                        sup = grammar.getSuperClass();
2999                        if (sup.lastIndexOf('.') != -1)
3000                                sup = sup.substring(sup.lastIndexOf('.')+1);
3001                        println("#include <antlr/"+sup+".hpp>");
3002                        sup = namespaceAntlr + sup;
3003                }
3004                println("");
3005
3006                // Generate header for the parser
3007                //
3008                // Do not use printAction because we assume tabs==0
3009                printHeaderAction(postIncludeHpp);
3010
3011                if (nameSpace != null)
3012                        nameSpace.emitDeclarations(currentOutput);
3013
3014                printHeaderAction("");
3015
3016                // print javadoc comment if any
3017                if ( grammar.comment!=null ) {
3018                        _println(grammar.comment);
3019                }
3020
3021                // Generate parser class definition
3022                print("class CUSTOM_API " + grammar.getClassName() + " : public "+sup);
3023                println(", public " + grammar.tokenManager.getName() + TokenTypesFileSuffix);
3024
3025                Token tsuffix = (Token)grammar.options.get("classHeaderSuffix");
3026                if ( tsuffix != null ) {
3027                        String suffix = StringUtils.stripFrontBack(tsuffix.getText(),"\"","\"");
3028                        if ( suffix != null ) {
3029                                print(", "+suffix);  // must be an interface name for Java
3030                        }
3031                }
3032                println("{");
3033
3034                // Generate user-defined parser class members
3035                if (grammar.classMemberAction != null) {
3036                        genLineNo(grammar.classMemberAction.getLine());
3037                        print(
3038                                        processActionForSpecialSymbols(grammar.classMemberAction.getText(),
3039                                                                                                                         grammar.classMemberAction.getLine(),
3040                                                                                                                         currentRule, null)
3041                                        );
3042                        genLineNo2();
3043                }
3044
3045                // Generate default parser class constructor
3046                tabs=0;
3047                println("public:");
3048
3049                if( noConstructors )
3050                {
3051                        println("#if 0");
3052                        println("// constructor creation turned of with 'noConstructor' option");
3053                }
3054                tabs=1;
3055                println(grammar.getClassName() + "();");
3056                if( noConstructors )
3057                {
3058                        tabs = 0;
3059                        println("#endif");
3060                        tabs = 1;
3061                }
3062
3063                // Generate declaration for the initializeFactory method
3064                println("static void initializeASTFactory( "+namespaceAntlr+"ASTFactory& factory );");
3065
3066                println("int getNumTokens() const");
3067                println("{"); tabs++;
3068                println("return "+grammar.getClassName()+"::NUM_TOKENS;");
3069                tabs--; println("}");
3070                println("const char* getTokenName( int type ) const");
3071                println("{"); tabs++;
3072                println("if( type > getNumTokens() ) return 0;");
3073                println("return "+grammar.getClassName()+"::tokenNames[type];");
3074                tabs--; println("}");
3075                println("const char* const* getTokenNames() const");
3076                println("{"); tabs++;
3077                println("return "+grammar.getClassName()+"::tokenNames;");
3078                tabs--; println("}");
3079
3080                // Generate code for each rule in the grammar
3081                Enumeration ids = grammar.rules.elements();
3082                String ruleNameInits = "";
3083                while ( ids.hasMoreElements() ) {
3084                        GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
3085                        if ( sym instanceof RuleSymbol) {
3086                                RuleSymbol rs = (RuleSymbol)sym;
3087                                genRuleHeader(rs, rs.references.size()==0);
3088                        }
3089                        exitIfError();
3090                }
3091                tabs = 0; println("public:"); tabs = 1;
3092                println(namespaceAntlr+"RefAST getAST()");
3093                println("{");
3094                if( usingCustomAST )
3095                {
3096                        tabs++;
3097                        println("return "+namespaceAntlr+"RefAST(returnAST);");
3098                        tabs--;
3099                }
3100                else
3101                {
3102                        tabs++;
3103                        println("return returnAST;");
3104                        tabs--;
3105                }
3106                println("}");
3107                println("");
3108
3109                tabs=0; println("protected:"); tabs=1;
3110                println(labeledElementASTType+" returnAST;");
3111                println(labeledElementASTType+" _retTree;");
3112
3113                // Make the rest private
3114                tabs=0;
3115                println("private:");
3116                tabs=1;
3117
3118                // Generate the token names
3119                println("static const char* tokenNames[];");
3120                // and how many there are of them
3121                _println("#ifndef NO_STATIC_CONSTS");
3122                println("static const int NUM_TOKENS = "+grammar.tokenManager.getVocabulary().size()+";");
3123                _println("#else");
3124                println("enum {");
3125                println("\tNUM_TOKENS = "+grammar.tokenManager.getVocabulary().size());
3126                println("};");
3127                _println("#endif");
3128
3129                // Generate the bitsets used throughout the grammar
3130                genBitsetsHeader(bitsetsUsed, grammar.tokenManager.maxTokenType());
3131
3132                // Close class definition
3133                tabs=0;
3134                println("};");
3135                println("");
3136                if (nameSpace != null)
3137                        nameSpace.emitClosures(currentOutput);
3138
3139                // Generate a guard wrapper
3140                println("#endif /*INC_"+grammar.getClassName()+"_hpp_*/");
3141
3142                // Close the parser output stream
3143                currentOutput.close();
3144                currentOutput = null;
3145        }
3146        /// for convenience
3147        protected void genASTDeclaration( AlternativeElement el ) {
3148                genASTDeclaration( el, labeledElementASTType );
3149        }
3150        /// for convenience
3151        protected void genASTDeclaration( AlternativeElement el, String node_type ) {
3152                genASTDeclaration( el, el.getLabel(), node_type );
3153        }
3154        /// Generate (if not already done) a declaration for the AST for el.
3155        protected void genASTDeclaration( AlternativeElement el, String var_name, String node_type ) {
3156                // already declared?
3157                if( declaredASTVariables.contains(el) )
3158                        return;
3159
3160                String init = labeledElementASTInit;
3161
3162                if (el instanceof GrammarAtom &&
3163                         ((GrammarAtom)el).getASTNodeType() != null )
3164                        init = "Ref"+((GrammarAtom)el).getASTNodeType()+"("+labeledElementASTInit+")";
3165
3166                // emit code
3167                println(node_type+" " + var_name + "_AST = "+init+";");
3168
3169                // mark as declared
3170                declaredASTVariables.put(el, el);
3171        }
3172        private void genLiteralsTest() {
3173                println("_ttype = testLiteralsTable(_ttype);");
3174        }
3175        private void genLiteralsTestForPartialToken() {
3176                println("_ttype = testLiteralsTable(text.substr(_begin, text.length()-_begin),_ttype);");
3177        }
3178        protected void genMatch(BitSet b) {
3179        }
3180        protected void genMatch(GrammarAtom atom) {
3181                if ( atom instanceof StringLiteralElement ) {
3182                        if ( grammar instanceof LexerGrammar ) {
3183                                genMatchUsingAtomText(atom);
3184                        }
3185                        else {
3186                                genMatchUsingAtomTokenType(atom);
3187                        }
3188                }
3189                else if ( atom instanceof CharLiteralElement ) {
3190                        // Lexer case is handled in the gen( CharLiteralElement x )
3191                        antlrTool.error("cannot ref character literals in grammar: "+atom);
3192                }
3193                else if ( atom instanceof TokenRefElement ) {
3194                        genMatchUsingAtomTokenType(atom);
3195                } else if (atom instanceof WildcardElement) {
3196                        gen((WildcardElement)atom);
3197                }
3198        }
3199        protected void genMatchUsingAtomText(GrammarAtom atom) {
3200                // match() for trees needs the _t cursor
3201                String astArgs="";
3202                if (grammar instanceof TreeWalkerGrammar) {
3203                        if( usingCustomAST )
3204                                astArgs=namespaceAntlr+"RefAST"+"(_t),";
3205                        else
3206                                astArgs="_t,";
3207                }
3208
3209                // if in lexer and ! on element, save buffer index to kill later
3210                if ( grammar instanceof LexerGrammar && (!saveText||atom.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
3211                        println("_saveIndex = text.length();");
3212                }
3213
3214                print(atom.not ? "matchNot(" : "match(");
3215                _print(astArgs);
3216
3217                // print out what to match
3218                if (atom.atomText.equals("EOF")) {
3219                        // horrible hack to handle EOF case
3220                        _print(namespaceAntlr+"Token::EOF_TYPE");
3221                }
3222                else
3223                {
3224                        if( grammar instanceof LexerGrammar )   // lexer needs special handling
3225                        {
3226                                String cppstring = convertJavaToCppString( atom.atomText, false );
3227                                _print(cppstring);
3228                        }
3229                        else
3230                                _print(atom.atomText);
3231                }
3232
3233                _println(");");
3234
3235                if ( grammar instanceof LexerGrammar && (!saveText||atom.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
3236                        println("text.erase(_saveIndex);");      // kill text atom put in buffer
3237                }
3238        }
3239        protected void genMatchUsingAtomTokenType(GrammarAtom atom) {
3240                // match() for trees needs the _t cursor
3241                String astArgs="";
3242                if (grammar instanceof TreeWalkerGrammar) {
3243                        if( usingCustomAST )
3244                                astArgs=namespaceAntlr+"RefAST"+"(_t),";
3245                        else
3246                                astArgs="_t,";
3247                }
3248
3249                // If the literal can be mangled, generate the symbolic constant instead
3250                String s = astArgs + getValueString(atom.getType());
3251
3252                // matching
3253                println( (atom.not ? "matchNot(" : "match(") + s + ");");
3254        }
3255        /** Generate the nextToken() rule.
3256         * nextToken() is a synthetic lexer rule that is the implicit OR of all
3257         * user-defined lexer rules.
3258         * @param RuleBlock
3259         */
3260        public void genNextToken() {
3261                // Are there any public rules?  If not, then just generate a
3262                // fake nextToken().
3263                boolean hasPublicRules = false;
3264                for (int i = 0; i < grammar.rules.size(); i++) {
3265                        RuleSymbol rs = (RuleSymbol)grammar.rules.elementAt(i);
3266                        if ( rs.isDefined() && rs.access.equals("public") ) {
3267                                hasPublicRules = true;
3268                                break;
3269                        }
3270                }
3271                if (!hasPublicRules) {
3272                        println("");
3273                        println(namespaceAntlr+"RefToken "+grammar.getClassName()+"::nextToken() { return "+namespaceAntlr+"RefToken(new "+namespaceAntlr+"CommonToken("+namespaceAntlr+"Token::EOF_TYPE, \"\")); }");
3274                        println("");
3275                        return;
3276                }
3277
3278                // Create the synthesized nextToken() rule
3279                RuleBlock nextTokenBlk = MakeGrammar.createNextTokenRule(grammar, grammar.rules, "nextToken");
3280                // Define the nextToken rule symbol
3281                RuleSymbol nextTokenRs = new RuleSymbol("mnextToken");
3282                nextTokenRs.setDefined();
3283                nextTokenRs.setBlock(nextTokenBlk);
3284                nextTokenRs.access = "private";
3285                grammar.define(nextTokenRs);
3286                // Analyze the nextToken rule
3287                boolean ok = grammar.theLLkAnalyzer.deterministic(nextTokenBlk);
3288
3289                // Generate the next token rule
3290                String filterRule=null;
3291                if ( ((LexerGrammar)grammar).filterMode ) {
3292                        filterRule = ((LexerGrammar)grammar).filterRule;
3293                }
3294
3295                println("");
3296                println(namespaceAntlr+"RefToken "+grammar.getClassName()+"::nextToken()");
3297                println("{");
3298                tabs++;
3299                println(namespaceAntlr+"RefToken theRetToken;");
3300                println("for (;;) {");
3301                tabs++;
3302                println(namespaceAntlr+"RefToken theRetToken;");
3303                println("int _ttype = "+namespaceAntlr+"Token::INVALID_TYPE;");
3304                if ( ((LexerGrammar)grammar).filterMode ) {
3305                        println("setCommitToPath(false);");
3306                        if ( filterRule!=null ) {
3307                                // Here's a good place to ensure that the filter rule actually exists
3308                                if ( !grammar.isDefined(CodeGenerator.encodeLexerRuleName(filterRule)) ) {
3309                                        grammar.antlrTool.error("Filter rule "+filterRule+" does not exist in this lexer");
3310                                }
3311                                else {
3312                                        RuleSymbol rs = (RuleSymbol)grammar.getSymbol(CodeGenerator.encodeLexerRuleName(filterRule));
3313                                        if ( !rs.isDefined() ) {
3314                                                grammar.antlrTool.error("Filter rule "+filterRule+" does not exist in this lexer");
3315                                        }
3316                                        else if ( rs.access.equals("public") ) {
3317                                                grammar.antlrTool.error("Filter rule "+filterRule+" must be protected");
3318                                        }
3319                                }
3320                                println("int _m;");
3321                                println("_m = mark();");
3322                        }
3323                }
3324                println("resetText();");
3325
3326                // Generate try around whole thing to trap scanner errors
3327                println("try {   // for lexical and char stream error handling");
3328                tabs++;
3329
3330                // Test for public lexical rules with empty paths
3331                for (int i=0; i<nextTokenBlk.getAlternatives().size(); i++) {
3332                        Alternative a = nextTokenBlk.getAlternativeAt(i);
3333                        if ( a.cache[1].containsEpsilon() ) {
3334                                antlrTool.warning("found optional path in nextToken()");
3335                        }
3336                }
3337
3338                // Generate the block
3339                String newline = System.getProperty("line.separator");
3340                CppBlockFinishingInfo howToFinish = genCommonBlock(nextTokenBlk, false);
3341                String errFinish = "if (LA(1)==EOF_CHAR)"+newline+
3342                        "\t\t\t\t{"+newline+"\t\t\t\t\tuponEOF();"+newline+
3343                        "\t\t\t\t\t_returnToken = makeToken("+namespaceAntlr+"Token::EOF_TYPE);"+
3344                        newline+"\t\t\t\t}";
3345                errFinish += newline+"\t\t\t\t";
3346                if ( ((LexerGrammar)grammar).filterMode ) {
3347                        if ( filterRule==null ) {
3348                                errFinish += "else {consume(); goto tryAgain;}";
3349                        }
3350                        else {
3351                                errFinish += "else {"+newline+
3352                                                "\t\t\t\t\tcommit();"+newline+
3353                                                "\t\t\t\t\ttry {m"+filterRule+"(false);}"+newline+
3354                                                "\t\t\t\t\tcatch("+namespaceAntlr+"RecognitionException& e) {"+newline+
3355                                                "\t\t\t\t\t     // catastrophic failure"+newline+
3356                                                "\t\t\t\t\t     reportError(e);"+newline+
3357                                                "\t\t\t\t\t     consume();"+newline+
3358                                                "\t\t\t\t\t}"+newline+
3359                                                "\t\t\t\t\tgoto tryAgain;"+newline+
3360                                                "\t\t\t\t}";
3361                        }
3362                }
3363                else {
3364                        errFinish += "else {"+throwNoViable+"}";
3365                }
3366                genBlockFinish(howToFinish, errFinish);
3367
3368                // at this point a valid token has been matched, undo "mark" that was done
3369                if ( ((LexerGrammar)grammar).filterMode && filterRule!=null ) {
3370                        println("commit();");
3371                }
3372
3373                // Generate literals test if desired
3374                // make sure _ttype is set first; note _returnToken must be
3375                // non-null as the rule was required to create it.
3376                println("if ( !_returnToken )"+newline+
3377                                  "\t\t\t\tgoto tryAgain; // found SKIP token"+newline);
3378                println("_ttype = _returnToken->getType();");
3379                if ( ((LexerGrammar)grammar).getTestLiterals()) {
3380                        genLiteralsTest();
3381                }
3382
3383                // return token created by rule reference in switch
3384                println("_returnToken->setType(_ttype);");
3385                println("return _returnToken;");
3386
3387                // Close try block
3388                tabs--;
3389                println("}");
3390                println("catch ("+namespaceAntlr+"RecognitionException& e) {");
3391                tabs++;
3392                if ( ((LexerGrammar)grammar).filterMode ) {
3393                        if ( filterRule==null ) {
3394                                println("if ( !getCommitToPath() ) {");
3395                                tabs++;
3396                                println("consume();");
3397                                println("goto tryAgain;");
3398                                tabs--;
3399                                println("}");
3400                        }
3401                        else {
3402                                println("if ( !getCommitToPath() ) {");
3403                                tabs++;
3404                                println("rewind(_m);");
3405                                println("resetText();");
3406                                println("try {m"+filterRule+"(false);}");
3407                                println("catch("+namespaceAntlr+"RecognitionException& ee) {");
3408                                println("       // horrendous failure: error in filter rule");
3409                                println("       reportError(ee);");
3410                                println("       consume();");
3411                                println("}");
3412                                // println("goto tryAgain;");
3413                                tabs--;
3414                                println("}");
3415                                println("else");
3416                        }
3417                }
3418                if ( nextTokenBlk.getDefaultErrorHandler() ) {
3419                        println("{");
3420                        tabs++;
3421                        println("reportError(e);");
3422                        println("consume();");
3423                        tabs--;
3424                        println("}");
3425                }
3426                else {
3427                    // pass on to invoking routine
3428          tabs++;
3429                    println("throw "+namespaceAntlr+"TokenStreamRecognitionException(e);");
3430                         tabs--;
3431                }
3432
3433                // close CharStreamException try
3434                tabs--;
3435                println("}");
3436                println("catch ("+namespaceAntlr+"CharStreamIOException& csie) {");
3437                println("\tthrow "+namespaceAntlr+"TokenStreamIOException(csie.io);");
3438                println("}");
3439                println("catch ("+namespaceAntlr+"CharStreamException& cse) {");
3440                println("\tthrow "+namespaceAntlr+"TokenStreamException(cse.getMessage());");
3441                println("}");
3442
3443                // close for-loop
3444                _println("tryAgain:;");
3445                tabs--;
3446                println("}");
3447
3448                // close method nextToken
3449                tabs--;
3450                println("}");
3451                println("");
3452        }
3453        /** Gen a named rule block.
3454         * ASTs are generated for each element of an alternative unless
3455         * the rule or the alternative have a '!' modifier.
3456         *
3457         * If an alternative defeats the default tree construction, it
3458         * must set <rule>_AST to the root of the returned AST.
3459         *
3460         * Each alternative that does automatic tree construction, builds
3461         * up root and child list pointers in an ASTPair structure.
3462         *
3463         * A rule finishes by setting the returnAST variable from the
3464         * ASTPair.
3465         *
3466         * @param rule The name of the rule to generate
3467         * @param startSymbol true if the rule is a start symbol (i.e., not referenced elsewhere)
3468        */
3469        public void genRule(RuleSymbol s, boolean startSymbol, int ruleNum, String prefix) {
3470//              tabs=1; // JavaCodeGenerator needs this
3471                if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genRule("+ s.getId() +")");
3472                if ( !s.isDefined() ) {
3473                        antlrTool.error("undefined rule: "+ s.getId());
3474                        return;
3475                }
3476
3477                // Generate rule return type, name, arguments
3478                RuleBlock rblk = s.getBlock();
3479
3480                currentRule = rblk;
3481                currentASTResult = s.getId();
3482
3483                // clear list of declared ast variables..
3484                declaredASTVariables.clear();
3485
3486                // Save the AST generation state, and set it to that of the rule
3487                boolean savegenAST = genAST;
3488                genAST = genAST && rblk.getAutoGen();
3489
3490                // boolean oldsaveTest = saveText;
3491                saveText = rblk.getAutoGen();
3492
3493                // print javadoc comment if any
3494                if ( s.comment!=null ) {
3495                        _println(s.comment);
3496                }
3497
3498                // Gen method return type (note lexer return action set at rule creation)
3499                if (rblk.returnAction != null)
3500                {
3501                        // Has specified return value
3502                        _print(extractTypeOfAction(rblk.returnAction, rblk.getLine(), rblk.getColumn()) + " ");
3503                } else {
3504                        // No specified return value
3505                        _print("void ");
3506                }
3507
3508                // Gen method name
3509                _print(prefix + s.getId() + "(");
3510
3511                // Additional rule parameters common to all rules for this grammar
3512                _print(commonExtraParams);
3513                if (commonExtraParams.length() != 0 && rblk.argAction != null ) {
3514                        _print(",");
3515                }
3516
3517                // Gen arguments
3518                if (rblk.argAction != null)
3519                {
3520                        // Has specified arguments
3521                        _println("");
3522// FIXME: make argAction also a token? Hmmmmm
3523//                      genLineNo(rblk);
3524                        tabs++;
3525
3526                        // Process arguments for default arguments
3527                        // newer gcc's don't accept these in two places (header/cpp)
3528                        //
3529                        // Old appraoch with StringBuffer gave trouble with gcj.
3530                        //
3531                        // RK: Actually this breaks with string default arguments containing
3532                        // a comma's or equal signs. Then again the old StringBuffer method
3533                        // suffered from the same.
3534                        String oldarg = rblk.argAction;
3535                        String newarg = "";
3536
3537                        String comma = "";
3538                        int eqpos = oldarg.indexOf( '=' );
3539                        if( eqpos != -1 )
3540                        {
3541                                int cmpos = 0;
3542                                while( cmpos != -1 && eqpos != -1 )
3543                                {
3544                                        newarg = newarg + comma + oldarg.substring( 0, eqpos ).trim();
3545                                        comma = ", ";
3546                                        cmpos = oldarg.indexOf( ',', eqpos );
3547                                        if( cmpos != -1 )
3548                                        {
3549                                                // cut off part we just handled
3550                                                oldarg = oldarg.substring( cmpos+1 ).trim();
3551                                                eqpos = oldarg.indexOf( '=' );
3552                                                if( eqpos == -1 )
3553                                                        newarg = newarg+comma+oldarg;
3554                                        }
3555                                }
3556                        }
3557                        else
3558                                newarg = oldarg;
3559
3560                        println( newarg );
3561
3562//                      println(rblk.argAction);
3563                        tabs--;
3564                        print(") ");
3565//                      genLineNo2();   // gcc gives error on the brace... hope it works for the others too
3566                } else {
3567                        // No specified arguments
3568                        _print(") ");
3569                }
3570                _println("{");
3571                tabs++;
3572
3573                if (grammar.traceRules) {
3574                        if ( grammar instanceof TreeWalkerGrammar ) {
3575                                if ( usingCustomAST )
3576                                        println("Tracer traceInOut(this,\""+ s.getId() +"\","+namespaceAntlr+"RefAST"+"(_t));");
3577                                else
3578                                        println("Tracer traceInOut(this,\""+ s.getId() +"\",_t);");
3579                        }
3580                        else {
3581                                println("Tracer traceInOut(this, \""+ s.getId() +"\");");
3582                        }
3583                }
3584
3585                // Convert return action to variable declaration
3586                if (rblk.returnAction != null)
3587                {
3588                        genLineNo(rblk);
3589                        println(rblk.returnAction + ";");
3590                        genLineNo2();
3591                }
3592
3593                // print out definitions needed by rules for various grammar types
3594                if (!commonLocalVars.equals(""))
3595                        println(commonLocalVars);
3596
3597                if ( grammar instanceof LexerGrammar ) {
3598                        // RK: why is this here? It seems not supported in the rest of the
3599                        // tool.
3600                        // lexer rule default return value is the rule's token name
3601                        // This is a horrible hack to support the built-in EOF lexer rule.
3602                        if (s.getId().equals("mEOF"))
3603                                println("_ttype = "+namespaceAntlr+"Token::EOF_TYPE;");
3604                        else
3605                                println("_ttype = "+ s.getId().substring(1)+";");
3606                        println(namespaceStd+"string::size_type _saveIndex;");          // used for element! (so we can kill text matched for element)
3607/*
3608                        println("boolean old_saveConsumedInput=saveConsumedInput;");
3609                        if ( !rblk.getAutoGen() ) {      // turn off "save input" if ! on rule
3610                                println("saveConsumedInput=false;");
3611                        }
3612*/
3613                }
3614
3615                // if debugging, write code to mark entry to the rule
3616                if ( grammar.debuggingOutput)
3617                    if (grammar instanceof ParserGrammar)
3618                                println("fireEnterRule(" + ruleNum + ",0);");
3619                        else if (grammar instanceof LexerGrammar)
3620                                println("fireEnterRule(" + ruleNum + ",_ttype);");
3621
3622                // Generate trace code if desired
3623//              if ( grammar.debuggingOutput || grammar.traceRules) {
3624//                      println("try { // debugging");
3625//                      tabs++;
3626//              }
3627
3628                // Initialize AST variables
3629                if (grammar instanceof TreeWalkerGrammar) {
3630                        // "Input" value for rule
3631//                      println(labeledElementASTType+" " + s.getId() + "_AST_in = "+labeledElementASTType+"(_t);");
3632                        println(labeledElementASTType+" " + s.getId() + "_AST_in = (_t == "+labeledElementASTType+"(ASTNULL)) ? "+labeledElementASTInit+" : _t;");
3633                }
3634                if (grammar.buildAST) {
3635                        // Parser member used to pass AST returns from rule invocations
3636                        println("returnAST = "+labeledElementASTInit+";");
3637                        // Tracks AST construction
3638                        println(namespaceAntlr+"ASTPair currentAST;"); // = new ASTPair();");
3639                        // User-settable return value for rule.
3640                        println(labeledElementASTType+" " + s.getId() + "_AST = "+labeledElementASTInit+";");
3641                }
3642
3643                genBlockPreamble(rblk);
3644                genBlockInitAction(rblk);
3645                println("");
3646
3647                // Search for an unlabeled exception specification attached to the rule
3648                ExceptionSpec unlabeledUserSpec = rblk.findExceptionSpec("");
3649
3650                // Generate try block around the entire rule for  error handling
3651                if (unlabeledUserSpec != null || rblk.getDefaultErrorHandler() ) {
3652                        println("try {      // for error handling");
3653                        tabs++;
3654                }
3655
3656                // Generate the alternatives
3657                if ( rblk.alternatives.size()==1 )
3658                {
3659                        // One alternative -- use simple form
3660                        Alternative alt = rblk.getAlternativeAt(0);
3661                        String pred = alt.semPred;
3662                        if ( pred!=null )
3663                                genSemPred(pred, currentRule.line);
3664                        if (alt.synPred != null) {
3665                                antlrTool.warning(
3666                                        "Syntactic predicate ignored for single alternative",
3667                                        grammar.getFilename(),
3668                                        alt.synPred.getLine(),
3669                                        alt.synPred.getColumn()
3670                                );
3671                        }
3672                        genAlt(alt, rblk);
3673                }
3674                else
3675                {
3676                        // Multiple alternatives -- generate complex form
3677                        boolean ok = grammar.theLLkAnalyzer.deterministic(rblk);
3678
3679                        CppBlockFinishingInfo howToFinish = genCommonBlock(rblk, false);
3680                        genBlockFinish(howToFinish, throwNoViable);
3681                }
3682
3683                // Generate catch phrase for error handling
3684                if (unlabeledUserSpec != null || rblk.getDefaultErrorHandler() ) {
3685                        // Close the try block
3686                        tabs--;
3687                        println("}");
3688                }
3689
3690                // Generate user-defined or default catch phrases
3691                if (unlabeledUserSpec != null)
3692                {
3693                        genErrorHandler(unlabeledUserSpec);
3694                }
3695                else if (rblk.getDefaultErrorHandler())
3696                {
3697                        // Generate default catch phrase
3698                        println("catch (" + exceptionThrown + "& ex) {");
3699                        tabs++;
3700                        // Generate code to handle error if not guessing
3701                        if (grammar.hasSyntacticPredicate) {
3702                                println("if( inputState->guessing == 0 ) {");
3703                                tabs++;
3704                        }
3705                        println("reportError(ex);");
3706                        if ( !(grammar instanceof TreeWalkerGrammar) )
3707                        {
3708                                // Generate code to consume until token in k==1 follow set
3709                                Lookahead follow = grammar.theLLkAnalyzer.FOLLOW(1, rblk.endNode);
3710                                String followSetName = getBitsetName(markBitsetForGen(follow.fset));
3711                                println("recover(ex," + followSetName + ");");
3712                        }
3713                        else
3714                        {
3715                                // Just consume one token
3716                                println("if ( _t != "+labeledElementASTInit+" )");
3717                                tabs++;
3718                                println("_t = _t->getNextSibling();");
3719                                tabs--;
3720                        }
3721                        if (grammar.hasSyntacticPredicate)
3722                        {
3723                                tabs--;
3724                                // When guessing, rethrow exception
3725                                println("} else {");
3726                                tabs++;
3727                                println("throw;");
3728                                tabs--;
3729                                println("}");
3730                        }
3731                        // Close catch phrase
3732                        tabs--;
3733                        println("}");
3734                }
3735
3736                // Squirrel away the AST "return" value
3737                if (grammar.buildAST) {
3738                        println("returnAST = " + s.getId() + "_AST;");
3739                }
3740
3741                // Set return tree value for tree walkers
3742                if ( grammar instanceof TreeWalkerGrammar ) {
3743                        println("_retTree = _t;");
3744                }
3745
3746                // Generate literals test for lexer rules so marked
3747                if (rblk.getTestLiterals()) {
3748                        if ( s.access.equals("protected") ) {
3749                                genLiteralsTestForPartialToken();
3750                        }
3751                        else {
3752                                genLiteralsTest();
3753                        }
3754                }
3755
3756                // if doing a lexer rule, dump code to create token if necessary
3757                if ( grammar instanceof LexerGrammar ) {
3758                        println("if ( _createToken && _token=="+namespaceAntlr+"nullToken && _ttype!="+namespaceAntlr+"Token::SKIP ) {");
3759                        println("   _token = makeToken(_ttype);");
3760                        println("   _token->setText(text.substr(_begin, text.length()-_begin));");
3761                        println("}");
3762                        println("_returnToken = _token;");
3763                        // It should be easy for an optimizing compiler to realize this does nothing
3764                        // but it avoids the warning about the variable being unused.
3765                        println("_saveIndex=0;");
3766                }
3767
3768                // Gen the return statement if there is one (lexer has hard-wired return action)
3769                if (rblk.returnAction != null) {
3770                        println("return " + extractIdOfAction(rblk.returnAction, rblk.getLine(), rblk.getColumn()) + ";");
3771                }
3772
3773//              if ( grammar.debuggingOutput || grammar.traceRules) {
3774////                    tabs--;
3775////                    println("} finally { // debugging");
3776////                    tabs++;
3777//
3778//                      // Generate trace code if desired
3779//                      if ( grammar.debuggingOutput)
3780//                              if (grammar instanceof ParserGrammar)
3781//                                      println("fireExitRule(" + ruleNum + ",0);");
3782//                              else if (grammar instanceof LexerGrammar)
3783//                                      println("fireExitRule(" + ruleNum + ",_ttype);");
3784//
3785////                    if (grammar.traceRules) {
3786////                            if ( grammar instanceof TreeWalkerGrammar ) {
3787////                                    println("traceOut(\""+ s.getId() +"\",_t);");
3788////                            }
3789////                            else {
3790////                                    println("traceOut(\""+ s.getId() +"\");");
3791////                            }
3792////                    }
3793////
3794////                    tabs--;
3795////                    println("}");
3796//              }
3797
3798                tabs--;
3799                println("}");
3800                println("");
3801
3802                // Restore the AST generation state
3803                genAST = savegenAST;
3804
3805                // restore char save state
3806                // saveText = oldsaveTest;
3807        }
3808        public void genRuleHeader(RuleSymbol s, boolean startSymbol) {
3809                tabs=1;
3810                if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genRuleHeader("+ s.getId() +")");
3811                if ( !s.isDefined() ) {
3812                        antlrTool.error("undefined rule: "+ s.getId());
3813                        return;
3814                }
3815
3816                // Generate rule return type, name, arguments
3817                RuleBlock rblk = s.getBlock();
3818                currentRule = rblk;
3819                currentASTResult = s.getId();
3820
3821                // Save the AST generation state, and set it to that of the rule
3822                boolean savegenAST = genAST;
3823                genAST = genAST && rblk.getAutoGen();
3824
3825                // boolean oldsaveTest = saveText;
3826                saveText = rblk.getAutoGen();
3827
3828                // Gen method access
3829                print(s.access + ": ");
3830
3831                // Gen method return type (note lexer return action set at rule creation)
3832                if (rblk.returnAction != null)
3833                {
3834                        // Has specified return value
3835                        _print(extractTypeOfAction(rblk.returnAction, rblk.getLine(), rblk.getColumn()) + " ");
3836                } else {
3837                        // No specified return value
3838                        _print("void ");
3839                }
3840
3841                // Gen method name
3842                _print(s.getId() + "(");
3843
3844                // Additional rule parameters common to all rules for this grammar
3845                _print(commonExtraParams);
3846                if (commonExtraParams.length() != 0 && rblk.argAction != null ) {
3847                        _print(",");
3848                }
3849
3850                // Gen arguments
3851                if (rblk.argAction != null)
3852                {
3853                        // Has specified arguments
3854                        _println("");
3855                        tabs++;
3856                        println(rblk.argAction);
3857                        tabs--;
3858                        print(")");
3859                } else {
3860                        // No specified arguments
3861                        _print(")");
3862                }
3863                _println(";");
3864
3865                tabs--;
3866
3867                // Restore the AST generation state
3868                genAST = savegenAST;
3869
3870                // restore char save state
3871                // saveText = oldsaveTest;
3872        }
3873        private void GenRuleInvocation(RuleRefElement rr) {
3874                // dump rule name
3875                _print(rr.targetRule + "(");
3876
3877                // lexers must tell rule if it should set _returnToken
3878                if ( grammar instanceof LexerGrammar ) {
3879                        // if labeled, could access Token, so tell rule to create
3880                        if ( rr.getLabel() != null ) {
3881                                _print("true");
3882                        }
3883                        else {
3884                                _print("false");
3885                        }
3886                        if (commonExtraArgs.length() != 0 || rr.args!=null ) {
3887                                _print(",");
3888                        }
3889                }
3890
3891                // Extra arguments common to all rules for this grammar
3892                _print(commonExtraArgs);
3893                if (commonExtraArgs.length() != 0 && rr.args!=null ) {
3894                        _print(",");
3895                }
3896
3897                // Process arguments to method, if any
3898                RuleSymbol rs = (RuleSymbol)grammar.getSymbol(rr.targetRule);
3899                if (rr.args != null)
3900                {
3901                        // When not guessing, execute user arg action
3902                        ActionTransInfo tInfo = new ActionTransInfo();
3903                        // FIXME: fix line number passed to processActionForTreeSpecifiers here..
3904                        // this one might be a bit off..
3905                        String args = processActionForSpecialSymbols(rr.args, rr.line,
3906                                                                                                                                                currentRule, tInfo);
3907                        if ( tInfo.assignToRoot || tInfo.refRuleRoot!=null )
3908                        {
3909                                antlrTool.error("Arguments of rule reference '" + rr.targetRule + "' cannot set or ref #"+
3910                                        currentRule.getRuleName()+" on line "+rr.getLine());
3911                        }
3912                        _print(args);
3913
3914                        // Warn if the rule accepts no arguments
3915                        if (rs.block.argAction == null)
3916                        {
3917                                antlrTool.warning("Rule '" + rr.targetRule + "' accepts no arguments",
3918                                        grammar.getFilename(),
3919                                        rr.getLine(), rr.getColumn());
3920                        }
3921                }
3922                else
3923                {
3924                        // For C++, no warning if rule has parameters, because there may be default
3925                        // values for all of the parameters
3926                        //if (rs.block.argAction != null) {
3927                        //      tool.warning("Missing parameters on reference to rule "+rr.targetRule, rr.getLine());
3928                        //}
3929                }
3930                _println(");");
3931
3932                // move down to the first child while parsing
3933                if ( grammar instanceof TreeWalkerGrammar ) {
3934                        println("_t = _retTree;");
3935                }
3936        }
3937        protected void genSemPred(String pred, int line) {
3938                // translate $ and # references
3939                ActionTransInfo tInfo = new ActionTransInfo();
3940                pred = processActionForSpecialSymbols(pred, line, currentRule, tInfo);
3941                // ignore translation info...we don't need to do anything with it.
3942                String escapedPred = charFormatter.escapeString(pred);
3943
3944                // if debugging, wrap the semantic predicate evaluation in a method
3945                // that can tell SemanticPredicateListeners the result
3946                if (grammar.debuggingOutput && ((grammar instanceof ParserGrammar) ||
3947                          (grammar instanceof LexerGrammar)))
3948                        pred = "fireSemanticPredicateEvaluated(antlr.debug.SemanticPredicateEvent.VALIDATING," //FIXME
3949                                + addSemPred(escapedPred) + "," + pred + ")";
3950                println("if (!(" + pred + "))");
3951                tabs++;
3952                println("throw "+namespaceAntlr+"SemanticException(\"" + escapedPred + "\");");
3953                tabs--;
3954        }
3955        /** Write an array of Strings which are the semantic predicate
3956         *  expressions.  The debugger will reference them by number only
3957         */
3958        protected void genSemPredMap(String prefix) {
3959                Enumeration e = semPreds.elements();
3960                println("const char* " + prefix + "_semPredNames[] = {");
3961                tabs++;
3962                while(e.hasMoreElements())
3963                        println("\""+e.nextElement()+"\",");
3964                println("0");
3965                tabs--;
3966                println("};");
3967        }
3968        protected void genSynPred(SynPredBlock blk, String lookaheadExpr) {
3969                if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("gen=>("+blk+")");
3970
3971                // Dump synpred result variable
3972                println("bool synPredMatched" + blk.ID + " = false;");
3973
3974                if( grammar instanceof TreeWalkerGrammar ) {
3975                        println("if (_t == "+labeledElementASTInit+" )");
3976                        tabs++;
3977                        println("_t = ASTNULL;");
3978                        tabs--;
3979                }
3980
3981                // Gen normal lookahead test
3982                println("if (" + lookaheadExpr + ") {");
3983                tabs++;
3984
3985                // Save input state
3986                if ( grammar instanceof TreeWalkerGrammar ) {
3987                        println(labeledElementType + " __t" + blk.ID + " = _t;");
3988                }
3989                else {
3990                        println("int _m" + blk.ID + " = mark();");
3991                }
3992
3993                // Once inside the try, assume synpred works unless exception caught
3994                println("synPredMatched" + blk.ID + " = true;");
3995                println("inputState->guessing++;");
3996
3997                // if debugging, tell listeners that a synpred has started
3998                if (grammar.debuggingOutput && ((grammar instanceof ParserGrammar) ||
3999                         (grammar instanceof LexerGrammar))) {
4000                        println("fireSyntacticPredicateStarted();");
4001                }
4002
4003                syntacticPredLevel++;
4004                println("try {");
4005                tabs++;
4006                gen((AlternativeBlock)blk);             // gen code to test predicate
4007                tabs--;
4008                //println("System.out.println(\"pred "+blk+" succeeded\");");
4009                println("}");
4010                println("catch (" + exceptionThrown + "& pe) {");
4011                tabs++;
4012                println("synPredMatched"+blk.ID+" = false;");
4013                //println("System.out.println(\"pred "+blk+" failed\");");
4014                tabs--;
4015                println("}");
4016
4017                // Restore input state
4018                if ( grammar instanceof TreeWalkerGrammar ) {
4019                        println("_t = __t"+blk.ID+";");
4020                }
4021                else {
4022                        println("rewind(_m"+blk.ID+");");
4023                }
4024
4025                println("inputState->guessing--;");
4026
4027                // if debugging, tell listeners how the synpred turned out
4028                if (grammar.debuggingOutput && ((grammar instanceof ParserGrammar) ||
4029                     (grammar instanceof LexerGrammar))) {
4030                        println("if (synPredMatched" + blk.ID +")");
4031                        println("  fireSyntacticPredicateSucceeded();");
4032                        println("else");
4033                        println("  fireSyntacticPredicateFailed();");
4034                }
4035
4036                syntacticPredLevel--;
4037                tabs--;
4038
4039                // Close lookahead test
4040                println("}");
4041
4042                // Test synpred result
4043                println("if ( synPredMatched"+blk.ID+" ) {");
4044        }
4045        /** Generate a static array containing the names of the tokens,
4046         * indexed by the token type values.  This static array is used
4047         * to format error messages so that the token identifers or literal
4048         * strings are displayed instead of the token numbers.
4049         *
4050         * If a lexical rule has a paraphrase, use it rather than the
4051         * token label.
4052         */
4053        public void genTokenStrings(String prefix) {
4054                // Generate a string for each token.  This creates a static
4055                // array of Strings indexed by token type.
4056//              println("");
4057                println("const char* " + prefix + "tokenNames[] = {");
4058                tabs++;
4059
4060                // Walk the token vocabulary and generate a Vector of strings
4061                // from the tokens.
4062                Vector v = grammar.tokenManager.getVocabulary();
4063                for (int i = 0; i < v.size(); i++)
4064                {
4065                        String s = (String)v.elementAt(i);
4066                        if (s == null)
4067                        {
4068                                s = "<"+String.valueOf(i)+">";
4069                        }
4070                        if ( !s.startsWith("\"") && !s.startsWith("<") ) {
4071                                TokenSymbol ts = (TokenSymbol)grammar.tokenManager.getTokenSymbol(s);
4072                                if ( ts!=null && ts.getParaphrase()!=null ) {
4073                                        s = StringUtils.stripFrontBack(ts.getParaphrase(), "\"", "\"");
4074                                }
4075                        }
4076                        print(charFormatter.literalString(s));
4077                        _println(",");
4078                }
4079                println("0");
4080
4081                // Close the string array initailizer
4082                tabs--;
4083                println("};");
4084        }
4085        /** Generate the token types C++ file */
4086        protected void genTokenTypes(TokenManager tm) throws IOException {
4087                // Open the token output header file and set the currentOutput stream
4088                outputFile = tm.getName() + TokenTypesFileSuffix+".hpp";
4089                outputLine = 1;
4090                currentOutput = antlrTool.openOutputFile(outputFile);
4091                //SAS: changed for proper text file io
4092
4093                tabs = 0;
4094
4095                // Generate a guard wrapper
4096                println("#ifndef INC_"+tm.getName()+TokenTypesFileSuffix+"_hpp_");
4097                println("#define INC_"+tm.getName()+TokenTypesFileSuffix+"_hpp_");
4098                println("");
4099
4100                if (nameSpace != null)
4101                        nameSpace.emitDeclarations(currentOutput);
4102
4103                // Generate the header common to all C++ files
4104                genHeader(outputFile);
4105
4106                // Encapsulate the definitions in an interface.  This can be done
4107                // because they are all constants.
4108                println("");
4109                println("#ifndef CUSTOM_API");
4110                println("# define CUSTOM_API");
4111                println("#endif");
4112                println("");
4113                // In the case that the .hpp is included from C source (flexLexer!)
4114                // we just turn things into a plain enum
4115                println("#ifdef __cplusplus");
4116                println("struct CUSTOM_API " + tm.getName() + TokenTypesFileSuffix+" {");
4117                println("#endif");
4118                tabs++;
4119                println("enum {");
4120                tabs++;
4121
4122                // Generate a definition for each token type
4123                Vector v = tm.getVocabulary();
4124
4125                // Do special tokens manually
4126                println("EOF_ = " + Token.EOF_TYPE + ",");
4127
4128                // Move the other special token to the end, so we can solve
4129                // the superfluous comma problem easily
4130
4131                for (int i = Token.MIN_USER_TYPE; i < v.size(); i++) {
4132                        String s = (String)v.elementAt(i);
4133                        if (s != null) {
4134                                if ( s.startsWith("\"") ) {
4135                                        // a string literal
4136                                        StringLiteralSymbol sl = (StringLiteralSymbol)tm.getTokenSymbol(s);
4137                                        if ( sl==null ) {
4138                                                antlrTool.panic("String literal "+s+" not in symbol table");
4139                                        }
4140                                        else if ( sl.label != null ) {
4141                                                println(sl.label + " = " + i + ",");
4142                                        }
4143                                        else {
4144                                                String mangledName = mangleLiteral(s);
4145                                                if (mangledName != null) {
4146                                                        // We were able to create a meaningful mangled token name
4147                                                        println(mangledName + " = " + i + ",");
4148                                                        // if no label specified, make the label equal to the mangled name
4149                                                        sl.label = mangledName;
4150                                                }
4151                                                else {
4152                                                        println("// " + s + " = " + i);
4153                                                }
4154                                        }
4155                                }
4156                                else if ( !s.startsWith("<") ) {
4157                                        println(s + " = " + i + ",");
4158                                }
4159                        }
4160                }
4161
4162                // Moved from above
4163                println("NULL_TREE_LOOKAHEAD = " + Token.NULL_TREE_LOOKAHEAD);
4164
4165                // Close the enum
4166                tabs--;
4167                println("};");
4168
4169                // Close the interface
4170                tabs--;
4171                println("#ifdef __cplusplus");
4172                println("};");
4173                println("#endif");
4174
4175                if (nameSpace != null)
4176                        nameSpace.emitClosures(currentOutput);
4177
4178                // Generate a guard wrapper
4179                println("#endif /*INC_"+tm.getName()+TokenTypesFileSuffix+"_hpp_*/");
4180
4181                // Close the tokens output file
4182                currentOutput.close();
4183                currentOutput = null;
4184                exitIfError();
4185        }
4186        /** Process a string for an simple expression for use in xx/action.g
4187         * it is used to cast simple tokens/references to the right type for
4188         * the generated language. Basically called for every element in
4189         * the vector to getASTCreateString(vector V)
4190         * @param str A String.
4191         */
4192        public String processStringForASTConstructor( String str )
4193        {
4194                if( usingCustomAST &&
4195                        ((grammar instanceof TreeWalkerGrammar) ||
4196                         (grammar instanceof ParserGrammar))  &&
4197                        !(grammar.tokenManager.tokenDefined(str) ) )
4198                {
4199//                      System.out.println("processStringForASTConstructor: "+str+" with cast");
4200                        return namespaceAntlr+"RefAST("+str+")";
4201                }
4202                else
4203                {
4204//                      System.out.println("processStringForASTConstructor: "+str);
4205                        return str;
4206                }
4207        }
4208        /** Get a string for an expression to generate creation of an AST subtree.
4209          * @param v A Vector of String, where each element is an expression
4210          * in the target language yielding an AST node.
4211          */
4212        public String getASTCreateString(Vector v) {
4213                if (v.size() == 0) {
4214                        return "";
4215                }
4216                StringBuffer buf = new StringBuffer();
4217                // the labeledElementASTType here can probably be a cast or nothing
4218                // in the case of ! usingCustomAST
4219                buf.append(labeledElementASTType+
4220                                        "(astFactory->make((new "+namespaceAntlr+
4221                                          "ASTArray("+v.size()+"))");
4222                for (int i = 0; i < v.size(); i++) {
4223                        buf.append("->add("+ v.elementAt(i) + ")");
4224                }
4225                buf.append("))");
4226                return buf.toString();
4227        }
4228        /** Get a string for an expression to generate creating of an AST node
4229         * @param str The arguments to the AST constructor
4230         */
4231        public String getASTCreateString(GrammarAtom atom, String str) {
4232                if ( atom!=null && atom.getASTNodeType() != null ) {
4233
4234                        // this atom is using a heterogeneous AST type. (and maybe a local
4235                        // override we can't see at the TokenManager level)
4236                        // make note of the factory needed to generate it..
4237                        // later this is inserted into the initializeFactory method.
4238                        astTypes.ensureCapacity(atom.getType());
4239                        String type = (String)astTypes.elementAt(atom.getType());
4240                        if( type == null )
4241                                astTypes.setElementAt(atom.getASTNodeType(),atom.getType());
4242                        else
4243                        {
4244                                // give a warning over action taken if the types are unequal
4245                                if( ! atom.getASTNodeType().equals(type) )
4246                                {
4247                                        antlrTool.warning("Attempt to redefine AST type for "+atom.getText(),grammar.getFilename(),atom.getLine(),atom.getColumn());
4248                                        antlrTool.warning(" from \""+type+"\" to \""+atom.getASTNodeType()+"\" sticking to \""+type+"\"",grammar.getFilename(),atom.getLine(),atom.getColumn());
4249                                }
4250                                else
4251                                        astTypes.setElementAt(atom.getASTNodeType(),atom.getType());
4252                        }
4253                        // after above init the factory knows what to generate...
4254                        return "astFactory->create("+str+")";
4255                }
4256                else
4257                {
4258                        // FIXME: This is *SO* ugly! but it will have to do for now...
4259                        // 2.7.2 will have better I hope
4260                        // this is due to the usage of getASTCreateString from inside
4261                        // actions/cpp/action.g
4262                        boolean is_constructor = false;
4263                        if( str.indexOf(',') != -1 )
4264                                is_constructor = grammar.tokenManager.tokenDefined(str.substring(0,str.indexOf(',')));
4265
4266//                      System.out.println("getAstCreateString(as): "+str+" "+grammar.tokenManager.tokenDefined(str));
4267                        if( usingCustomAST &&
4268                           (grammar instanceof TreeWalkerGrammar) &&
4269                                !(grammar.tokenManager.tokenDefined(str) ) &&
4270                                ! is_constructor )
4271                                return "astFactory->create("+namespaceAntlr+"RefAST("+str+"))";
4272                        else
4273                                return "astFactory->create("+str+")";
4274                }
4275        }
4276
4277        /** Get a string for an expression to generate creating of an AST node
4278         * @param str The arguments to the AST constructor
4279         */
4280        public String getASTCreateString(String str) {
4281//              System.out.println("getAstCreateString(str): "+str+" "+grammar.tokenManager.tokenDefined(str));
4282                if( usingCustomAST )
4283                        return labeledElementASTType+"(astFactory->create("+namespaceAntlr+"RefAST("+str+")))";
4284                else
4285                        return "astFactory->create("+str+")";
4286        }
4287
4288        protected String getLookaheadTestExpression(Lookahead[] look, int k) {
4289                StringBuffer e = new StringBuffer(100);
4290                boolean first = true;
4291
4292                e.append("(");
4293                for (int i = 1; i <= k; i++) {
4294                        BitSet p = look[i].fset;
4295                        if (!first) {
4296                                e.append(") && (");
4297                        }
4298                        first = false;
4299
4300                        // Syn preds can yield <end-of-syn-pred> (epsilon) lookahead.
4301                        // There is no way to predict what that token would be.  Just
4302                        // allow anything instead.
4303                        if (look[i].containsEpsilon()) {
4304                                e.append("true");
4305                        } else {
4306                                e.append(getLookaheadTestTerm(i, p));
4307                        }
4308                }
4309                e.append(")");
4310
4311                return e.toString();
4312        }
4313        /** Generate a lookahead test expression for an alternate.  This
4314         * will be a series of tests joined by '&&' and enclosed by '()',
4315         * the number of such tests being determined by the depth of the lookahead.
4316         */
4317        protected String getLookaheadTestExpression(Alternative alt, int maxDepth) {
4318                int depth = alt.lookaheadDepth;
4319                if ( depth == GrammarAnalyzer.NONDETERMINISTIC ) {
4320                        // if the decision is nondeterministic, do the best we can: LL(k)
4321                        // any predicates that are around will be generated later.
4322                        depth = grammar.maxk;
4323                }
4324
4325                if ( maxDepth==0 ) {
4326                        // empty lookahead can result from alt with sem pred
4327                        // that can see end of token.  E.g., A : {pred}? ('a')? ;
4328                        return "true";
4329                }
4330
4331/*
4332boolean first = true;
4333                for (int i=1; i<=depth && i<=maxDepth; i++) {
4334                        BitSet p = alt.cache[i].fset;
4335                        if (!first) {
4336                                e.append(") && (");
4337                        }
4338                        first = false;
4339
4340                        // Syn preds can yield <end-of-syn-pred> (epsilon) lookahead.
4341                        // There is no way to predict what that token would be.  Just
4342                        // allow anything instead.
4343                        if ( alt.cache[i].containsEpsilon() ) {
4344                                e.append("true");
4345                        }
4346                        else {
4347                                e.append(getLookaheadTestTerm(i, p));
4348                        }
4349                }
4350
4351                e.append(")");
4352*/
4353
4354                return "(" + getLookaheadTestExpression(alt.cache,depth) + ")";
4355        }
4356        /**Generate a depth==1 lookahead test expression given the BitSet.
4357         * This may be one of:
4358         * 1) a series of 'x==X||' tests
4359         * 2) a range test using >= && <= where possible,
4360         * 3) a bitset membership test for complex comparisons
4361         * @param k The lookahead level
4362         * @param p The lookahead set for level k
4363         */
4364        protected String getLookaheadTestTerm(int k, BitSet p) {
4365                // Determine the name of the item to be compared
4366                String ts = lookaheadString(k);
4367
4368                // Generate a range expression if possible
4369                int[] elems = p.toArray();
4370                if (elementsAreRange(elems)) {
4371                        return getRangeExpression(k, elems);
4372                }
4373
4374                // Generate a bitset membership test if possible
4375                StringBuffer e;
4376                int degree = p.degree();
4377                if ( degree == 0 ) {
4378                        return "true";
4379                }
4380
4381                if (degree >= bitsetTestThreshold) {
4382                        int bitsetIdx = markBitsetForGen(p);
4383                        return getBitsetName(bitsetIdx) + ".member(" + ts + ")";
4384                }
4385
4386                // Otherwise, generate the long-winded series of "x==X||" tests
4387                e = new StringBuffer();
4388                for (int i = 0; i < elems.length; i++) {
4389                        // Get the compared-to item (token or character value)
4390                        String cs = getValueString(elems[i]);
4391
4392                        // Generate the element comparison
4393                        if( i > 0 ) e.append(" || ");
4394                        e.append(ts);
4395                        e.append(" == ");
4396                        e.append(cs);
4397                }
4398                return e.toString();
4399        }
4400        /** Return an expression for testing a contiguous renage of elements
4401         * @param k The lookahead level
4402         * @param elems The elements representing the set, usually from BitSet.toArray().
4403         * @return String containing test expression.
4404         */
4405        public String getRangeExpression(int k, int[] elems) {
4406                if (!elementsAreRange(elems)) {
4407                        antlrTool.panic("getRangeExpression called with non-range");
4408                }
4409                int begin = elems[0];
4410                int end = elems[elems.length-1];
4411                return
4412                        "(" + lookaheadString(k) + " >= " + getValueString(begin) + " && " +
4413                          lookaheadString(k) + " <= " + getValueString(end) + ")";
4414        }
4415        /** getValueString: get a string representation of a token or char value
4416         * @param value The token or char value
4417         */
4418        private String getValueString(int value) {
4419                String cs;
4420                if ( grammar instanceof LexerGrammar ) {
4421                        cs = charFormatter.literalChar(value);
4422                }
4423                else
4424                {
4425                        TokenSymbol ts = grammar.tokenManager.getTokenSymbolAt(value);
4426                        if ( ts == null ) {
4427                                return ""+value; // return token type as string
4428                                // tool.panic("vocabulary for token type " + value + " is null");
4429                        }
4430                        String tId = ts.getId();
4431                        if ( ts instanceof StringLiteralSymbol ) {
4432                                // if string literal, use predefined label if any
4433                                // if no predefined, try to mangle into LITERAL_xxx.
4434                                // if can't mangle, use int value as last resort
4435                                StringLiteralSymbol sl = (StringLiteralSymbol)ts;
4436                                String label = sl.getLabel();
4437                                if ( label!=null ) {
4438                                        cs = label;
4439                                }
4440                                else {
4441                                        cs = mangleLiteral(tId);
4442                                        if (cs == null) {
4443                                                cs = String.valueOf(value);
4444                                        }
4445                                }
4446                        }
4447                        else {
4448                                if ( tId.equals("EOF") )
4449                                        cs = namespaceAntlr+"Token::EOF_TYPE";
4450                                else
4451                                        cs = tId;
4452                        }
4453                }
4454                return cs;
4455        }
4456        /**Is the lookahead for this alt empty? */
4457        protected boolean lookaheadIsEmpty(Alternative alt, int maxDepth) {
4458                int depth = alt.lookaheadDepth;
4459                if ( depth == GrammarAnalyzer.NONDETERMINISTIC ) {
4460                        depth = grammar.maxk;
4461                }
4462                for (int i=1; i<=depth && i<=maxDepth; i++) {
4463                        BitSet p = alt.cache[i].fset;
4464                        if (p.degree() != 0) {
4465                                return false;
4466                        }
4467                }
4468                return true;
4469        }
4470        private String lookaheadString(int k) {
4471                if (grammar instanceof TreeWalkerGrammar) {
4472                        return "_t->getType()";
4473                }
4474                return "LA(" + k + ")";
4475        }
4476        /** Mangle a string literal into a meaningful token name.  This is
4477          * only possible for literals that are all characters.  The resulting
4478          * mangled literal name is literalsPrefix with the text of the literal
4479          * appended.
4480          * @return A string representing the mangled literal, or null if not possible.
4481          */
4482        private String mangleLiteral(String s) {
4483                String mangled = antlrTool.literalsPrefix;
4484                for (int i = 1; i < s.length()-1; i++) {
4485                        if (!Character.isLetter(s.charAt(i)) &&
4486                                 s.charAt(i) != '_') {
4487                                return null;
4488                        }
4489                        mangled += s.charAt(i);
4490                }
4491                if ( antlrTool.upperCaseMangledLiterals ) {
4492                        mangled = mangled.toUpperCase();
4493                }
4494                return mangled;
4495        }
4496        /** Map an identifier to it's corresponding tree-node variable.
4497          * This is context-sensitive, depending on the rule and alternative
4498          * being generated
4499          * @param idParam The identifier name to map
4500          * @return The mapped id (which may be the same as the input), or null if the mapping is invalid due to duplicates
4501          */
4502        public String mapTreeId(String idParam, ActionTransInfo transInfo) {
4503                // if not in an action of a rule, nothing to map.
4504                if ( currentRule==null ) return idParam;
4505//              System.out.print("mapTreeId: "+idParam+" "+currentRule.getRuleName()+" ");
4506
4507                boolean in_var = false;
4508                String id = idParam;
4509                if (grammar instanceof TreeWalkerGrammar)
4510                {
4511//                      RK: hmmm this seems odd. If buildAST is false it translates
4512//                      #rulename_in to 'rulename_in' else to 'rulename_AST_in' which indeed
4513//                      exists. disabling for now.. and hope it doesn't blow up somewhere.
4514                        if ( !grammar.buildAST )
4515                        {
4516                                in_var = true;
4517//                              System.out.println("in_var1");
4518                        }
4519                        // If the id ends with "_in", then map it to the input variable
4520//                      else
4521                        if (id.length() > 3 && id.lastIndexOf("_in") == id.length()-3)
4522                        {
4523                                // Strip off the "_in"
4524                                id = id.substring(0, id.length()-3);
4525                                in_var = true;
4526//                              System.out.println("in_var2");
4527                        }
4528                }
4529//              System.out.print(in_var+"\t");
4530
4531                // Check the rule labels.  If id is a label, then the output
4532                // variable is label_AST, and the input variable is plain label.
4533                for (int i = 0; i < currentRule.labeledElements.size(); i++)
4534                {
4535                        AlternativeElement elt = (AlternativeElement)currentRule.labeledElements.elementAt(i);
4536                        if (elt.getLabel().equals(id))
4537                        {
4538//                              if( in_var )
4539//                                      System.out.println("returning (vec) "+(in_var ? id : id + "_AST"));
4540                                return in_var ? id : id + "_AST";
4541                        }
4542                }
4543
4544                // Failing that, check the id-to-variable map for the alternative.
4545                // If the id is in the map, then output variable is the name in the
4546                // map, and input variable is name_in
4547                String s = (String)treeVariableMap.get(id);
4548                if (s != null)
4549                {
4550                        if (s == NONUNIQUE)
4551                        {
4552//                              if( in_var )
4553//                                      System.out.println("returning null (nonunique)");
4554                                // There is more than one element with this id
4555                                antlrTool.error("Ambiguous reference to AST element "+id+
4556                                                                " in rule "+currentRule.getRuleName());
4557                                return null;
4558                        }
4559                        else if (s.equals(currentRule.getRuleName()))
4560                        {
4561                                // a recursive call to the enclosing rule is
4562                                // ambiguous with the rule itself.
4563//                              if( in_var )
4564//                                      System.out.println("returning null (rulename)");
4565                                antlrTool.error("Ambiguous reference to AST element "+id+
4566                                                                " in rule "+currentRule.getRuleName());
4567                                return null;
4568                        }
4569                        else
4570                        {
4571//                              if( in_var )
4572//                              System.out.println("returning "+(in_var?s+"_in":s));
4573                                return in_var ? s + "_in" : s;
4574                        }
4575                }
4576
4577//              System.out.println("Last check: "+id+" == "+currentRule.getRuleName());
4578                // Failing that, check the rule name itself.  Output variable
4579                // is rule_AST; input variable is rule_AST_in (treeparsers).
4580                if( id.equals(currentRule.getRuleName()) )
4581                {
4582                        String r = in_var ? id + "_AST_in" : id + "_AST";
4583                        if ( transInfo!=null ) {
4584                                if ( !in_var ) {
4585                                        transInfo.refRuleRoot = r;
4586                                }
4587                        }
4588//                      if( in_var )
4589//                              System.out.println("returning (r) "+r);
4590                        return r;
4591                }
4592                else
4593                {
4594//                      if( in_var )
4595//                      System.out.println("returning (last) "+id);
4596                        // id does not map to anything -- return itself.
4597                        return id;
4598                }
4599        }
4600        /** Given an element and the name of an associated AST variable,
4601          * create a mapping between the element "name" and the variable name.
4602          */
4603        private void mapTreeVariable(AlternativeElement e, String name)
4604        {
4605                // For tree elements, defer to the root
4606                if (e instanceof TreeElement) {
4607                        mapTreeVariable( ((TreeElement)e).root, name);
4608                        return;
4609                }
4610
4611                // Determine the name of the element, if any, for mapping purposes
4612                String elName = null;
4613
4614                // Don't map labeled items
4615                if (e.getLabel() == null) {
4616                        if (e instanceof TokenRefElement) {
4617                                // use the token id
4618                                elName = ((TokenRefElement)e).atomText;
4619                        }
4620                        else if (e instanceof RuleRefElement) {
4621                                // use the rule name
4622                                elName = ((RuleRefElement)e).targetRule;
4623                        }
4624                }
4625                // Add the element to the tree variable map if it has a name
4626                if (elName != null) {
4627                        if (treeVariableMap.get(elName) != null) {
4628                                // Name is already in the map -- mark it as duplicate
4629                                treeVariableMap.remove(elName);
4630                                treeVariableMap.put(elName, NONUNIQUE);
4631                        }
4632                        else {
4633                                treeVariableMap.put(elName, name);
4634                        }
4635                }
4636        }
4637
4638        /** Lexically process tree-specifiers in the action.
4639         * This will replace #id and #(...) with the appropriate
4640         * function calls and/or variables.
4641         */
4642        protected String processActionForSpecialSymbols(String actionStr,
4643                                                                                                                                        int line,
4644                                                                                                                                        RuleBlock currentRule,
4645                                                                                                                                        ActionTransInfo tInfo)
4646        {
4647                if ( actionStr==null || actionStr.length()==0 )
4648                        return null;
4649
4650                // The action trans info tells us (at the moment) whether an
4651                // assignment was done to the rule's tree root.
4652                if (grammar==null)
4653                        return actionStr;
4654
4655                if ((grammar.buildAST && actionStr.indexOf('#') != -1) ||
4656                         grammar instanceof TreeWalkerGrammar ||
4657                         ((grammar instanceof LexerGrammar ||
4658                                grammar instanceof ParserGrammar)
4659                                && actionStr.indexOf('$') != -1) )
4660                {
4661                        // Create a lexer to read an action and return the translated version
4662                        antlr.actions.cpp.ActionLexer lexer =
4663                                new antlr.actions.cpp.ActionLexer(actionStr, currentRule, this, tInfo);
4664                        lexer.setLineOffset(line);
4665                        lexer.setFilename(grammar.getFilename());
4666                        lexer.setTool(antlrTool);
4667
4668                        try {
4669                                lexer.mACTION(true);
4670                                actionStr = lexer.getTokenObject().getText();
4671                                // System.out.println("action translated: "+actionStr);
4672                                // System.out.println("trans info is "+tInfo);
4673                        }
4674                        catch (RecognitionException ex) {
4675                                lexer.reportError(ex);
4676                                return actionStr;
4677                        }
4678                        catch (TokenStreamException tex) {
4679                                antlrTool.panic("Error reading action:"+actionStr);
4680                                return actionStr;
4681                        }
4682                        catch (CharStreamException io) {
4683                                antlrTool.panic("Error reading action:"+actionStr);
4684                                return actionStr;
4685                        }
4686                }
4687                return actionStr;
4688        }
4689
4690        private String fixNameSpaceOption( String ns )
4691        {
4692                ns = StringUtils.stripFrontBack(ns,"\"","\"");
4693                if( ns.length() > 2 &&
4694                         !ns.substring(ns.length()-2, ns.length()).equals("::") )
4695                ns += "::";
4696                return ns;
4697        }
4698
4699        private void setupGrammarParameters(Grammar g) {
4700                if (g instanceof ParserGrammar ||
4701                         g instanceof LexerGrammar  ||
4702                         g instanceof TreeWalkerGrammar
4703                        )
4704                {
4705                        /* RK: options also have to be added to Grammar.java and for options
4706                         * on the file level entries have to be defined in
4707                         * DefineGrammarSymbols.java and passed around via 'globals' in
4708                         * antlrTool.java
4709                         */
4710                        if( antlrTool.nameSpace != null )
4711                                nameSpace = antlrTool.nameSpace;
4712
4713                        if( antlrTool.namespaceStd != null )
4714                                namespaceStd = fixNameSpaceOption(antlrTool.namespaceStd);
4715
4716                        if( antlrTool.namespaceAntlr != null )
4717                                namespaceAntlr = fixNameSpaceOption(antlrTool.namespaceAntlr);
4718
4719                        genHashLines = antlrTool.genHashLines;
4720
4721                        /* let grammar level options override filelevel ones...
4722                         */
4723                        if( g.hasOption("namespace") ) {
4724                                Token t = g.getOption("namespace");
4725                                if( t != null ) {
4726                                        nameSpace = new NameSpace(t.getText());
4727                                }
4728                        }
4729                        if( g.hasOption("namespaceAntlr") ) {
4730                                Token t = g.getOption("namespaceAntlr");
4731                                if( t != null ) {
4732                                        String ns = StringUtils.stripFrontBack(t.getText(),"\"","\"");
4733                                        if ( ns != null ) {
4734                                                if( ns.length() > 2 &&
4735                                                         !ns.substring(ns.length()-2, ns.length()).equals("::") )
4736                                                        ns += "::";
4737                                                namespaceAntlr = ns;
4738                                        }
4739                                }
4740                        }
4741                        if( g.hasOption("namespaceStd") ) {
4742                                Token t = g.getOption("namespaceStd");
4743                                if( t != null ) {
4744                                        String ns = StringUtils.stripFrontBack(t.getText(),"\"","\"");
4745                                        if ( ns != null ) {
4746                                                if( ns.length() > 2 &&
4747                                                         !ns.substring(ns.length()-2, ns.length()).equals("::") )
4748                                                        ns += "::";
4749                                                namespaceStd = ns;
4750                                        }
4751                                }
4752                        }
4753                        if( g.hasOption("genHashLines") ) {
4754                                Token t = g.getOption("genHashLines");
4755                                if( t != null ) {
4756                                        String val = StringUtils.stripFrontBack(t.getText(),"\"","\"");
4757                                        genHashLines = val.equals("true");
4758                                }
4759                        }
4760                        noConstructors = antlrTool.noConstructors;      // get the default
4761                        if( g.hasOption("noConstructors") ) {
4762                                Token t = g.getOption("noConstructors");
4763                                if( (t != null) && !(t.getText().equals("true") || t.getText().equals("false")))
4764                                        antlrTool.error("noConstructors option must be true or false", antlrTool.getGrammarFile(), t.getLine(), t.getColumn());
4765                                noConstructors = t.getText().equals("true");
4766                        }
4767                }
4768                if (g instanceof ParserGrammar) {
4769                        labeledElementASTType = namespaceAntlr+"RefAST";
4770                        labeledElementASTInit = namespaceAntlr+"nullAST";
4771                        if ( g.hasOption("ASTLabelType") ) {
4772                                Token tsuffix = g.getOption("ASTLabelType");
4773                                if ( tsuffix != null ) {
4774                                        String suffix = StringUtils.stripFrontBack(tsuffix.getText(),"\"","\"");
4775                                        if ( suffix != null ) {
4776                                                usingCustomAST = true;
4777                                                labeledElementASTType = suffix;
4778                                                labeledElementASTInit = suffix+"("+namespaceAntlr+"nullAST)";
4779                                        }
4780                                }
4781                        }
4782                        labeledElementType = namespaceAntlr+"RefToken ";
4783                        labeledElementInit = namespaceAntlr+"nullToken";
4784                        commonExtraArgs = "";
4785                        commonExtraParams = "";
4786                        commonLocalVars = "";
4787                        lt1Value = "LT(1)";
4788                        exceptionThrown = namespaceAntlr+"RecognitionException";
4789                        throwNoViable = "throw "+namespaceAntlr+"NoViableAltException(LT(1), getFilename());";
4790                }
4791                else if (g instanceof LexerGrammar) {
4792                        labeledElementType = "char ";
4793                        labeledElementInit = "'\\0'";
4794                        commonExtraArgs = "";
4795                        commonExtraParams = "bool _createToken";
4796                        commonLocalVars = "int _ttype; "+namespaceAntlr+"RefToken _token; "+namespaceStd+"string::size_type _begin = text.length();";
4797                        lt1Value = "LA(1)";
4798                        exceptionThrown = namespaceAntlr+"RecognitionException";
4799                        throwNoViable = "throw "+namespaceAntlr+"NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());";
4800                }
4801                else if (g instanceof TreeWalkerGrammar) {
4802                        labeledElementInit = namespaceAntlr+"nullAST";
4803                        labeledElementASTInit = namespaceAntlr+"nullAST";
4804                        labeledElementASTType = namespaceAntlr+"RefAST";
4805                        labeledElementType = namespaceAntlr+"RefAST";
4806                        commonExtraParams = namespaceAntlr+"RefAST _t";
4807                        throwNoViable = "throw "+namespaceAntlr+"NoViableAltException(_t);";
4808                        lt1Value = "_t";
4809                        if ( g.hasOption("ASTLabelType") ) {
4810                                Token tsuffix = g.getOption("ASTLabelType");
4811                                if ( tsuffix != null ) {
4812                                        String suffix = StringUtils.stripFrontBack(tsuffix.getText(),"\"","\"");
4813                                        if ( suffix != null ) {
4814                                                usingCustomAST = true;
4815                                                labeledElementASTType = suffix;
4816                                                labeledElementType = suffix;
4817                                                labeledElementInit = suffix+"("+namespaceAntlr+"nullAST)";
4818                                                labeledElementASTInit = labeledElementInit;
4819                                                commonExtraParams = suffix+" _t";
4820                                                throwNoViable = "throw "+namespaceAntlr+"NoViableAltException("+namespaceAntlr+"RefAST(_t));";
4821                                                lt1Value = "_t";
4822                                        }
4823                                }
4824                        }
4825                        if ( !g.hasOption("ASTLabelType") ) {
4826                                g.setOption("ASTLabelType", new Token(ANTLRTokenTypes.STRING_LITERAL,namespaceAntlr+"RefAST"));
4827                        }
4828                        commonExtraArgs = "_t";
4829                        commonLocalVars = "";
4830                        exceptionThrown = namespaceAntlr+"RecognitionException";
4831                }
4832                else {
4833                        antlrTool.panic("Unknown grammar type");
4834                }
4835        }
4836}
Note: See TracBrowser for help on using the repository browser.