Source Code Cross Referenced for CppCodeGenerator.java in  » Database-ORM » toplink » persistence » antlr » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database ORM » toplink » persistence.antlr 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package persistence.antlr;
0002:
0003:        /* ANTLR Translator Generator
0004:         * Project led by Terence Parr at http://www.jGuru.com
0005:         * Software rights: http://www.antlr.org/license.html
0006:         *
0007:         */
0008:
0009:        // C++ code generator by Pete Wells: pete@yamuna.demon.co.uk
0010:        // #line generation contributed by: Ric Klaren <klaren@cs.utwente.nl>
0011:        import java.util.Enumeration;
0012:        import java.util.Hashtable;
0013:        import persistence.antlr.collections.impl.BitSet;
0014:        import persistence.antlr.collections.impl.Vector;
0015:        import java.io.PrintWriter; //SAS: changed for proper text file io
0016:        import java.io.IOException;
0017:        import java.io.FileWriter;
0018:
0019:        /** Generate MyParser.cpp, MyParser.hpp, MyLexer.cpp, MyLexer.hpp
0020:         * and MyParserTokenTypes.hpp
0021:         */
0022:        public class CppCodeGenerator extends CodeGenerator {
0023:            boolean DEBUG_CPP_CODE_GENERATOR = false;
0024:            // non-zero if inside syntactic predicate generation
0025:            protected int syntacticPredLevel = 0;
0026:
0027:            // Are we generating ASTs (for parsers and tree parsers) right now?
0028:            protected boolean genAST = false;
0029:
0030:            // Are we saving the text consumed (for lexers) right now?
0031:            protected boolean saveText = false;
0032:
0033:            // Generate #line's
0034:            protected boolean genHashLines = true;
0035:            // Generate constructors or not
0036:            protected boolean noConstructors = false;
0037:
0038:            // Used to keep track of lineno in output
0039:            protected int outputLine;
0040:            protected String outputFile;
0041:
0042:            // Grammar parameters set up to handle different grammar classes.
0043:            // These are used to get instanceof tests out of code generation
0044:            boolean usingCustomAST = false;
0045:            String labeledElementType;
0046:            String labeledElementASTType; // mostly the same as labeledElementType except in parsers
0047:            String labeledElementASTInit;
0048:            String labeledElementInit;
0049:            String commonExtraArgs;
0050:            String commonExtraParams;
0051:            String commonLocalVars;
0052:            String lt1Value;
0053:            String exceptionThrown;
0054:            String throwNoViable;
0055:
0056:            // Tracks the rule being generated.  Used for mapTreeId
0057:            RuleBlock currentRule;
0058:            // Tracks the rule or labeled subrule being generated.  Used for AST generation.
0059:            String currentASTResult;
0060:            // Mapping between the ids used in the current alt, and the
0061:            // names of variables used to represent their AST values.
0062:            Hashtable treeVariableMap = new Hashtable();
0063:
0064:            /** Used to keep track of which AST variables have been defined in a rule
0065:             * (except for the #rule_name and #rule_name_in var's
0066:             */
0067:            Hashtable declaredASTVariables = new Hashtable();
0068:
0069:            // Count of unnamed generated variables
0070:            int astVarNumber = 1;
0071:            // Special value used to mark duplicate in treeVariableMap
0072:            protected static final String NONUNIQUE = new String();
0073:
0074:            public static final int caseSizeThreshold = 127; // ascii is max
0075:
0076:            private Vector semPreds;
0077:
0078:            // Used to keep track of which (heterogeneous AST types are used)
0079:            // which need to be set in the ASTFactory of the generated parser
0080:            private Vector astTypes;
0081:
0082:            private static String namespaceStd = "ANTLR_USE_NAMESPACE(std)";
0083:            private static String namespaceAntlr = "ANTLR_USE_NAMESPACE(antlr)";
0084:            private static NameSpace nameSpace = null;
0085:
0086:            private static final String preIncludeCpp = "pre_include_cpp";
0087:            private static final String preIncludeHpp = "pre_include_hpp";
0088:            private static final String postIncludeCpp = "post_include_cpp";
0089:            private static final String postIncludeHpp = "post_include_hpp";
0090:
0091:            /** Create a C++ code-generator using the given Grammar.
0092:             * The caller must still call setTool, setBehavior, and setAnalyzer
0093:             * before generating code.
0094:             */
0095:            public CppCodeGenerator() {
0096:                super ();
0097:                charFormatter = new CppCharFormatter();
0098:            }
0099:
0100:            /** Adds a semantic predicate string to the sem pred vector
0101:                These strings will be used to build an array of sem pred names
0102:                when building a debugging parser.  This method should only be
0103:                called when the debug option is specified
0104:             */
0105:            protected int addSemPred(String predicate) {
0106:                semPreds.appendElement(predicate);
0107:                return semPreds.size() - 1;
0108:            }
0109:
0110:            public void exitIfError() {
0111:                if (antlrTool.hasError()) {
0112:                    antlrTool.fatalError("Exiting due to errors.");
0113:                }
0114:            }
0115:
0116:            protected int countLines(String s) {
0117:                int lines = 0;
0118:                for (int i = 0; i < s.length(); i++) {
0119:                    if (s.charAt(i) == '\n')
0120:                        lines++;
0121:                }
0122:                return lines;
0123:            }
0124:
0125:            /** Output a String to the currentOutput stream.
0126:             * Ignored if string is null.
0127:             * @param s The string to output
0128:             */
0129:            protected void _print(String s) {
0130:                if (s != null) {
0131:                    outputLine += countLines(s);
0132:                    currentOutput.print(s);
0133:                }
0134:            }
0135:
0136:            /** Print an action without leading tabs, attempting to
0137:             * preserve the current indentation level for multi-line actions
0138:             * Ignored if string is null.
0139:             * @param s The action string to output
0140:             */
0141:            protected void _printAction(String s) {
0142:                if (s != null) {
0143:                    outputLine += countLines(s) + 1;
0144:                    super ._printAction(s);
0145:                }
0146:            }
0147:
0148:            /** Print an action stored in a token surrounded by #line stuff */
0149:            public void printAction(Token t) {
0150:                if (t != null) {
0151:                    genLineNo(t.getLine());
0152:                    printTabs();
0153:                    _printAction(processActionForSpecialSymbols(t.getText(), t
0154:                            .getLine(), null, null));
0155:                    genLineNo2();
0156:                }
0157:            }
0158:
0159:            /** Print a header action by #line stuff also process any tree construction
0160:             * @param name The name of the header part
0161:             */
0162:            public void printHeaderAction(String name) {
0163:                Token a = (persistence.antlr.Token) behavior.headerActions
0164:                        .get(name);
0165:                if (a != null) {
0166:                    genLineNo(a.getLine());
0167:                    println(processActionForSpecialSymbols(a.getText(), a
0168:                            .getLine(), null, null));
0169:                    genLineNo2();
0170:                }
0171:            }
0172:
0173:            /** Output a String followed by newline, to the currentOutput stream.
0174:             * Ignored if string is null.
0175:             * @param s The string to output
0176:             */
0177:            protected void _println(String s) {
0178:                if (s != null) {
0179:                    outputLine += countLines(s) + 1;
0180:                    currentOutput.println(s);
0181:                }
0182:            }
0183:
0184:            /** Output tab indent followed by a String followed by newline,
0185:             * to the currentOutput stream.  Ignored if string is null.
0186:             * @param s The string to output
0187:             */
0188:            protected void println(String s) {
0189:                if (s != null) {
0190:                    printTabs();
0191:                    outputLine += countLines(s) + 1;
0192:                    currentOutput.println(s);
0193:                }
0194:            }
0195:
0196:            /** Generate a #line or // line depending on options */
0197:            public void genLineNo(int line) {
0198:                if (line == 0) {
0199:                    line++;
0200:                }
0201:                if (genHashLines)
0202:                    _println("#line " + line + " \""
0203:                            + antlrTool.fileMinusPath(antlrTool.grammarFile)
0204:                            + "\"");
0205:            }
0206:
0207:            /** Generate a #line or // line depending on options */
0208:            public void genLineNo(GrammarElement el) {
0209:                if (el != null)
0210:                    genLineNo(el.getLine());
0211:            }
0212:
0213:            /** Generate a #line or // line depending on options */
0214:            public void genLineNo(Token t) {
0215:                if (t != null)
0216:                    genLineNo(t.getLine());
0217:            }
0218:
0219:            /** Generate a #line or // line depending on options */
0220:            public void genLineNo2() {
0221:                if (genHashLines) {
0222:                    _println("#line " + (outputLine + 1) + " \"" + outputFile
0223:                            + "\"");
0224:                }
0225:            }
0226:
0227:            /** Sanitize a string coming from antlr's lexer to something that's ok
0228:             * Also bomb out on multibyte char attempts.
0229:             * The bombing out on mb char's is a bit crude but alas.
0230:             */
0231:            private String convertJavaToCppString(String s) {
0232:                String ret = new String();
0233:
0234:                int i = 0;
0235:                int val;
0236:                while (i < s.length()) {
0237:                    if (s.charAt(i) == '\\') {
0238:                        // deal with escaped junk
0239:                        switch (s.charAt(i + 1)) {
0240:                        case 'b':
0241:                        case 'r':
0242:                        case 't':
0243:                        case 'n':
0244:                        case 'f':
0245:                        case '"':
0246:                        case '\'':
0247:                        case '\\':
0248:                            ret += "\\" + s.charAt(i + 1);
0249:                            i += 2;
0250:                            continue;
0251:
0252:                        case 'u':
0253:                            // Unicode char \u1234
0254:                            val = Character.digit(s.charAt(i + 2), 16) * 16
0255:                                    * 16 * 16
0256:                                    + Character.digit(s.charAt(i + 3), 16) * 16
0257:                                    * 16 + Character.digit(s.charAt(i + 4), 16)
0258:                                    * 16 + Character.digit(s.charAt(i + 5), 16);
0259:                            i += 6;
0260:                            break;
0261:
0262:                        case '0': // \123
0263:                        case '1':
0264:                        case '2':
0265:                        case '3':
0266:                            if (Character.isDigit(s.charAt(i + 2))) {
0267:                                if (Character.isDigit(s.charAt(i + 3))) {
0268:                                    val = (s.charAt(i + 1) - '0') * 8 * 8
0269:                                            + (s.charAt(i + 2) - '0') * 8
0270:                                            + (s.charAt(i + 3) - '0');
0271:                                    i += 4;
0272:                                } else {
0273:                                    val = (s.charAt(i + 1) - '0') * 8
0274:                                            + (s.charAt(i + 2) - '0');
0275:                                    i += 3;
0276:                                }
0277:                            } else {
0278:                                val = s.charAt(i + 1) - '0';
0279:                                i += 2;
0280:                            }
0281:                            break;
0282:
0283:                        case '4':
0284:                        case '5':
0285:                        case '6':
0286:                        case '7':
0287:                            if (Character.isDigit(s.charAt(i + 2))) {
0288:                                val = (s.charAt(i + 1) - '0') * 8
0289:                                        + (s.charAt(i + 2) - '0');
0290:                                i += 3;
0291:                            } else {
0292:                                val = s.charAt(i + 1) - '0';
0293:                                i += 2;
0294:                            }
0295:                        default:
0296:                            antlrTool
0297:                                    .error("Unhandled escape in string constant: '"
0298:                                            + s + "'");
0299:                            val = 0;
0300:                        }
0301:                        if (val >= ' ' && val <= 126) // just concat if printable
0302:                            ret += (char) val;
0303:                        else if (val > 255) // abort if multibyte
0304:                            antlrTool
0305:                                    .error("Multibyte character found in string constant: '"
0306:                                            + s + "'");
0307:                        else
0308:                            ret += charFormatter.escapeChar(val, true);
0309:                    } else if (s.charAt(i) >= ' ' && s.charAt(i) <= 126)
0310:                        ret += s.charAt(i++);
0311:                    else
0312:                        ret += charFormatter.escapeChar(s.charAt(i++), true);
0313:                }
0314:                // System.out.println("convertJavaToCppString: "+s+" -> "+ret);
0315:                return ret;
0316:            }
0317:
0318:            /** Generate the parser, lexer, treeparser, and token types in C++
0319:             */
0320:            public void gen() {
0321:                // Do the code generation
0322:                try {
0323:                    // Loop over all grammars
0324:                    Enumeration grammarIter = behavior.grammars.elements();
0325:                    while (grammarIter.hasMoreElements()) {
0326:                        Grammar g = (Grammar) grammarIter.nextElement();
0327:                        if (g.debuggingOutput) {
0328:                            antlrTool.error(g.getFilename()
0329:                                    + ": C++ mode does not support -debug");
0330:                        }
0331:                        // Connect all the components to each other
0332:                        g.setGrammarAnalyzer(analyzer);
0333:                        g.setCodeGenerator(this );
0334:                        analyzer.setGrammar(g);
0335:                        // To get right overloading behavior across hetrogeneous grammars
0336:                        setupGrammarParameters(g);
0337:                        g.generate();
0338:                        exitIfError();
0339:                    }
0340:
0341:                    // Loop over all token managers (some of which are lexers)
0342:                    Enumeration tmIter = behavior.tokenManagers.elements();
0343:                    while (tmIter.hasMoreElements()) {
0344:                        TokenManager tm = (TokenManager) tmIter.nextElement();
0345:                        if (!tm.isReadOnly()) {
0346:                            // Write the token manager tokens as C++
0347:                            // this must appear before genTokenInterchange so that
0348:                            // labels are set on string literals
0349:                            genTokenTypes(tm);
0350:                            // Write the token manager tokens as plain text
0351:                            genTokenInterchange(tm);
0352:                        }
0353:                        exitIfError();
0354:                    }
0355:                } catch (IOException e) {
0356:                    antlrTool.reportException(e, null);
0357:                }
0358:            }
0359:
0360:            /** Generate code for the given grammar element.
0361:             * @param blk The {...} action to generate
0362:             */
0363:            public void gen(ActionElement action) {
0364:                if (DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR)
0365:                    System.out.println("genAction(" + action + ")");
0366:                if (action.isSemPred) {
0367:                    genSemPred(action.actionText, action.line);
0368:                } else {
0369:                    if (grammar.hasSyntacticPredicate) {
0370:                        println("if ( inputState->guessing==0 ) {");
0371:                        tabs++;
0372:                    }
0373:
0374:                    ActionTransInfo tInfo = new ActionTransInfo();
0375:                    String actionStr = processActionForSpecialSymbols(
0376:                            action.actionText, action.getLine(), currentRule,
0377:                            tInfo);
0378:
0379:                    if (tInfo.refRuleRoot != null) {
0380:                        // Somebody referenced "#rule", make sure translated var is valid
0381:                        // assignment to #rule is left as a ref also, meaning that assignments
0382:                        // with no other refs like "#rule = foo();" still forces this code to be
0383:                        // generated (unnecessarily).
0384:                        println(tInfo.refRuleRoot + " = "
0385:                                + labeledElementASTType + "(currentAST.root);");
0386:                    }
0387:
0388:                    // dump the translated action
0389:                    genLineNo(action);
0390:                    printAction(actionStr);
0391:                    genLineNo2();
0392:
0393:                    if (tInfo.assignToRoot) {
0394:                        // Somebody did a "#rule=", reset internal currentAST.root
0395:                        println("currentAST.root = " + tInfo.refRuleRoot + ";");
0396:                        // reset the child pointer too to be last sibling in sibling list
0397:                        // now use if else in stead of x ? y : z to shut CC 4.2 up.
0398:                        println("if ( " + tInfo.refRuleRoot + "!="
0399:                                + labeledElementASTInit + " &&");
0400:                        tabs++;
0401:                        println(tInfo.refRuleRoot + "->getFirstChild() != "
0402:                                + labeledElementASTInit + " )");
0403:                        println("  currentAST.child = " + tInfo.refRuleRoot
0404:                                + "->getFirstChild();");
0405:                        tabs--;
0406:                        println("else");
0407:                        tabs++;
0408:                        println("currentAST.child = " + tInfo.refRuleRoot + ";");
0409:                        tabs--;
0410:                        println("currentAST.advanceChildToEnd();");
0411:                    }
0412:
0413:                    if (grammar.hasSyntacticPredicate) {
0414:                        tabs--;
0415:                        println("}");
0416:                    }
0417:                }
0418:            }
0419:
0420:            /** Generate code for the given grammar element.
0421:             * @param blk The "x|y|z|..." block to generate
0422:             */
0423:            public void gen(AlternativeBlock blk) {
0424:                if (DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR)
0425:                    System.out.println("gen(" + blk + ")");
0426:                println("{");
0427:                genBlockPreamble(blk);
0428:                genBlockInitAction(blk);
0429:
0430:                // Tell AST generation to build subrule result
0431:                String saveCurrentASTResult = currentASTResult;
0432:                if (blk.getLabel() != null) {
0433:                    currentASTResult = blk.getLabel();
0434:                }
0435:
0436:                boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
0437:
0438:                CppBlockFinishingInfo howToFinish = genCommonBlock(blk, true);
0439:                genBlockFinish(howToFinish, throwNoViable);
0440:
0441:                println("}");
0442:
0443:                // Restore previous AST generation
0444:                currentASTResult = saveCurrentASTResult;
0445:            }
0446:
0447:            /** Generate code for the given grammar element.
0448:             * @param blk The block-end element to generate.  Block-end
0449:             * elements are synthesized by the grammar parser to represent
0450:             * the end of a block.
0451:             */
0452:            public void gen(BlockEndElement end) {
0453:                if (DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR)
0454:                    System.out.println("genRuleEnd(" + end + ")");
0455:            }
0456:
0457:            /** Generate code for the given grammar element.
0458:             * @param blk The character literal reference to generate
0459:             */
0460:            public void gen(CharLiteralElement atom) {
0461:                if (DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR)
0462:                    System.out.println("genChar(" + atom + ")");
0463:
0464:                if (atom.getLabel() != null) {
0465:                    println(atom.getLabel() + " = " + lt1Value + ";");
0466:                }
0467:
0468:                boolean oldsaveText = saveText;
0469:                saveText = saveText
0470:                        && atom.getAutoGenType() == GrammarElement.AUTO_GEN_NONE;
0471:                genMatch(atom);
0472:                saveText = oldsaveText;
0473:            }
0474:
0475:            /** Generate code for the given grammar element.
0476:             * @param blk The character-range reference to generate
0477:             */
0478:            public void gen(CharRangeElement r) {
0479:                if (DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR)
0480:                    System.out.println("genCharRangeElement(" + r.beginText
0481:                            + ".." + r.endText + ")");
0482:
0483:                if (r.getLabel() != null && syntacticPredLevel == 0) {
0484:                    println(r.getLabel() + " = " + lt1Value + ";");
0485:                }
0486:                // Correctly take care of saveIndex stuff...
0487:                boolean save = (grammar instanceof  LexerGrammar && (!saveText || r
0488:                        .getAutoGenType() == GrammarElement.AUTO_GEN_BANG));
0489:                if (save)
0490:                    println("_saveIndex=text.length();");
0491:
0492:                if (grammar instanceof  LexerGrammar)
0493:                    println("matchRange(" + convertJavaToCppString(r.beginText)
0494:                            + "," + convertJavaToCppString(r.endText) + ");");
0495:                else
0496:                    println("matchRange(" + r.beginText + "," + r.endText
0497:                            + ");");
0498:
0499:                if (save)
0500:                    println("text.setLength(_saveIndex);");
0501:            }
0502:
0503:            /** Generate the lexer C++ files */
0504:            public void gen(LexerGrammar g) throws IOException {
0505:                // If debugging, create a new sempred vector for this grammar
0506:                if (g.debuggingOutput)
0507:                    semPreds = new Vector();
0508:
0509:                if (g.charVocabulary.size() > 256)
0510:                    antlrTool
0511:                            .warning(g.getFilename()
0512:                                    + ": C++ mode does not support more than 8 bit characters (vocabulary size now: "
0513:                                    + g.charVocabulary.size() + ")");
0514:
0515:                setGrammar(g);
0516:                if (!(grammar instanceof  LexerGrammar)) {
0517:                    antlrTool.panic("Internal error generating lexer");
0518:                }
0519:
0520:                genBody(g);
0521:                genInclude(g);
0522:            }
0523:
0524:            /** Generate code for the given grammar element.
0525:             * @param blk The (...)+ block to generate
0526:             */
0527:            public void gen(OneOrMoreBlock blk) {
0528:                if (DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR)
0529:                    System.out.println("gen+(" + blk + ")");
0530:                String label;
0531:                String cnt;
0532:                println("{ // ( ... )+");
0533:                genBlockPreamble(blk);
0534:                if (blk.getLabel() != null) {
0535:                    cnt = "_cnt_" + blk.getLabel();
0536:                } else {
0537:                    cnt = "_cnt" + blk.ID;
0538:                }
0539:                println("int " + cnt + "=0;");
0540:                if (blk.getLabel() != null) {
0541:                    label = blk.getLabel();
0542:                } else {
0543:                    label = "_loop" + blk.ID;
0544:                }
0545:
0546:                println("for (;;) {");
0547:                tabs++;
0548:                // generate the init action for ()+ ()* inside the loop
0549:                // this allows us to do usefull EOF checking...
0550:                genBlockInitAction(blk);
0551:
0552:                // Tell AST generation to build subrule result
0553:                String saveCurrentASTResult = currentASTResult;
0554:                if (blk.getLabel() != null) {
0555:                    currentASTResult = blk.getLabel();
0556:                }
0557:
0558:                boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
0559:
0560:                // generate exit test if greedy set to false
0561:                // and an alt is ambiguous with exit branch
0562:                // or when lookahead derived purely from end-of-file
0563:                // Lookahead analysis stops when end-of-file is hit,
0564:                // returning set {epsilon}.  Since {epsilon} is not
0565:                // ambig with any real tokens, no error is reported
0566:                // by deterministic() routines and we have to check
0567:                // for the case where the lookahead depth didn't get
0568:                // set to NONDETERMINISTIC (this only happens when the
0569:                // FOLLOW contains real atoms + epsilon).
0570:                boolean generateNonGreedyExitPath = false;
0571:                int nonGreedyExitDepth = grammar.maxk;
0572:
0573:                if (!blk.greedy
0574:                        && blk.exitLookaheadDepth <= grammar.maxk
0575:                        && blk.exitCache[blk.exitLookaheadDepth]
0576:                                .containsEpsilon()) {
0577:                    generateNonGreedyExitPath = true;
0578:                    nonGreedyExitDepth = blk.exitLookaheadDepth;
0579:                } else if (!blk.greedy
0580:                        && blk.exitLookaheadDepth == LLkGrammarAnalyzer.NONDETERMINISTIC) {
0581:                    generateNonGreedyExitPath = true;
0582:                }
0583:
0584:                // generate exit test if greedy set to false
0585:                // and an alt is ambiguous with exit branch
0586:                if (generateNonGreedyExitPath) {
0587:                    if (DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR) {
0588:                        System.out
0589:                                .println("nongreedy (...)+ loop; exit depth is "
0590:                                        + blk.exitLookaheadDepth);
0591:                    }
0592:                    String predictExit = getLookaheadTestExpression(
0593:                            blk.exitCache, nonGreedyExitDepth);
0594:                    println("// nongreedy exit test");
0595:                    println("if ( " + cnt + ">=1 && " + predictExit + ") goto "
0596:                            + label + ";");
0597:                }
0598:
0599:                CppBlockFinishingInfo howToFinish = genCommonBlock(blk, false);
0600:                genBlockFinish(howToFinish, "if ( " + cnt + ">=1 ) { goto "
0601:                        + label + "; } else {" + throwNoViable + "}");
0602:
0603:                println(cnt + "++;");
0604:                tabs--;
0605:                println("}");
0606:                println(label + ":;");
0607:                println("}  // ( ... )+");
0608:
0609:                // Restore previous AST generation
0610:                currentASTResult = saveCurrentASTResult;
0611:            }
0612:
0613:            /** Generate the parser C++ file */
0614:            public void gen(ParserGrammar g) throws IOException {
0615:
0616:                // if debugging, set up a new vector to keep track of sempred
0617:                //   strings for this grammar
0618:                if (g.debuggingOutput)
0619:                    semPreds = new Vector();
0620:
0621:                setGrammar(g);
0622:                if (!(grammar instanceof  ParserGrammar)) {
0623:                    antlrTool.panic("Internal error generating parser");
0624:                }
0625:
0626:                genBody(g);
0627:                genInclude(g);
0628:            }
0629:
0630:            /** Generate code for the given grammar element.
0631:             * @param blk The rule-reference to generate
0632:             */
0633:            public void gen(RuleRefElement rr) {
0634:                if (DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR)
0635:                    System.out.println("genRR(" + rr + ")");
0636:                RuleSymbol rs = (RuleSymbol) grammar.getSymbol(rr.targetRule);
0637:                if (rs == null || !rs.isDefined()) {
0638:                    // Is this redundant???
0639:                    antlrTool.error("Rule '" + rr.targetRule
0640:                            + "' is not defined", grammar.getFilename(), rr
0641:                            .getLine(), rr.getColumn());
0642:                    return;
0643:                }
0644:                if (!(rs instanceof  RuleSymbol)) {
0645:                    // Is this redundant???
0646:                    antlrTool.error("'" + rr.targetRule
0647:                            + "' does not name a grammar rule", grammar
0648:                            .getFilename(), rr.getLine(), rr.getColumn());
0649:                    return;
0650:                }
0651:
0652:                genErrorTryForElement(rr);
0653:
0654:                // AST value for labeled rule refs in tree walker.
0655:                // This is not AST construction;  it is just the input tree node value.
0656:                if (grammar instanceof  TreeWalkerGrammar
0657:                        && rr.getLabel() != null && syntacticPredLevel == 0) {
0658:                    println(rr.getLabel() + " = (_t == ASTNULL) ? "
0659:                            + labeledElementASTInit + " : " + lt1Value + ";");
0660:                }
0661:
0662:                // if in lexer and ! on rule ref or alt or rule, save buffer index to
0663:                // kill later
0664:                if (grammar instanceof  LexerGrammar
0665:                        && (!saveText || rr.getAutoGenType() == GrammarElement.AUTO_GEN_BANG)) {
0666:                    println("_saveIndex = text.length();");
0667:                }
0668:
0669:                // Process return value assignment if any
0670:                printTabs();
0671:                if (rr.idAssign != null) {
0672:                    // Warn if the rule has no return type
0673:                    if (rs.block.returnAction == null) {
0674:                        antlrTool.warning("Rule '" + rr.targetRule
0675:                                + "' has no return type",
0676:                                grammar.getFilename(), rr.getLine(), rr
0677:                                        .getColumn());
0678:                    }
0679:                    _print(rr.idAssign + "=");
0680:                } else {
0681:                    // Warn about return value if any, but not inside syntactic predicate
0682:                    if (!(grammar instanceof  LexerGrammar)
0683:                            && syntacticPredLevel == 0
0684:                            && rs.block.returnAction != null) {
0685:                        antlrTool.warning("Rule '" + rr.targetRule
0686:                                + "' returns a value", grammar.getFilename(),
0687:                                rr.getLine(), rr.getColumn());
0688:                    }
0689:                }
0690:
0691:                // Call the rule
0692:                GenRuleInvocation(rr);
0693:
0694:                // if in lexer and ! on element or alt or rule, save buffer index to kill later
0695:                if (grammar instanceof  LexerGrammar
0696:                        && (!saveText || rr.getAutoGenType() == GrammarElement.AUTO_GEN_BANG)) {
0697:                    println("text.erase(_saveIndex);");
0698:                }
0699:
0700:                // if not in a syntactic predicate
0701:                if (syntacticPredLevel == 0) {
0702:                    boolean doNoGuessTest = (grammar.hasSyntacticPredicate && (grammar.buildAST
0703:                            && rr.getLabel() != null || (genAST && rr
0704:                            .getAutoGenType() == GrammarElement.AUTO_GEN_NONE)));
0705:
0706:                    if (doNoGuessTest) {
0707:                        println("if (inputState->guessing==0) {");
0708:                        tabs++;
0709:                    }
0710:
0711:                    if (grammar.buildAST && rr.getLabel() != null) {
0712:                        // always gen variable for rule return on labeled rules
0713:                        // RK: hmm do I know here if the returnAST needs a cast ?
0714:                        println(rr.getLabel() + "_AST = returnAST;");
0715:                    }
0716:
0717:                    if (genAST) {
0718:                        switch (rr.getAutoGenType()) {
0719:                        case GrammarElement.AUTO_GEN_NONE:
0720:                            if (usingCustomAST)
0721:                                println("astFactory->addASTChild(currentAST, "
0722:                                        + namespaceAntlr
0723:                                        + "RefAST(returnAST));");
0724:                            else
0725:                                println("astFactory->addASTChild( currentAST, returnAST );");
0726:                            break;
0727:                        case GrammarElement.AUTO_GEN_CARET:
0728:                            // FIXME: RK: I'm not so sure this should be an error..
0729:                            // I think it might actually work and be usefull at times.
0730:                            antlrTool
0731:                                    .error("Internal: encountered ^ after rule reference");
0732:                            break;
0733:                        default:
0734:                            break;
0735:                        }
0736:                    }
0737:
0738:                    // if a lexer and labeled, Token label defined at rule level, just set it here
0739:                    if (grammar instanceof  LexerGrammar
0740:                            && rr.getLabel() != null) {
0741:                        println(rr.getLabel() + "=_returnToken;");
0742:                    }
0743:
0744:                    if (doNoGuessTest) {
0745:                        tabs--;
0746:                        println("}");
0747:                    }
0748:                }
0749:                genErrorCatchForElement(rr);
0750:            }
0751:
0752:            /** Generate code for the given grammar element.
0753:             * @param blk The string-literal reference to generate
0754:             */
0755:            public void gen(StringLiteralElement atom) {
0756:                if (DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR)
0757:                    System.out.println("genString(" + atom + ")");
0758:
0759:                // Variable declarations for labeled elements
0760:                if (atom.getLabel() != null && syntacticPredLevel == 0) {
0761:                    println(atom.getLabel() + " = " + lt1Value + ";");
0762:                }
0763:
0764:                // AST
0765:                genElementAST(atom);
0766:
0767:                // is there a bang on the literal?
0768:                boolean oldsaveText = saveText;
0769:                saveText = saveText
0770:                        && atom.getAutoGenType() == GrammarElement.AUTO_GEN_NONE;
0771:
0772:                // matching
0773:                genMatch(atom);
0774:
0775:                saveText = oldsaveText;
0776:
0777:                // tack on tree cursor motion if doing a tree walker
0778:                if (grammar instanceof  TreeWalkerGrammar) {
0779:                    println("_t = _t->getNextSibling();");
0780:                }
0781:            }
0782:
0783:            /** Generate code for the given grammar element.
0784:             * @param blk The token-range reference to generate
0785:             */
0786:            public void gen(TokenRangeElement r) {
0787:                genErrorTryForElement(r);
0788:                if (r.getLabel() != null && syntacticPredLevel == 0) {
0789:                    println(r.getLabel() + " = " + lt1Value + ";");
0790:                }
0791:
0792:                // AST
0793:                genElementAST(r);
0794:
0795:                // match
0796:                println("matchRange(" + r.beginText + "," + r.endText + ");");
0797:                genErrorCatchForElement(r);
0798:            }
0799:
0800:            /** Generate code for the given grammar element.
0801:             * @param blk The token-reference to generate
0802:             */
0803:            public void gen(TokenRefElement atom) {
0804:                if (DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR)
0805:                    System.out.println("genTokenRef(" + atom + ")");
0806:                if (grammar instanceof  LexerGrammar) {
0807:                    antlrTool.panic("Token reference found in lexer");
0808:                }
0809:                genErrorTryForElement(atom);
0810:                // Assign Token value to token label variable
0811:                if (atom.getLabel() != null && syntacticPredLevel == 0) {
0812:                    println(atom.getLabel() + " = " + lt1Value + ";");
0813:                }
0814:
0815:                // AST
0816:                genElementAST(atom);
0817:                // matching
0818:                genMatch(atom);
0819:                genErrorCatchForElement(atom);
0820:
0821:                // tack on tree cursor motion if doing a tree walker
0822:                if (grammar instanceof  TreeWalkerGrammar) {
0823:                    println("_t = _t->getNextSibling();");
0824:                }
0825:            }
0826:
0827:            public void gen(TreeElement t) {
0828:                // save AST cursor
0829:                println(labeledElementType + " __t" + t.ID + " = _t;");
0830:
0831:                // If there is a label on the root, then assign that to the variable
0832:                if (t.root.getLabel() != null) {
0833:                    println(t.root.getLabel() + " = (_t == ASTNULL) ? "
0834:                            + labeledElementASTInit + " : _t;");
0835:                }
0836:
0837:                // check for invalid modifiers ! and ^ on tree element roots
0838:                if (t.root.getAutoGenType() == GrammarElement.AUTO_GEN_BANG) {
0839:                    antlrTool
0840:                            .error(
0841:                                    "Suffixing a root node with '!' is not implemented",
0842:                                    grammar.getFilename(), t.getLine(), t
0843:                                            .getColumn());
0844:                    t.root.setAutoGenType(GrammarElement.AUTO_GEN_NONE);
0845:                }
0846:                if (t.root.getAutoGenType() == GrammarElement.AUTO_GEN_CARET) {
0847:                    antlrTool
0848:                            .warning(
0849:                                    "Suffixing a root node with '^' is redundant; already a root",
0850:                                    grammar.getFilename(), t.getLine(), t
0851:                                            .getColumn());
0852:                    t.root.setAutoGenType(GrammarElement.AUTO_GEN_NONE);
0853:                }
0854:
0855:                // Generate AST variables
0856:                genElementAST(t.root);
0857:                if (grammar.buildAST) {
0858:                    // Save the AST construction state
0859:                    println(namespaceAntlr + "ASTPair __currentAST" + t.ID
0860:                            + " = currentAST;");
0861:                    // Make the next item added a child of the TreeElement root
0862:                    println("currentAST.root = currentAST.child;");
0863:                    println("currentAST.child = " + labeledElementASTInit + ";");
0864:                }
0865:
0866:                // match root
0867:                if (t.root instanceof  WildcardElement) {
0868:                    println("if ( _t == ASTNULL ) throw " + namespaceAntlr
0869:                            + "MismatchedTokenException();");
0870:                } else {
0871:                    genMatch(t.root);
0872:                }
0873:                // move to list of children
0874:                println("_t = _t->getFirstChild();");
0875:
0876:                // walk list of children, generating code for each
0877:                for (int i = 0; i < t.getAlternatives().size(); i++) {
0878:                    Alternative a = t.getAlternativeAt(i);
0879:                    AlternativeElement e = a.head;
0880:                    while (e != null) {
0881:                        e.generate();
0882:                        e = e.next;
0883:                    }
0884:                }
0885:
0886:                if (grammar.buildAST) {
0887:                    // restore the AST construction state to that just after the
0888:                    // tree root was added
0889:                    println("currentAST = __currentAST" + t.ID + ";");
0890:                }
0891:                // restore AST cursor
0892:                println("_t = __t" + t.ID + ";");
0893:                // move cursor to sibling of tree just parsed
0894:                println("_t = _t->getNextSibling();");
0895:            }
0896:
0897:            /** Generate the tree-parser C++ files */
0898:            public void gen(TreeWalkerGrammar g) throws IOException {
0899:                setGrammar(g);
0900:                if (!(grammar instanceof  TreeWalkerGrammar)) {
0901:                    antlrTool.panic("Internal error generating tree-walker");
0902:                }
0903:
0904:                genBody(g);
0905:                genInclude(g);
0906:            }
0907:
0908:            /** Generate code for the given grammar element.
0909:             * @param wc The wildcard element to generate
0910:             */
0911:            public void gen(WildcardElement wc) {
0912:                // Variable assignment for labeled elements
0913:                if (wc.getLabel() != null && syntacticPredLevel == 0) {
0914:                    println(wc.getLabel() + " = " + lt1Value + ";");
0915:                }
0916:
0917:                // AST
0918:                genElementAST(wc);
0919:                // Match anything but EOF
0920:                if (grammar instanceof  TreeWalkerGrammar) {
0921:                    println("if ( _t == " + labeledElementASTInit + " ) throw "
0922:                            + namespaceAntlr + "MismatchedTokenException();");
0923:                } else if (grammar instanceof  LexerGrammar) {
0924:                    if (grammar instanceof  LexerGrammar
0925:                            && (!saveText || wc.getAutoGenType() == GrammarElement.AUTO_GEN_BANG)) {
0926:                        println("_saveIndex = text.length();");
0927:                    }
0928:                    println("matchNot(EOF/*_CHAR*/);");
0929:                    if (grammar instanceof  LexerGrammar
0930:                            && (!saveText || wc.getAutoGenType() == GrammarElement.AUTO_GEN_BANG)) {
0931:                        println("text.erase(_saveIndex);"); // kill text atom put in buffer
0932:                    }
0933:                } else {
0934:                    println("matchNot(" + getValueString(Token.EOF_TYPE) + ");");
0935:                }
0936:
0937:                // tack on tree cursor motion if doing a tree walker
0938:                if (grammar instanceof  TreeWalkerGrammar) {
0939:                    println("_t = _t->getNextSibling();");
0940:                }
0941:            }
0942:
0943:            /** Generate code for the given grammar element.
0944:             * @param blk The (...)* block to generate
0945:             */
0946:            public void gen(ZeroOrMoreBlock blk) {
0947:                if (DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR)
0948:                    System.out.println("gen*(" + blk + ")");
0949:                println("{ // ( ... )*");
0950:                genBlockPreamble(blk);
0951:                String label;
0952:                if (blk.getLabel() != null) {
0953:                    label = blk.getLabel();
0954:                } else {
0955:                    label = "_loop" + blk.ID;
0956:                }
0957:                println("for (;;) {");
0958:                tabs++;
0959:                // generate the init action for ()+ ()* inside the loop
0960:                // this allows us to do usefull EOF checking...
0961:                genBlockInitAction(blk);
0962:
0963:                // Tell AST generation to build subrule result
0964:                String saveCurrentASTResult = currentASTResult;
0965:                if (blk.getLabel() != null) {
0966:                    currentASTResult = blk.getLabel();
0967:                }
0968:
0969:                boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
0970:
0971:                // generate exit test if greedy set to false
0972:                // and an alt is ambiguous with exit branch
0973:                // or when lookahead derived purely from end-of-file
0974:                // Lookahead analysis stops when end-of-file is hit,
0975:                // returning set {epsilon}.  Since {epsilon} is not
0976:                // ambig with any real tokens, no error is reported
0977:                // by deterministic() routines and we have to check
0978:                // for the case where the lookahead depth didn't get
0979:                // set to NONDETERMINISTIC (this only happens when the
0980:                // FOLLOW contains real atoms + epsilon).
0981:                boolean generateNonGreedyExitPath = false;
0982:                int nonGreedyExitDepth = grammar.maxk;
0983:
0984:                if (!blk.greedy
0985:                        && blk.exitLookaheadDepth <= grammar.maxk
0986:                        && blk.exitCache[blk.exitLookaheadDepth]
0987:                                .containsEpsilon()) {
0988:                    generateNonGreedyExitPath = true;
0989:                    nonGreedyExitDepth = blk.exitLookaheadDepth;
0990:                } else if (!blk.greedy
0991:                        && blk.exitLookaheadDepth == LLkGrammarAnalyzer.NONDETERMINISTIC) {
0992:                    generateNonGreedyExitPath = true;
0993:                }
0994:                if (generateNonGreedyExitPath) {
0995:                    if (DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR) {
0996:                        System.out
0997:                                .println("nongreedy (...)* loop; exit depth is "
0998:                                        + blk.exitLookaheadDepth);
0999:                    }
1000:                    String predictExit = getLookaheadTestExpression(
1001:                            blk.exitCache, nonGreedyExitDepth);
1002:                    println("// nongreedy exit test");
1003:                    println("if (" + predictExit + ") goto " + label + ";");
1004:                }
1005:
1006:                CppBlockFinishingInfo howToFinish = genCommonBlock(blk, false);
1007:                genBlockFinish(howToFinish, "goto " + label + ";");
1008:
1009:                tabs--;
1010:                println("}");
1011:                println(label + ":;");
1012:                println("} // ( ... )*");
1013:
1014:                // Restore previous AST generation
1015:                currentASTResult = saveCurrentASTResult;
1016:            }
1017:
1018:            /** Generate an alternative.
1019:             * @param alt  The alternative to generate
1020:             * @param blk The block to which the alternative belongs
1021:             */
1022:            protected void genAlt(Alternative alt, AlternativeBlock blk) {
1023:                // Save the AST generation state, and set it to that of the alt
1024:                boolean savegenAST = genAST;
1025:                genAST = genAST && alt.getAutoGen();
1026:
1027:                boolean oldsaveTest = saveText;
1028:                saveText = saveText && alt.getAutoGen();
1029:
1030:                // Reset the variable name map for the alternative
1031:                Hashtable saveMap = treeVariableMap;
1032:                treeVariableMap = new Hashtable();
1033:
1034:                // Generate try block around the alt for  error handling
1035:                if (alt.exceptionSpec != null) {
1036:                    println("try {      // for error handling");
1037:                    tabs++;
1038:                }
1039:
1040:                AlternativeElement elem = alt.head;
1041:                while (!(elem instanceof  BlockEndElement)) {
1042:                    elem.generate(); // alt can begin with anything. Ask target to gen.
1043:                    elem = elem.next;
1044:                }
1045:
1046:                if (genAST) {
1047:                    if (blk instanceof  RuleBlock) {
1048:                        // Set the AST return value for the rule
1049:                        RuleBlock rblk = (RuleBlock) blk;
1050:                        if (usingCustomAST)
1051:                            println(rblk.getRuleName() + "_AST = "
1052:                                    + labeledElementASTType
1053:                                    + "(currentAST.root);");
1054:                        else
1055:                            println(rblk.getRuleName()
1056:                                    + "_AST = currentAST.root;");
1057:                    } else if (blk.getLabel() != null) {
1058:                        // ### future: also set AST value for labeled subrules.
1059:                        // println(blk.getLabel() + "_AST = "+labeledElementASTType+"(currentAST.root);");
1060:                        antlrTool.warning(
1061:                                "Labeled subrules are not implemented", grammar
1062:                                        .getFilename(), blk.getLine(), blk
1063:                                        .getColumn());
1064:                    }
1065:                }
1066:
1067:                if (alt.exceptionSpec != null) {
1068:                    // close try block
1069:                    tabs--;
1070:                    println("}");
1071:                    genErrorHandler(alt.exceptionSpec);
1072:                }
1073:
1074:                genAST = savegenAST;
1075:                saveText = oldsaveTest;
1076:
1077:                treeVariableMap = saveMap;
1078:            }
1079:
1080:            /** Generate all the bitsets to be used in the parser or lexer
1081:             * Generate the raw bitset data like "long _tokenSet1_data[] = {...};"
1082:             * and the BitSet object declarations like
1083:             * "BitSet _tokenSet1 = new BitSet(_tokenSet1_data);"
1084:             * Note that most languages do not support object initialization inside a
1085:             * class definition, so other code-generators may have to separate the
1086:             * bitset declarations from the initializations (e.g., put the
1087:             * initializations in the generated constructor instead).
1088:             * @param bitsetList The list of bitsets to generate.
1089:             * @param maxVocabulary Ensure that each generated bitset can contain at
1090:             *        least this value.
1091:             * @param prefix string glued in from of bitset names used for namespace
1092:             *        qualifications.
1093:             */
1094:            protected void genBitsets(Vector bitsetList, int maxVocabulary,
1095:                    String prefix) {
1096:                TokenManager tm = grammar.tokenManager;
1097:
1098:                println("");
1099:
1100:                for (int i = 0; i < bitsetList.size(); i++) {
1101:                    BitSet p = (BitSet) bitsetList.elementAt(i);
1102:                    // Ensure that generated BitSet is large enough for vocabulary
1103:                    p.growToInclude(maxVocabulary);
1104:
1105:                    // initialization data
1106:                    println("const unsigned long " + prefix + getBitsetName(i)
1107:                            + "_data_" + "[] = { " + p.toStringOfHalfWords()
1108:                            + " };");
1109:
1110:                    // Dump the contents of the bitset in readable format...
1111:                    String t = "// ";
1112:                    for (int j = 0; j < tm.getVocabulary().size(); j++) {
1113:                        if (p.member(j)) {
1114:                            if ((grammar instanceof  LexerGrammar))
1115:                                t += tm.getVocabulary().elementAt(j) + " ";
1116:                            else
1117:                                t += tm.getTokenStringAt(j) + " ";
1118:
1119:                            if (t.length() > 70) {
1120:                                println(t);
1121:                                t = "// ";
1122:                            }
1123:                        }
1124:                    }
1125:                    if (t != "// ")
1126:                        println(t);
1127:
1128:                    // BitSet object
1129:                    println("const " + namespaceAntlr + "BitSet " + prefix
1130:                            + getBitsetName(i) + "(" + getBitsetName(i)
1131:                            + "_data_," + p.size() / 32 + ");");
1132:                }
1133:            }
1134:
1135:            protected void genBitsetsHeader(Vector bitsetList, int maxVocabulary) {
1136:                println("");
1137:                for (int i = 0; i < bitsetList.size(); i++) {
1138:                    BitSet p = (BitSet) bitsetList.elementAt(i);
1139:                    // Ensure that generated BitSet is large enough for vocabulary
1140:                    p.growToInclude(maxVocabulary);
1141:                    // initialization data
1142:                    println("static const unsigned long " + getBitsetName(i)
1143:                            + "_data_" + "[];");
1144:                    // BitSet object
1145:                    println("static const " + namespaceAntlr + "BitSet "
1146:                            + getBitsetName(i) + ";");
1147:                }
1148:            }
1149:
1150:            /** Generate the finish of a block, using a combination of the info
1151:             * returned from genCommonBlock() and the action to perform when
1152:             * no alts were taken
1153:             * @param howToFinish The return of genCommonBlock()
1154:             * @param noViableAction What to generate when no alt is taken
1155:             */
1156:            private void genBlockFinish(CppBlockFinishingInfo howToFinish,
1157:                    String noViableAction) {
1158:                if (howToFinish.needAnErrorClause
1159:                        && (howToFinish.generatedAnIf || howToFinish.generatedSwitch)) {
1160:                    if (howToFinish.generatedAnIf) {
1161:                        println("else {");
1162:                    } else {
1163:                        println("{");
1164:                    }
1165:                    tabs++;
1166:                    println(noViableAction);
1167:                    tabs--;
1168:                    println("}");
1169:                }
1170:
1171:                if (howToFinish.postscript != null) {
1172:                    println(howToFinish.postscript);
1173:                }
1174:            }
1175:
1176:            /** Generate the initaction for a block, which may be a RuleBlock or a
1177:             * plain AlternativeBLock.
1178:             * @blk The block for which the preamble is to be generated.
1179:             */
1180:            protected void genBlockInitAction(AlternativeBlock blk) {
1181:                // dump out init action
1182:                if (blk.initAction != null) {
1183:                    genLineNo(blk);
1184:                    printAction(processActionForSpecialSymbols(blk.initAction,
1185:                            blk.line, currentRule, null));
1186:                    genLineNo2();
1187:                }
1188:            }
1189:
1190:            /** Generate the header for a block, which may be a RuleBlock or a
1191:             * plain AlternativeBlock. This generates any variable declarations
1192:             * and syntactic-predicate-testing variables.
1193:             * @blk The block for which the preamble is to be generated.
1194:             */
1195:            protected void genBlockPreamble(AlternativeBlock blk) {
1196:                // define labels for rule blocks.
1197:                if (blk instanceof  RuleBlock) {
1198:                    RuleBlock rblk = (RuleBlock) blk;
1199:                    if (rblk.labeledElements != null) {
1200:                        for (int i = 0; i < rblk.labeledElements.size(); i++) {
1201:
1202:                            AlternativeElement a = (AlternativeElement) rblk.labeledElements
1203:                                    .elementAt(i);
1204:                            //System.out.println("looking at labeled element: "+a);
1205:                            // Variables for labeled rule refs and subrules are different than
1206:                            // variables for grammar atoms.  This test is a little tricky because
1207:                            // we want to get all rule refs and ebnf, but not rule blocks or
1208:                            // syntactic predicates
1209:                            if (a instanceof  RuleRefElement
1210:                                    || a instanceof  AlternativeBlock
1211:                                    && !(a instanceof  RuleBlock)
1212:                                    && !(a instanceof  SynPredBlock)) {
1213:                                if (!(a instanceof  RuleRefElement)
1214:                                        && ((AlternativeBlock) a).not
1215:                                        && analyzer
1216:                                                .subruleCanBeInverted(
1217:                                                        ((AlternativeBlock) a),
1218:                                                        grammar instanceof  LexerGrammar)) {
1219:                                    // Special case for inverted subrules that will be
1220:                                    // inlined. Treat these like token or char literal
1221:                                    // references
1222:                                    println(labeledElementType + " "
1223:                                            + a.getLabel() + " = "
1224:                                            + labeledElementInit + ";");
1225:                                    if (grammar.buildAST) {
1226:                                        genASTDeclaration(a);
1227:                                    }
1228:                                } else {
1229:                                    if (grammar.buildAST) {
1230:                                        // Always gen AST variables for labeled elements,
1231:                                        // even if the element itself is marked with !
1232:                                        genASTDeclaration(a);
1233:                                    }
1234:                                    if (grammar instanceof  LexerGrammar)
1235:                                        println(namespaceAntlr + "RefToken "
1236:                                                + a.getLabel() + ";");
1237:
1238:                                    if (grammar instanceof  TreeWalkerGrammar) {
1239:                                        // always generate rule-ref variables for tree walker
1240:                                        println(labeledElementType + " "
1241:                                                + a.getLabel() + " = "
1242:                                                + labeledElementInit + ";");
1243:                                    }
1244:                                }
1245:                            } else {
1246:                                // It is a token or literal reference.  Generate the
1247:                                // correct variable type for this grammar
1248:                                println(labeledElementType + " " + a.getLabel()
1249:                                        + " = " + labeledElementInit + ";");
1250:                                // In addition, generate *_AST variables if building ASTs
1251:                                if (grammar.buildAST) {
1252:                                    if (a instanceof  GrammarAtom
1253:                                            && ((GrammarAtom) a)
1254:                                                    .getASTNodeType() != null) {
1255:                                        GrammarAtom ga = (GrammarAtom) a;
1256:                                        genASTDeclaration(a, "Ref"
1257:                                                + ga.getASTNodeType());
1258:                                    } else {
1259:                                        genASTDeclaration(a);
1260:                                    }
1261:                                }
1262:                            }
1263:                        }
1264:                    }
1265:                }
1266:            }
1267:
1268:            public void genBody(LexerGrammar g) throws IOException {
1269:                outputFile = grammar.getClassName() + ".cpp";
1270:                outputLine = 1;
1271:                currentOutput = antlrTool.openOutputFile(outputFile);
1272:                //SAS: changed for proper text file io
1273:
1274:                genAST = false; // no way to gen trees.
1275:                saveText = true; // save consumed characters.
1276:
1277:                tabs = 0;
1278:
1279:                // Generate header common to all C++ output files
1280:                genHeader(outputFile);
1281:
1282:                printHeaderAction(preIncludeCpp);
1283:                // Generate header specific to lexer C++ file
1284:                println("#include \"" + grammar.getClassName() + ".hpp\"");
1285:                println("#include <antlr/CharBuffer.hpp>");
1286:                println("#include <antlr/TokenStreamException.hpp>");
1287:                println("#include <antlr/TokenStreamIOException.hpp>");
1288:                println("#include <antlr/TokenStreamRecognitionException.hpp>");
1289:                println("#include <antlr/CharStreamException.hpp>");
1290:                println("#include <antlr/CharStreamIOException.hpp>");
1291:                println("#include <antlr/NoViableAltForCharException.hpp>");
1292:                if (grammar.debuggingOutput)
1293:                    println("#include <antlr/DebuggingInputBuffer.hpp>");
1294:                println("");
1295:                printHeaderAction(postIncludeCpp);
1296:
1297:                if (nameSpace != null)
1298:                    nameSpace.emitDeclarations(currentOutput);
1299:
1300:                // Generate user-defined lexer file preamble
1301:                printAction(grammar.preambleAction);
1302:
1303:                // Generate lexer class definition
1304:                String sup = null;
1305:                if (grammar.super Class != null) {
1306:                    sup = grammar.super Class;
1307:                } else {
1308:                    sup = grammar.getSuperClass();
1309:                    if (sup.lastIndexOf('.') != -1)
1310:                        sup = sup.substring(sup.lastIndexOf('.') + 1);
1311:                    sup = namespaceAntlr + sup;
1312:                }
1313:
1314:                if (noConstructors) {
1315:                    println("#if 0");
1316:                    println("// constructor creation turned of with 'noConstructor' option");
1317:                }
1318:                //
1319:                // Generate the constructor from InputStream
1320:                //
1321:                println(grammar.getClassName() + "::" + grammar.getClassName()
1322:                        + "(" + namespaceStd + "istream& in)");
1323:                tabs++;
1324:                // if debugging, wrap the input buffer in a debugger
1325:                if (grammar.debuggingOutput)
1326:                    println(": " + sup + "(new " + namespaceAntlr
1327:                            + "DebuggingInputBuffer(new " + namespaceAntlr
1328:                            + "CharBuffer(in))," + g.caseSensitive + ")");
1329:                else
1330:                    println(": " + sup + "(new " + namespaceAntlr
1331:                            + "CharBuffer(in)," + g.caseSensitive + ")");
1332:                tabs--;
1333:                println("{");
1334:                tabs++;
1335:
1336:                // if debugging, set up array variables and call user-overridable
1337:                //   debugging setup method
1338:                if (grammar.debuggingOutput) {
1339:                    println("setRuleNames(_ruleNames);");
1340:                    println("setSemPredNames(_semPredNames);");
1341:                    println("setupDebugging();");
1342:                }
1343:
1344:                //		println("setCaseSensitive("+g.caseSensitive+");");
1345:                println("initLiterals();");
1346:                tabs--;
1347:                println("}");
1348:                println("");
1349:
1350:                // Generate the constructor from InputBuffer
1351:                println(grammar.getClassName() + "::" + grammar.getClassName()
1352:                        + "(" + namespaceAntlr + "InputBuffer& ib)");
1353:                tabs++;
1354:                // if debugging, wrap the input buffer in a debugger
1355:                if (grammar.debuggingOutput)
1356:                    println(": " + sup + "(new " + namespaceAntlr
1357:                            + "DebuggingInputBuffer(ib)," + g.caseSensitive
1358:                            + ")");
1359:                else
1360:                    println(": " + sup + "(ib," + g.caseSensitive + ")");
1361:                tabs--;
1362:                println("{");
1363:                tabs++;
1364:
1365:                // if debugging, set up array variables and call user-overridable
1366:                //   debugging setup method
1367:                if (grammar.debuggingOutput) {
1368:                    println("setRuleNames(_ruleNames);");
1369:                    println("setSemPredNames(_semPredNames);");
1370:                    println("setupDebugging();");
1371:                }
1372:
1373:                //		println("setCaseSensitive("+g.caseSensitive+");");
1374:                println("initLiterals();");
1375:                tabs--;
1376:                println("}");
1377:                println("");
1378:
1379:                // Generate the constructor from LexerSharedInputState
1380:                println(grammar.getClassName() + "::" + grammar.getClassName()
1381:                        + "(const " + namespaceAntlr
1382:                        + "LexerSharedInputState& state)");
1383:                tabs++;
1384:                println(": " + sup + "(state," + g.caseSensitive + ")");
1385:                tabs--;
1386:                println("{");
1387:                tabs++;
1388:
1389:                // if debugging, set up array variables and call user-overridable
1390:                //   debugging setup method
1391:                if (grammar.debuggingOutput) {
1392:                    println("setRuleNames(_ruleNames);");
1393:                    println("setSemPredNames(_semPredNames);");
1394:                    println("setupDebugging();");
1395:                }
1396:
1397:                //		println("setCaseSensitive("+g.caseSensitive+");");
1398:                println("initLiterals();");
1399:                tabs--;
1400:                println("}");
1401:                println("");
1402:
1403:                if (noConstructors) {
1404:                    println("// constructor creation turned of with 'noConstructor' option");
1405:                    println("#endif");
1406:                }
1407:
1408:                println("void " + grammar.getClassName() + "::initLiterals()");
1409:                println("{");
1410:                tabs++;
1411:                // Generate the initialization of the map
1412:                // containing the string literals used in the lexer
1413:                // The literals variable itself is in CharScanner
1414:                Enumeration keys = grammar.tokenManager.getTokenSymbolKeys();
1415:                while (keys.hasMoreElements()) {
1416:                    String key = (String) keys.nextElement();
1417:                    if (key.charAt(0) != '"') {
1418:                        continue;
1419:                    }
1420:                    TokenSymbol sym = grammar.tokenManager.getTokenSymbol(key);
1421:                    if (sym instanceof  StringLiteralSymbol) {
1422:                        StringLiteralSymbol s = (StringLiteralSymbol) sym;
1423:                        println("literals[" + s.getId() + "] = "
1424:                                + s.getTokenType() + ";");
1425:                    }
1426:                }
1427:
1428:                // Generate the setting of various generated options.
1429:                tabs--;
1430:                println("}");
1431:
1432:                Enumeration ids;
1433:                // generate the rule name array for debugging
1434:                if (grammar.debuggingOutput) {
1435:                    println("const char* " + grammar.getClassName()
1436:                            + "::_ruleNames[] = {");
1437:                    tabs++;
1438:
1439:                    ids = grammar.rules.elements();
1440:                    int ruleNum = 0;
1441:                    while (ids.hasMoreElements()) {
1442:                        GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
1443:                        if (sym instanceof  RuleSymbol)
1444:                            println("\"" + ((RuleSymbol) sym).getId() + "\",");
1445:                    }
1446:                    println("0");
1447:                    tabs--;
1448:                    println("};");
1449:                }
1450:
1451:                // Generate nextToken() rule.
1452:                // nextToken() is a synthetic lexer rule that is the implicit OR of all
1453:                // user-defined lexer rules.
1454:                genNextToken();
1455:
1456:                // Generate code for each rule in the lexer
1457:                ids = grammar.rules.elements();
1458:                int ruleNum = 0;
1459:                while (ids.hasMoreElements()) {
1460:                    RuleSymbol sym = (RuleSymbol) ids.nextElement();
1461:                    // Don't generate the synthetic rules
1462:                    if (!sym.getId().equals("mnextToken")) {
1463:                        genRule(sym, false, ruleNum++, grammar.getClassName()
1464:                                + "::");
1465:                    }
1466:                    exitIfError();
1467:                }
1468:
1469:                // Generate the semantic predicate map for debugging
1470:                if (grammar.debuggingOutput)
1471:                    genSemPredMap(grammar.getClassName() + "::");
1472:
1473:                // Generate the bitsets used throughout the lexer
1474:                genBitsets(bitsetsUsed, ((LexerGrammar) grammar).charVocabulary
1475:                        .size(), grammar.getClassName() + "::");
1476:
1477:                println("");
1478:                if (nameSpace != null)
1479:                    nameSpace.emitClosures(currentOutput);
1480:
1481:                // Close the lexer output stream
1482:                currentOutput.close();
1483:                currentOutput = null;
1484:            }
1485:
1486:            public void genInitFactory(Grammar g) {
1487:                // Generate the method to initialize an ASTFactory when we're
1488:                // building AST's
1489:                String param_name = "factory ";
1490:                if (!g.buildAST)
1491:                    param_name = "";
1492:
1493:                println("void " + g.getClassName() + "::initializeASTFactory( "
1494:                        + namespaceAntlr + "ASTFactory& " + param_name + ")");
1495:                println("{");
1496:                tabs++;
1497:
1498:                if (g.buildAST) {
1499:                    // print out elements collected...
1500:                    Enumeration e = astTypes.elements();
1501:                    while (e.hasMoreElements())
1502:                        println((String) e.nextElement());
1503:
1504:                    println("factory.setMaxNodeType("
1505:                            + grammar.tokenManager.maxTokenType() + ");");
1506:                }
1507:                tabs--;
1508:                println("}");
1509:            }
1510:
1511:            // FIXME: and so why are we passing here a g param while inside
1512:            // we merrily use the global grammar.
1513:            public void genBody(ParserGrammar g) throws IOException {
1514:                // Open the output stream for the parser and set the currentOutput
1515:                outputFile = grammar.getClassName() + ".cpp";
1516:                outputLine = 1;
1517:                currentOutput = antlrTool.openOutputFile(outputFile);
1518:
1519:                genAST = grammar.buildAST;
1520:
1521:                tabs = 0;
1522:
1523:                // Generate the header common to all output files.
1524:                genHeader(outputFile);
1525:
1526:                printHeaderAction(preIncludeCpp);
1527:
1528:                // Generate header for the parser
1529:                println("#include \"" + grammar.getClassName() + ".hpp\"");
1530:                println("#include <antlr/NoViableAltException.hpp>");
1531:                println("#include <antlr/SemanticException.hpp>");
1532:                println("#include <antlr/ASTFactory.hpp>");
1533:
1534:                printHeaderAction(postIncludeCpp);
1535:
1536:                if (nameSpace != null)
1537:                    nameSpace.emitDeclarations(currentOutput);
1538:
1539:                // Output the user-defined parser preamble
1540:                printAction(grammar.preambleAction);
1541:
1542:                String sup = null;
1543:                if (grammar.super Class != null)
1544:                    sup = grammar.super Class;
1545:                else {
1546:                    sup = grammar.getSuperClass();
1547:                    if (sup.lastIndexOf('.') != -1)
1548:                        sup = sup.substring(sup.lastIndexOf('.') + 1);
1549:                    sup = namespaceAntlr + sup;
1550:                }
1551:
1552:                // set up an array of all the rule names so the debugger can
1553:                // keep track of them only by number -- less to store in tree...
1554:                if (grammar.debuggingOutput) {
1555:                    println("const char* " + grammar.getClassName()
1556:                            + "::_ruleNames[] = {");
1557:                    tabs++;
1558:
1559:                    Enumeration ids = grammar.rules.elements();
1560:                    int ruleNum = 0;
1561:                    while (ids.hasMoreElements()) {
1562:                        GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
1563:                        if (sym instanceof  RuleSymbol)
1564:                            println("\"" + ((RuleSymbol) sym).getId() + "\",");
1565:                    }
1566:                    println("0");
1567:                    tabs--;
1568:                    println("};");
1569:                }
1570:
1571:                // Generate _initialize function
1572:                // disabled since it isn't used anymore..
1573:
1574:                //		println("void " + grammar.getClassName() + "::_initialize(void)");
1575:                //		println("{");
1576:                //		tabs++;
1577:
1578:                // if debugging, set up arrays and call the user-overridable
1579:                //   debugging setup method
1580:                //		if ( grammar.debuggingOutput ) {
1581:                //			println("setRuleNames(_ruleNames);");
1582:                //			println("setSemPredNames(_semPredNames);");
1583:                //			println("setupDebugging();");
1584:                //		}
1585:                //		tabs--;
1586:                //		println("}");
1587:                if (noConstructors) {
1588:                    println("#if 0");
1589:                    println("// constructor creation turned of with 'noConstructor' option");
1590:                }
1591:
1592:                // Generate parser class constructor from TokenBuffer
1593:                print(grammar.getClassName() + "::" + grammar.getClassName());
1594:                println("(" + namespaceAntlr + "TokenBuffer& tokenBuf, int k)");
1595:                println(": " + sup + "(tokenBuf,k)");
1596:                println("{");
1597:                //		tabs++;
1598:                //		println("_initialize();");
1599:                //		tabs--;
1600:                println("}");
1601:                println("");
1602:
1603:                print(grammar.getClassName() + "::" + grammar.getClassName());
1604:                println("(" + namespaceAntlr + "TokenBuffer& tokenBuf)");
1605:                println(": " + sup + "(tokenBuf," + grammar.maxk + ")");
1606:                println("{");
1607:                //		tabs++;
1608:                //		println("_initialize();");
1609:                //		tabs--;
1610:                println("}");
1611:                println("");
1612:
1613:                // Generate parser class constructor from TokenStream
1614:                print(grammar.getClassName() + "::" + grammar.getClassName());
1615:                println("(" + namespaceAntlr + "TokenStream& lexer, int k)");
1616:                println(": " + sup + "(lexer,k)");
1617:                println("{");
1618:                //		tabs++;
1619:                //		println("_initialize();");
1620:                //		tabs--;
1621:                println("}");
1622:                println("");
1623:
1624:                print(grammar.getClassName() + "::" + grammar.getClassName());
1625:                println("(" + namespaceAntlr + "TokenStream& lexer)");
1626:                println(": " + sup + "(lexer," + grammar.maxk + ")");
1627:                println("{");
1628:                //		tabs++;
1629:                //		println("_initialize();");
1630:                //		tabs--;
1631:                println("}");
1632:                println("");
1633:
1634:                print(grammar.getClassName() + "::" + grammar.getClassName());
1635:                println("(const " + namespaceAntlr
1636:                        + "ParserSharedInputState& state)");
1637:                println(": " + sup + "(state," + grammar.maxk + ")");
1638:                println("{");
1639:                //		tabs++;
1640:                //		println("_initialize();");
1641:                //		tabs--;
1642:                println("}");
1643:                println("");
1644:
1645:                if (noConstructors) {
1646:                    println("// constructor creation turned of with 'noConstructor' option");
1647:                    println("#endif");
1648:                }
1649:
1650:                astTypes = new Vector();
1651:
1652:                // Generate code for each rule in the grammar
1653:                Enumeration ids = grammar.rules.elements();
1654:                int ruleNum = 0;
1655:                while (ids.hasMoreElements()) {
1656:                    GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
1657:                    if (sym instanceof  RuleSymbol) {
1658:                        RuleSymbol rs = (RuleSymbol) sym;
1659:                        genRule(rs, rs.references.size() == 0, ruleNum++,
1660:                                grammar.getClassName() + "::");
1661:                    }
1662:                    exitIfError();
1663:                }
1664:
1665:                genInitFactory(g);
1666:
1667:                // Generate the token names
1668:                genTokenStrings(grammar.getClassName() + "::");
1669:
1670:                // Generate the bitsets used throughout the grammar
1671:                genBitsets(bitsetsUsed, grammar.tokenManager.maxTokenType(),
1672:                        grammar.getClassName() + "::");
1673:
1674:                // Generate the semantic predicate map for debugging
1675:                if (grammar.debuggingOutput)
1676:                    genSemPredMap(grammar.getClassName() + "::");
1677:
1678:                // Close class definition
1679:                println("");
1680:                println("");
1681:                if (nameSpace != null)
1682:                    nameSpace.emitClosures(currentOutput);
1683:
1684:                // Close the parser output stream
1685:                currentOutput.close();
1686:                currentOutput = null;
1687:            }
1688:
1689:            public void genBody(TreeWalkerGrammar g) throws IOException {
1690:                // Open the output stream for the parser and set the currentOutput
1691:                outputFile = grammar.getClassName() + ".cpp";
1692:                outputLine = 1;
1693:                currentOutput = antlrTool.openOutputFile(outputFile);
1694:                //SAS: changed for proper text file io
1695:
1696:                genAST = grammar.buildAST;
1697:                tabs = 0;
1698:
1699:                // Generate the header common to all output files.
1700:                genHeader(outputFile);
1701:
1702:                printHeaderAction(preIncludeCpp);
1703:
1704:                // Generate header for the parser
1705:                println("#include \"" + grammar.getClassName() + ".hpp\"");
1706:                println("#include <antlr/Token.hpp>");
1707:                println("#include <antlr/AST.hpp>");
1708:                println("#include <antlr/NoViableAltException.hpp>");
1709:                println("#include <antlr/MismatchedTokenException.hpp>");
1710:                println("#include <antlr/SemanticException.hpp>");
1711:                println("#include <antlr/BitSet.hpp>");
1712:
1713:                printHeaderAction(postIncludeCpp);
1714:
1715:                if (nameSpace != null)
1716:                    nameSpace.emitDeclarations(currentOutput);
1717:
1718:                // Output the user-defined parser premamble
1719:                printAction(grammar.preambleAction);
1720:
1721:                // Generate parser class definition
1722:                String sup = null;
1723:                if (grammar.super Class != null) {
1724:                    sup = grammar.super Class;
1725:                } else {
1726:                    sup = grammar.getSuperClass();
1727:                    if (sup.lastIndexOf('.') != -1)
1728:                        sup = sup.substring(sup.lastIndexOf('.') + 1);
1729:                    sup = namespaceAntlr + sup;
1730:                }
1731:                if (noConstructors) {
1732:                    println("#if 0");
1733:                    println("// constructor creation turned of with 'noConstructor' option");
1734:                }
1735:
1736:                // Generate default parser class constructor
1737:                println(grammar.getClassName() + "::" + grammar.getClassName()
1738:                        + "()");
1739:                println("\t: " + namespaceAntlr + "TreeParser() {");
1740:                tabs++;
1741:                //		println("setTokenNames(_tokenNames);");
1742:                tabs--;
1743:                println("}");
1744:
1745:                if (noConstructors) {
1746:                    println("// constructor creation turned of with 'noConstructor' option");
1747:                    println("#endif");
1748:                }
1749:                println("");
1750:
1751:                astTypes = new Vector();
1752:
1753:                // Generate code for each rule in the grammar
1754:                Enumeration ids = grammar.rules.elements();
1755:                int ruleNum = 0;
1756:                String ruleNameInits = "";
1757:                while (ids.hasMoreElements()) {
1758:                    GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
1759:                    if (sym instanceof  RuleSymbol) {
1760:                        RuleSymbol rs = (RuleSymbol) sym;
1761:                        genRule(rs, rs.references.size() == 0, ruleNum++,
1762:                                grammar.getClassName() + "::");
1763:                    }
1764:                    exitIfError();
1765:                }
1766:
1767:                // Generate the ASTFactory initialization function
1768:                genInitFactory(grammar);
1769:                // Generate the token names
1770:                genTokenStrings(grammar.getClassName() + "::");
1771:
1772:                // Generate the bitsets used throughout the grammar
1773:                genBitsets(bitsetsUsed, grammar.tokenManager.maxTokenType(),
1774:                        grammar.getClassName() + "::");
1775:
1776:                // Close class definition
1777:                println("");
1778:                println("");
1779:
1780:                if (nameSpace != null)
1781:                    nameSpace.emitClosures(currentOutput);
1782:
1783:                // Close the parser output stream
1784:                currentOutput.close();
1785:                currentOutput = null;
1786:            }
1787:
1788:            /** Generate a series of case statements that implement a BitSet test.
1789:             * @param p The Bitset for which cases are to be generated
1790:             */
1791:            protected void genCases(BitSet p) {
1792:                if (DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR)
1793:                    System.out.println("genCases(" + p + ")");
1794:                int[] elems;
1795:
1796:                elems = p.toArray();
1797:                // Wrap cases four-per-line for lexer, one-per-line for parser
1798:                int wrap = 1; //(grammar instanceof LexerGrammar) ? 4 : 1;
1799:                int j = 1;
1800:                boolean startOfLine = true;
1801:                for (int i = 0; i < elems.length; i++) {
1802:                    if (j == 1) {
1803:                        print("");
1804:                    } else {
1805:                        _print("  ");
1806:                    }
1807:                    _print("case " + getValueString(elems[i]) + ":");
1808:
1809:                    if (j == wrap) {
1810:                        _println("");
1811:                        startOfLine = true;
1812:                        j = 1;
1813:                    } else {
1814:                        j++;
1815:                        startOfLine = false;
1816:                    }
1817:                }
1818:                if (!startOfLine) {
1819:                    _println("");
1820:                }
1821:            }
1822:
1823:            /** Generate common code for a block of alternatives; return a postscript
1824:             * that needs to be generated at the end of the block.  Other routines
1825:             * may append else-clauses and such for error checking before the postfix
1826:             * is generated.
1827:             * If the grammar is a lexer, then generate alternatives in an order where
1828:             * alternatives requiring deeper lookahead are generated first, and
1829:             * EOF in the lookahead set reduces the depth of the lookahead.
1830:             * @param blk The block to generate
1831:             * @param noTestForSingle If true, then it does not generate a test for a single alternative.
1832:             */
1833:            public CppBlockFinishingInfo genCommonBlock(AlternativeBlock blk,
1834:                    boolean noTestForSingle) {
1835:                int nIF = 0;
1836:                boolean createdLL1Switch = false;
1837:                int closingBracesOfIFSequence = 0;
1838:                CppBlockFinishingInfo finishingInfo = new CppBlockFinishingInfo();
1839:                if (DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR)
1840:                    System.out.println("genCommonBlk(" + blk + ")");
1841:
1842:                // Save the AST generation state, and set it to that of the block
1843:                boolean savegenAST = genAST;
1844:                genAST = genAST && blk.getAutoGen();
1845:
1846:                boolean oldsaveTest = saveText;
1847:                saveText = saveText && blk.getAutoGen();
1848:
1849:                // Is this block inverted?  If so, generate special-case code
1850:                if (blk.not
1851:                        && analyzer.subruleCanBeInverted(blk,
1852:                                grammar instanceof  LexerGrammar)) {
1853:                    Lookahead p = analyzer.look(1, blk);
1854:                    // Variable assignment for labeled elements
1855:                    if (blk.getLabel() != null && syntacticPredLevel == 0) {
1856:                        println(blk.getLabel() + " = " + lt1Value + ";");
1857:                    }
1858:
1859:                    // AST
1860:                    genElementAST(blk);
1861:
1862:                    String astArgs = "";
1863:                    if (grammar instanceof  TreeWalkerGrammar) {
1864:                        if (usingCustomAST)
1865:                            astArgs = namespaceAntlr + "RefAST" + "(_t),";
1866:                        else
1867:                            astArgs = "_t,";
1868:                    }
1869:
1870:                    // match the bitset for the alternative
1871:                    println("match(" + astArgs
1872:                            + getBitsetName(markBitsetForGen(p.fset)) + ");");
1873:
1874:                    // tack on tree cursor motion if doing a tree walker
1875:                    if (grammar instanceof  TreeWalkerGrammar) {
1876:                        println("_t = _t->getNextSibling();");
1877:                    }
1878:                    return finishingInfo;
1879:                }
1880:
1881:                // Special handling for single alt
1882:                if (blk.getAlternatives().size() == 1) {
1883:                    Alternative alt = blk.getAlternativeAt(0);
1884:                    // Generate a warning if there is a synPred for single alt.
1885:                    if (alt.synPred != null) {
1886:                        antlrTool
1887:                                .warning(
1888:                                        "Syntactic predicate superfluous for single alternative",
1889:                                        grammar.getFilename(), blk
1890:                                                .getAlternativeAt(0).synPred
1891:                                                .getLine(), blk
1892:                                                .getAlternativeAt(0).synPred
1893:                                                .getColumn());
1894:                    }
1895:                    if (noTestForSingle) {
1896:                        if (alt.semPred != null) {
1897:                            // Generate validating predicate
1898:                            genSemPred(alt.semPred, blk.line);
1899:                        }
1900:                        genAlt(alt, blk);
1901:                        return finishingInfo;
1902:                    }
1903:                }
1904:
1905:                // count number of simple LL(1) cases; only do switch for
1906:                // many LL(1) cases (no preds, no end of token refs)
1907:                // We don't care about exit paths for (...)*, (...)+
1908:                // because we don't explicitly have a test for them
1909:                // as an alt in the loop.
1910:                //
1911:                // Also, we now count how many unicode lookahead sets
1912:                // there are--they must be moved to DEFAULT or ELSE
1913:                // clause.
1914:
1915:                int nLL1 = 0;
1916:                for (int i = 0; i < blk.getAlternatives().size(); i++) {
1917:                    Alternative a = blk.getAlternativeAt(i);
1918:                    if (suitableForCaseExpression(a))
1919:                        nLL1++;
1920:                }
1921:
1922:                // do LL(1) cases
1923:                if (nLL1 >= makeSwitchThreshold) {
1924:                    // Determine the name of the item to be compared
1925:                    String testExpr = lookaheadString(1);
1926:                    createdLL1Switch = true;
1927:                    // when parsing trees, convert null to valid tree node with NULL lookahead
1928:                    if (grammar instanceof  TreeWalkerGrammar) {
1929:                        println("if (_t == " + labeledElementASTInit + " )");
1930:                        tabs++;
1931:                        println("_t = ASTNULL;");
1932:                        tabs--;
1933:                    }
1934:                    println("switch ( " + testExpr + ") {");
1935:                    for (int i = 0; i < blk.alternatives.size(); i++) {
1936:                        Alternative alt = blk.getAlternativeAt(i);
1937:                        // ignore any non-LL(1) alts, predicated alts or end-of-token alts
1938:                        // or end-of-token alts for case expressions
1939:                        if (!suitableForCaseExpression(alt)) {
1940:                            continue;
1941:                        }
1942:                        Lookahead p = alt.cache[1];
1943:                        if (p.fset.degree() == 0 && !p.containsEpsilon()) {
1944:                            antlrTool
1945:                                    .warning(
1946:                                            "Alternate omitted due to empty prediction set",
1947:                                            grammar.getFilename(), alt.head
1948:                                                    .getLine(), alt.head
1949:                                                    .getColumn());
1950:                        } else {
1951:                            genCases(p.fset);
1952:                            println("{");
1953:                            tabs++;
1954:                            genAlt(alt, blk);
1955:                            println("break;");
1956:                            tabs--;
1957:                            println("}");
1958:                        }
1959:                    }
1960:                    println("default:");
1961:                    tabs++;
1962:                }
1963:
1964:                // do non-LL(1) and nondeterministic cases
1965:                // This is tricky in the lexer, because of cases like:
1966:                //     STAR : '*' ;
1967:                //     ASSIGN_STAR : "*=";
1968:                // Since nextToken is generated without a loop, then the STAR will
1969:                // have end-of-token as it's lookahead set for LA(2).  So, we must generate the
1970:                // alternatives containing trailing end-of-token in their lookahead sets *after*
1971:                // the alternatives without end-of-token.  This implements the usual
1972:                // lexer convention that longer matches come before shorter ones, e.g.
1973:                // "*=" matches ASSIGN_STAR not STAR
1974:                //
1975:                // For non-lexer grammars, this does not sort the alternates by depth
1976:                // Note that alts whose lookahead is purely end-of-token at k=1 end up
1977:                // as default or else clauses.
1978:                int startDepth = (grammar instanceof  LexerGrammar) ? grammar.maxk
1979:                        : 0;
1980:                for (int altDepth = startDepth; altDepth >= 0; altDepth--) {
1981:                    if (DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR)
1982:                        System.out.println("checking depth " + altDepth);
1983:                    for (int i = 0; i < blk.alternatives.size(); i++) {
1984:                        Alternative alt = blk.getAlternativeAt(i);
1985:                        if (DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR)
1986:                            System.out.println("genAlt: " + i);
1987:                        // if we made a switch above, ignore what we already took care
1988:                        // of.  Specifically, LL(1) alts with no preds
1989:                        // that do not have end-of-token in their prediction set
1990:                        if (createdLL1Switch && suitableForCaseExpression(alt)) {
1991:                            if (DEBUG_CODE_GENERATOR
1992:                                    || DEBUG_CPP_CODE_GENERATOR)
1993:                                System.out
1994:                                        .println("ignoring alt because it was in the switch");
1995:                            continue;
1996:                        }
1997:                        String e;
1998:
1999:                        boolean unpredicted = false;
2000:
2001:                        if (grammar instanceof  LexerGrammar) {
2002:                            // Calculate the "effective depth" of the alt, which is the max
2003:                            // depth at which cache[depth]!=end-of-token
2004:                            int effectiveDepth = alt.lookaheadDepth;
2005:                            if (effectiveDepth == GrammarAnalyzer.NONDETERMINISTIC) {
2006:                                // use maximum lookahead
2007:                                effectiveDepth = grammar.maxk;
2008:                            }
2009:                            while (effectiveDepth >= 1
2010:                                    && alt.cache[effectiveDepth]
2011:                                            .containsEpsilon()) {
2012:                                effectiveDepth--;
2013:                            }
2014:                            // Ignore alts whose effective depth is other than the ones we
2015:                            // are generating for this iteration.
2016:                            if (effectiveDepth != altDepth) {
2017:                                if (DEBUG_CODE_GENERATOR
2018:                                        || DEBUG_CPP_CODE_GENERATOR)
2019:                                    System.out
2020:                                            .println("ignoring alt because effectiveDepth!=altDepth;"
2021:                                                    + effectiveDepth
2022:                                                    + "!="
2023:                                                    + altDepth);
2024:                                continue;
2025:                            }
2026:                            unpredicted = lookaheadIsEmpty(alt, effectiveDepth);
2027:                            e = getLookaheadTestExpression(alt, effectiveDepth);
2028:                        } else {
2029:                            unpredicted = lookaheadIsEmpty(alt, grammar.maxk);
2030:                            e = getLookaheadTestExpression(alt, grammar.maxk);
2031:                        }
2032:
2033:                        // Was it a big unicode range that forced unsuitability
2034:                        // for a case expression?
2035:                        if (alt.cache[1].fset.degree() > caseSizeThreshold
2036:                                && suitableForCaseExpression(alt)) {
2037:                            if (nIF == 0) {
2038:                                // generate this only for the first if the elseif's
2039:                                // are covered by this one
2040:                                if (grammar instanceof  TreeWalkerGrammar) {
2041:                                    println("if (_t == "
2042:                                            + labeledElementASTInit + " )");
2043:                                    tabs++;
2044:                                    println("_t = ASTNULL;");
2045:                                    tabs--;
2046:                                }
2047:                                println("if " + e + " {");
2048:                            } else
2049:                                println("else if " + e + " {");
2050:                        } else if (unpredicted && alt.semPred == null
2051:                                && alt.synPred == null) {
2052:                            // The alt has empty prediction set and no
2053:                            // predicate to help out.  if we have not
2054:                            // generated a previous if, just put {...} around
2055:                            // the end-of-token clause
2056:                            if (nIF == 0) {
2057:                                println("{");
2058:                            } else {
2059:                                println("else {");
2060:                            }
2061:                            finishingInfo.needAnErrorClause = false;
2062:                        } else {
2063:                            // check for sem and syn preds
2064:                            // Add any semantic predicate expression to the lookahead test
2065:                            if (alt.semPred != null) {
2066:                                // if debugging, wrap the evaluation of the predicate in a method
2067:                                //
2068:                                // translate $ and # references
2069:                                ActionTransInfo tInfo = new ActionTransInfo();
2070:                                String actionStr = processActionForSpecialSymbols(
2071:                                        alt.semPred, blk.line, currentRule,
2072:                                        tInfo);
2073:                                // ignore translation info...we don't need to do anything with it.
2074:
2075:                                // call that will inform SemanticPredicateListeners of the
2076:                                // result
2077:                                if (grammar.debuggingOutput
2078:                                        && ((grammar instanceof  ParserGrammar) || (grammar instanceof  LexerGrammar)))
2079:                                    e = "("
2080:                                            + e
2081:                                            + "&& fireSemanticPredicateEvaluated(persistence.antlr.debug.SemanticPredicateEvent.PREDICTING,"
2082:                                            + //FIXME
2083:                                            addSemPred(charFormatter
2084:                                                    .escapeString(actionStr))
2085:                                            + "," + actionStr + "))";
2086:                                else
2087:                                    e = "(" + e + "&&(" + actionStr + "))";
2088:                            }
2089:
2090:                            // Generate any syntactic predicates
2091:                            if (nIF > 0) {
2092:                                if (alt.synPred != null) {
2093:                                    println("else {");
2094:                                    tabs++;
2095:                                    genSynPred(alt.synPred, e);
2096:                                    closingBracesOfIFSequence++;
2097:                                } else {
2098:                                    println("else if " + e + " {");
2099:                                }
2100:                            } else {
2101:                                if (alt.synPred != null) {
2102:                                    genSynPred(alt.synPred, e);
2103:                                } else {
2104:                                    // when parsing trees, convert null to valid tree node
2105:                                    // with NULL lookahead.
2106:                                    if (grammar instanceof  TreeWalkerGrammar) {
2107:                                        println("if (_t == "
2108:                                                + labeledElementASTInit + " )");
2109:                                        tabs++;
2110:                                        println("_t = ASTNULL;");
2111:                                        tabs--;
2112:                                    }
2113:                                    println("if " + e + " {");
2114:                                }
2115:                            }
2116:
2117:                        }
2118:
2119:                        nIF++;
2120:                        tabs++;
2121:                        genAlt(alt, blk);
2122:                        tabs--;
2123:                        println("}");
2124:                    }
2125:                }
2126:                String ps = "";
2127:                for (int i = 1; i <= closingBracesOfIFSequence; i++) {
2128:                    tabs--; // does JavaCodeGenerator need this?
2129:                    ps += "}";
2130:                }
2131:
2132:                // Restore the AST generation state
2133:                genAST = savegenAST;
2134:
2135:                // restore save text state
2136:                saveText = oldsaveTest;
2137:
2138:                // Return the finishing info.
2139:                if (createdLL1Switch) {
2140:                    tabs--;
2141:                    finishingInfo.postscript = ps + "}";
2142:                    finishingInfo.generatedSwitch = true;
2143:                    finishingInfo.generatedAnIf = nIF > 0;
2144:                    //return new CppBlockFinishingInfo(ps+"}",true,nIF>0); // close up switch statement
2145:
2146:                } else {
2147:                    finishingInfo.postscript = ps;
2148:                    finishingInfo.generatedSwitch = false;
2149:                    finishingInfo.generatedAnIf = nIF > 0;
2150:                    //return new CppBlockFinishingInfo(ps, false,nIF>0);
2151:                }
2152:                return finishingInfo;
2153:            }
2154:
2155:            private static boolean suitableForCaseExpression(Alternative a) {
2156:                return a.lookaheadDepth == 1 && a.semPred == null
2157:                        && !a.cache[1].containsEpsilon()
2158:                        && a.cache[1].fset.degree() <= caseSizeThreshold;
2159:            }
2160:
2161:            /** Generate code to link an element reference into the AST
2162:             */
2163:            private void genElementAST(AlternativeElement el) {
2164:
2165:                // handle case where you're not building trees, but are in tree walker.
2166:                // Just need to get labels set up.
2167:                if (grammar instanceof  TreeWalkerGrammar && !grammar.buildAST) {
2168:                    String elementRef;
2169:                    String astName;
2170:
2171:                    // Generate names and declarations of the AST variable(s)
2172:                    if (el.getLabel() == null) {
2173:                        elementRef = lt1Value;
2174:                        // Generate AST variables for unlabeled stuff
2175:                        astName = "tmp" + astVarNumber + "_AST";
2176:                        astVarNumber++;
2177:                        // Map the generated AST variable in the alternate
2178:                        mapTreeVariable(el, astName);
2179:                        // Generate an "input" AST variable also
2180:                        println(labeledElementASTType + " " + astName
2181:                                + "_in = " + elementRef + ";");
2182:                    }
2183:                    return;
2184:                }
2185:
2186:                if (grammar.buildAST && syntacticPredLevel == 0) {
2187:                    boolean needASTDecl = (genAST && (el.getLabel() != null || el
2188:                            .getAutoGenType() != GrammarElement.AUTO_GEN_BANG));
2189:
2190:                    // RK: if we have a grammar element always generate the decl
2191:                    // since some guy can access it from an action and we can't
2192:                    // peek ahead (well not without making a mess).
2193:                    // I'd prefer taking this out.
2194:                    if (el.getAutoGenType() != GrammarElement.AUTO_GEN_BANG
2195:                            && (el instanceof  TokenRefElement))
2196:                        needASTDecl = true;
2197:
2198:                    boolean doNoGuessTest = (grammar.hasSyntacticPredicate && needASTDecl);
2199:
2200:                    String elementRef;
2201:                    String astNameBase;
2202:
2203:                    // Generate names and declarations of the AST variable(s)
2204:                    if (el.getLabel() != null) {
2205:                        // if the element is labeled use that name...
2206:                        elementRef = el.getLabel();
2207:                        astNameBase = el.getLabel();
2208:                    } else {
2209:                        // else generate a temporary name...
2210:                        elementRef = lt1Value;
2211:                        // Generate AST variables for unlabeled stuff
2212:                        astNameBase = "tmp" + astVarNumber;
2213:                        astVarNumber++;
2214:                    }
2215:
2216:                    // Generate the declaration if required.
2217:                    if (needASTDecl) {
2218:                        if (el instanceof  GrammarAtom) {
2219:                            GrammarAtom ga = (GrammarAtom) el;
2220:                            if (ga.getASTNodeType() != null) {
2221:                                genASTDeclaration(el, astNameBase, "Ref"
2222:                                        + ga.getASTNodeType());
2223:                                //						println("Ref"+ga.getASTNodeType()+" " + astName + ";");
2224:                            } else {
2225:                                genASTDeclaration(el, astNameBase,
2226:                                        labeledElementASTType);
2227:                                //						println(labeledElementASTType+" " + astName + " = "+labeledElementASTInit+";");
2228:                            }
2229:                        } else {
2230:                            genASTDeclaration(el, astNameBase,
2231:                                    labeledElementASTType);
2232:                            //					println(labeledElementASTType+" " + astName + " = "+labeledElementASTInit+";");
2233:                        }
2234:                    }
2235:
2236:                    // for convenience..
2237:                    String astName = astNameBase + "_AST";
2238:
2239:                    // Map the generated AST variable in the alternate
2240:                    mapTreeVariable(el, astName);
2241:                    if (grammar instanceof  TreeWalkerGrammar) {
2242:                        // Generate an "input" AST variable also
2243:                        println(labeledElementASTType + " " + astName
2244:                                + "_in = " + labeledElementASTInit + ";");
2245:                    }
2246:
2247:                    // Enclose actions with !guessing
2248:                    if (doNoGuessTest) {
2249:                        println("if ( inputState->guessing == 0 ) {");
2250:                        tabs++;
2251:                    }
2252:
2253:                    // if something has a label assume it will be used
2254:                    // so we must initialize the RefAST
2255:                    if (el.getLabel() != null) {
2256:                        if (el instanceof  GrammarAtom) {
2257:                            println(astName
2258:                                    + " = "
2259:                                    + getASTCreateString((GrammarAtom) el,
2260:                                            elementRef) + ";");
2261:                        } else {
2262:                            println(astName + " = "
2263:                                    + getASTCreateString(elementRef) + ";");
2264:                        }
2265:                    }
2266:
2267:                    // if it has no label but a declaration exists initialize it.
2268:                    if (el.getLabel() == null && needASTDecl) {
2269:                        elementRef = lt1Value;
2270:                        if (el instanceof  GrammarAtom) {
2271:                            println(astName
2272:                                    + " = "
2273:                                    + getASTCreateString((GrammarAtom) el,
2274:                                            elementRef) + ";");
2275:                        } else {
2276:                            println(astName + " = "
2277:                                    + getASTCreateString(elementRef) + ";");
2278:                        }
2279:                        // Map the generated AST variable in the alternate
2280:                        if (grammar instanceof  TreeWalkerGrammar) {
2281:                            // set "input" AST variable also
2282:                            println(astName + "_in = " + elementRef + ";");
2283:                        }
2284:                    }
2285:
2286:                    if (genAST) {
2287:                        switch (el.getAutoGenType()) {
2288:                        case GrammarElement.AUTO_GEN_NONE:
2289:                            if (usingCustomAST
2290:                                    || (el instanceof  GrammarAtom && ((GrammarAtom) el)
2291:                                            .getASTNodeType() != null))
2292:                                println("astFactory->addASTChild(currentAST, "
2293:                                        + namespaceAntlr + "RefAST(" + astName
2294:                                        + "));");
2295:                            else
2296:                                println("astFactory->addASTChild(currentAST, "
2297:                                        + astName + ");");
2298:                            //						println("astFactory.addASTChild(currentAST, "+namespaceAntlr+"RefAST(" + astName + "));");
2299:                            break;
2300:                        case GrammarElement.AUTO_GEN_CARET:
2301:                            if (usingCustomAST
2302:                                    || (el instanceof  GrammarAtom && ((GrammarAtom) el)
2303:                                            .getASTNodeType() != null))
2304:                                println("astFactory->makeASTRoot(currentAST, "
2305:                                        + namespaceAntlr + "RefAST(" + astName
2306:                                        + "));");
2307:                            else
2308:                                println("astFactory->makeASTRoot(currentAST, "
2309:                                        + astName + ");");
2310:                            break;
2311:                        default:
2312:                            break;
2313:                        }
2314:                    }
2315:                    if (doNoGuessTest) {
2316:                        tabs--;
2317:                        println("}");
2318:                    }
2319:                }
2320:            }
2321:
2322:            /** Close the try block and generate catch phrases
2323:             * if the element has a labeled handler in the rule
2324:             */
2325:            private void genErrorCatchForElement(AlternativeElement el) {
2326:                if (el.getLabel() == null)
2327:                    return;
2328:                String r = el.enclosingRuleName;
2329:                if (grammar instanceof  LexerGrammar) {
2330:                    r = CodeGenerator.encodeLexerRuleName(el.enclosingRuleName);
2331:                }
2332:                RuleSymbol rs = (RuleSymbol) grammar.getSymbol(r);
2333:                if (rs == null) {
2334:                    antlrTool.panic("Enclosing rule not found!");
2335:                }
2336:                ExceptionSpec ex = rs.block.findExceptionSpec(el.getLabel());
2337:                if (ex != null) {
2338:                    tabs--;
2339:                    println("}");
2340:                    genErrorHandler(ex);
2341:                }
2342:            }
2343:
2344:            /** Generate the catch phrases for a user-specified error handler */
2345:            private void genErrorHandler(ExceptionSpec ex) {
2346:                // Each ExceptionHandler in the ExceptionSpec is a separate catch
2347:                for (int i = 0; i < ex.handlers.size(); i++) {
2348:                    ExceptionHandler handler = (ExceptionHandler) ex.handlers
2349:                            .elementAt(i);
2350:                    // Generate catch phrase
2351:                    println("catch (" + handler.exceptionTypeAndName.getText()
2352:                            + ") {");
2353:                    tabs++;
2354:                    if (grammar.hasSyntacticPredicate) {
2355:                        println("if (inputState->guessing==0) {");
2356:                        tabs++;
2357:                    }
2358:
2359:                    // When not guessing, execute user handler action
2360:                    ActionTransInfo tInfo = new ActionTransInfo();
2361:                    genLineNo(handler.action);
2362:                    printAction(processActionForSpecialSymbols(handler.action
2363:                            .getText(), handler.action.getLine(), currentRule,
2364:                            tInfo));
2365:                    genLineNo2();
2366:
2367:                    if (grammar.hasSyntacticPredicate) {
2368:                        tabs--;
2369:                        println("} else {");
2370:                        tabs++;
2371:                        // When guessing, rethrow exception
2372:                        println("throw;");
2373:                        tabs--;
2374:                        println("}");
2375:                    }
2376:                    // Close catch phrase
2377:                    tabs--;
2378:                    println("}");
2379:                }
2380:            }
2381:
2382:            /** Generate a try { opening if the element has a labeled handler in the rule */
2383:            private void genErrorTryForElement(AlternativeElement el) {
2384:                if (el.getLabel() == null)
2385:                    return;
2386:                String r = el.enclosingRuleName;
2387:                if (grammar instanceof  LexerGrammar) {
2388:                    r = CodeGenerator.encodeLexerRuleName(el.enclosingRuleName);
2389:                }
2390:                RuleSymbol rs = (RuleSymbol) grammar.getSymbol(r);
2391:                if (rs == null) {
2392:                    antlrTool.panic("Enclosing rule not found!");
2393:                }
2394:                ExceptionSpec ex = rs.block.findExceptionSpec(el.getLabel());
2395:                if (ex != null) {
2396:                    println("try { // for error handling");
2397:                    tabs++;
2398:                }
2399:            }
2400:
2401:            /** Generate a header that is common to all C++ files */
2402:            protected void genHeader(String fileName) {
2403:                println("/* $ANTLR " + antlrTool.version + ": " + "\""
2404:                        + antlrTool.fileMinusPath(antlrTool.grammarFile) + "\""
2405:                        + " -> " + "\"" + fileName + "\"$ */");
2406:            }
2407:
2408:            // these are unique to C++ mode
2409:            public void genInclude(LexerGrammar g) throws IOException {
2410:                outputFile = grammar.getClassName() + ".hpp";
2411:                outputLine = 1;
2412:                currentOutput = antlrTool.openOutputFile(outputFile);
2413:                //SAS: changed for proper text file io
2414:
2415:                genAST = false; // no way to gen trees.
2416:                saveText = true; // save consumed characters.
2417:
2418:                tabs = 0;
2419:
2420:                // Generate a guard wrapper
2421:                println("#ifndef INC_" + grammar.getClassName() + "_hpp_");
2422:                println("#define INC_" + grammar.getClassName() + "_hpp_");
2423:                println("");
2424:
2425:                printHeaderAction(preIncludeHpp);
2426:
2427:                println("#include <antlr/config.hpp>");
2428:
2429:                // Generate header common to all C++ output files
2430:                genHeader(outputFile);
2431:
2432:                // Generate header specific to lexer header file
2433:                println("#include <antlr/CommonToken.hpp>");
2434:                println("#include <antlr/InputBuffer.hpp>");
2435:                println("#include <antlr/BitSet.hpp>");
2436:                println("#include \"" + grammar.tokenManager.getName()
2437:                        + TokenTypesFileSuffix + ".hpp\"");
2438:
2439:                // Find the name of the super class
2440:                String sup = null;
2441:                if (grammar.super Class != null) {
2442:                    sup = grammar.super Class;
2443:
2444:                    println("\n// Include correct superclass header with a header statement for example:");
2445:                    println("// header \"post_include_hpp\" {");
2446:                    println("// #include \"" + sup + ".hpp\"");
2447:                    println("// }");
2448:                    println("// Or....");
2449:                    println("// header {");
2450:                    println("// #include \"" + sup + ".hpp\"");
2451:                    println("// }\n");
2452:                } else {
2453:                    sup = grammar.getSuperClass();
2454:                    if (sup.lastIndexOf('.') != -1)
2455:                        sup = sup.substring(sup.lastIndexOf('.') + 1);
2456:                    println("#include <antlr/" + sup + ".hpp>");
2457:                    sup = namespaceAntlr + sup;
2458:                }
2459:
2460:                // Do not use printAction because we assume tabs==0
2461:                printHeaderAction(postIncludeHpp);
2462:
2463:                if (nameSpace != null)
2464:                    nameSpace.emitDeclarations(currentOutput);
2465:
2466:                printHeaderAction("");
2467:
2468:                // print javadoc comment if any
2469:                if (grammar.comment != null) {
2470:                    _println(grammar.comment);
2471:                }
2472:
2473:                // Generate lexer class definition
2474:                print("class CUSTOM_API " + grammar.getClassName()
2475:                        + " : public " + sup);
2476:                println(", public " + grammar.tokenManager.getName()
2477:                        + TokenTypesFileSuffix);
2478:
2479:                Token tsuffix = (Token) grammar.options
2480:                        .get("classHeaderSuffix");
2481:                if (tsuffix != null) {
2482:                    String suffix = StringUtils.stripFrontBack(tsuffix
2483:                            .getText(), "\"", "\"");
2484:                    if (suffix != null) {
2485:                        print(", " + suffix); // must be an interface name for Java
2486:                    }
2487:                }
2488:                println("{");
2489:
2490:                // Generate user-defined lexer class members
2491:                if (grammar.classMemberAction != null) {
2492:                    genLineNo(grammar.classMemberAction);
2493:                    print(processActionForSpecialSymbols(
2494:                            grammar.classMemberAction.getText(),
2495:                            grammar.classMemberAction.getLine(), currentRule,
2496:                            null));
2497:                    genLineNo2();
2498:                }
2499:
2500:                // Generate initLiterals() method
2501:                tabs = 0;
2502:                println("private:");
2503:                tabs = 1;
2504:                println("void initLiterals();");
2505:
2506:                // Generate getCaseSensitiveLiterals() method
2507:                tabs = 0;
2508:                println("public:");
2509:                tabs = 1;
2510:                println("bool getCaseSensitiveLiterals() const");
2511:                println("{");
2512:                tabs++;
2513:                println("return " + g.caseSensitiveLiterals + ";");
2514:                tabs--;
2515:                println("}");
2516:
2517:                // Make constructors public
2518:                tabs = 0;
2519:                println("public:");
2520:                tabs = 1;
2521:
2522:                if (noConstructors) {
2523:                    tabs = 0;
2524:                    println("#if 0");
2525:                    println("// constructor creation turned of with 'noConstructor' option");
2526:                    tabs = 1;
2527:                }
2528:
2529:                // Generate the constructor from std::istream
2530:                println(grammar.getClassName() + "(" + namespaceStd
2531:                        + "istream& in);");
2532:
2533:                // Generate the constructor from InputBuffer
2534:                println(grammar.getClassName() + "(" + namespaceAntlr
2535:                        + "InputBuffer& ib);");
2536:
2537:                println(grammar.getClassName() + "(const " + namespaceAntlr
2538:                        + "LexerSharedInputState& state);");
2539:                if (noConstructors) {
2540:                    tabs = 0;
2541:                    println("// constructor creation turned of with 'noConstructor' option");
2542:                    println("#endif");
2543:                    tabs = 1;
2544:                }
2545:
2546:                // Generate nextToken() rule.
2547:                // nextToken() is a synthetic lexer rule that is the implicit OR of all
2548:                // user-defined lexer rules.
2549:                println(namespaceAntlr + "RefToken nextToken();");
2550:
2551:                // Generate code for each rule in the lexer
2552:                Enumeration ids = grammar.rules.elements();
2553:                while (ids.hasMoreElements()) {
2554:                    RuleSymbol sym = (RuleSymbol) ids.nextElement();
2555:                    // Don't generate the synthetic rules
2556:                    if (!sym.getId().equals("mnextToken")) {
2557:                        genRuleHeader(sym, false);
2558:                    }
2559:                    exitIfError();
2560:                }
2561:
2562:                // Make the rest private
2563:                tabs = 0;
2564:                println("private:");
2565:                tabs = 1;
2566:
2567:                // generate the rule name array for debugging
2568:                if (grammar.debuggingOutput) {
2569:                    println("static const char* _ruleNames[];");
2570:                }
2571:
2572:                // Generate the semantic predicate map for debugging
2573:                if (grammar.debuggingOutput)
2574:                    println("static const char* _semPredNames[];");
2575:
2576:                // Generate the bitsets used throughout the lexer
2577:                genBitsetsHeader(bitsetsUsed,
2578:                        ((LexerGrammar) grammar).charVocabulary.size());
2579:
2580:                tabs = 0;
2581:                println("};");
2582:                println("");
2583:                if (nameSpace != null)
2584:                    nameSpace.emitClosures(currentOutput);
2585:
2586:                // Generate a guard wrapper
2587:                println("#endif /*INC_" + grammar.getClassName() + "_hpp_*/");
2588:
2589:                // Close the lexer output stream
2590:                currentOutput.close();
2591:                currentOutput = null;
2592:            }
2593:
2594:            public void genInclude(ParserGrammar g) throws IOException {
2595:                // Open the output stream for the parser and set the currentOutput
2596:                outputFile = grammar.getClassName() + ".hpp";
2597:                outputLine = 1;
2598:                currentOutput = antlrTool.openOutputFile(outputFile);
2599:                //SAS: changed for proper text file io
2600:
2601:                genAST = grammar.buildAST;
2602:
2603:                tabs = 0;
2604:
2605:                // Generate a guard wrapper
2606:                println("#ifndef INC_" + grammar.getClassName() + "_hpp_");
2607:                println("#define INC_" + grammar.getClassName() + "_hpp_");
2608:                println("");
2609:                printHeaderAction(preIncludeHpp);
2610:                println("#include <antlr/config.hpp>");
2611:
2612:                // Generate the header common to all output files.
2613:                genHeader(outputFile);
2614:
2615:                // Generate header for the parser
2616:                println("#include <antlr/TokenStream.hpp>");
2617:                println("#include <antlr/TokenBuffer.hpp>");
2618:                println("#include \"" + grammar.tokenManager.getName()
2619:                        + TokenTypesFileSuffix + ".hpp\"");
2620:
2621:                // Generate parser class definition
2622:                String sup = null;
2623:                if (grammar.super Class != null) {
2624:                    sup = grammar.super Class;
2625:                    println("\n// Include correct superclass header with a header statement for example:");
2626:                    println("// header \"post_include_hpp\" {");
2627:                    println("// #include \"" + sup + ".hpp\"");
2628:                    println("// }");
2629:                    println("// Or....");
2630:                    println("// header {");
2631:                    println("// #include \"" + sup + ".hpp\"");
2632:                    println("// }\n");
2633:                } else {
2634:                    sup = grammar.getSuperClass();
2635:                    if (sup.lastIndexOf('.') != -1)
2636:                        sup = sup.substring(sup.lastIndexOf('.') + 1);
2637:                    println("#include <antlr/" + sup + ".hpp>");
2638:                    sup = namespaceAntlr + sup;
2639:                }
2640:                println("");
2641:
2642:                // Do not use printAction because we assume tabs==0
2643:                printHeaderAction(postIncludeHpp);
2644:
2645:                if (nameSpace != null)
2646:                    nameSpace.emitDeclarations(currentOutput);
2647:
2648:                printHeaderAction("");
2649:
2650:                // print javadoc comment if any
2651:                if (grammar.comment != null) {
2652:                    _println(grammar.comment);
2653:                }
2654:
2655:                // generate the actual class definition
2656:                print("class CUSTOM_API " + grammar.getClassName()
2657:                        + " : public " + sup);
2658:                println(", public " + grammar.tokenManager.getName()
2659:                        + TokenTypesFileSuffix);
2660:
2661:                Token tsuffix = (Token) grammar.options
2662:                        .get("classHeaderSuffix");
2663:                if (tsuffix != null) {
2664:                    String suffix = StringUtils.stripFrontBack(tsuffix
2665:                            .getText(), "\"", "\"");
2666:                    if (suffix != null)
2667:                        print(", " + suffix); // must be an interface name for Java
2668:                }
2669:                println("{");
2670:
2671:                // set up an array of all the rule names so the debugger can
2672:                // keep track of them only by number -- less to store in tree...
2673:                if (grammar.debuggingOutput) {
2674:                    println("public: static const char* _ruleNames[];");
2675:                }
2676:                // Generate user-defined parser class members
2677:                if (grammar.classMemberAction != null) {
2678:                    genLineNo(grammar.classMemberAction.getLine());
2679:                    print(processActionForSpecialSymbols(
2680:                            grammar.classMemberAction.getText(),
2681:                            grammar.classMemberAction.getLine(), currentRule,
2682:                            null));
2683:                    genLineNo2();
2684:                }
2685:                println("public:");
2686:                tabs = 1;
2687:                println("void initializeASTFactory( " + namespaceAntlr
2688:                        + "ASTFactory& factory );");
2689:                //		println("// called from constructors");
2690:                //		println("void _initialize( void );");
2691:
2692:                // Generate parser class constructor from TokenBuffer
2693:                tabs = 0;
2694:                if (noConstructors) {
2695:                    println("#if 0");
2696:                    println("// constructor creation turned of with 'noConstructor' option");
2697:                }
2698:                println("protected:");
2699:                tabs = 1;
2700:                println(grammar.getClassName() + "(" + namespaceAntlr
2701:                        + "TokenBuffer& tokenBuf, int k);");
2702:                tabs = 0;
2703:                println("public:");
2704:                tabs = 1;
2705:                println(grammar.getClassName() + "(" + namespaceAntlr
2706:                        + "TokenBuffer& tokenBuf);");
2707:
2708:                // Generate parser class constructor from TokenStream
2709:                tabs = 0;
2710:                println("protected:");
2711:                tabs = 1;
2712:                println(grammar.getClassName() + "(" + namespaceAntlr
2713:                        + "TokenStream& lexer, int k);");
2714:                tabs = 0;
2715:                println("public:");
2716:                tabs = 1;
2717:                println(grammar.getClassName() + "(" + namespaceAntlr
2718:                        + "TokenStream& lexer);");
2719:
2720:                println(grammar.getClassName() + "(const " + namespaceAntlr
2721:                        + "ParserSharedInputState& state);");
2722:                if (noConstructors) {
2723:                    tabs = 0;
2724:                    println("// constructor creation turned of with 'noConstructor' option");
2725:                    println("#endif");
2726:                    tabs = 1;
2727:                }
2728:
2729:                println("int getNumTokens() const");
2730:                println("{");
2731:                tabs++;
2732:                println("return " + grammar.getClassName() + "::NUM_TOKENS;");
2733:                tabs--;
2734:                println("}");
2735:                println("const char* getTokenName( int type ) const");
2736:                println("{");
2737:                tabs++;
2738:                println("if( type > getNumTokens() ) return 0;");
2739:                println("return " + grammar.getClassName()
2740:                        + "::tokenNames[type];");
2741:                tabs--;
2742:                println("}");
2743:                println("const char* const* getTokenNames() const");
2744:                println("{");
2745:                tabs++;
2746:                println("return " + grammar.getClassName() + "::tokenNames;");
2747:                tabs--;
2748:                println("}");
2749:
2750:                // Generate code for each rule in the grammar
2751:                Enumeration ids = grammar.rules.elements();
2752:                while (ids.hasMoreElements()) {
2753:                    GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
2754:                    if (sym instanceof  RuleSymbol) {
2755:                        RuleSymbol rs = (RuleSymbol) sym;
2756:                        genRuleHeader(rs, rs.references.size() == 0);
2757:                    }
2758:                    exitIfError();
2759:                }
2760:
2761:                // RK: when we are using a custom ast override Parser::getAST to return
2762:                // the custom AST type. Ok, this does not work anymore with newer
2763:                // compilers gcc 3.2.x and up. The reference counter is probably
2764:                // getting in the way.
2765:                // So now we just patch the return type back to RefAST
2766:                tabs = 0;
2767:                println("public:");
2768:                tabs = 1;
2769:                println(namespaceAntlr + "RefAST getAST()");
2770:                println("{");
2771:                if (usingCustomAST) {
2772:                    tabs++;
2773:                    println("return " + namespaceAntlr + "RefAST(returnAST);");
2774:                    tabs--;
2775:                } else {
2776:                    tabs++;
2777:                    println("return returnAST;");
2778:                    tabs--;
2779:                }
2780:                println("}");
2781:                println("");
2782:
2783:                tabs = 0;
2784:                println("protected:");
2785:                tabs = 1;
2786:                println(labeledElementASTType + " returnAST;");
2787:
2788:                // Make the rest private
2789:                tabs = 0;
2790:                println("private:");
2791:                tabs = 1;
2792:
2793:                // Generate the token names
2794:                println("static const char* tokenNames[];");
2795:                // and how many there are of them
2796:                _println("#ifndef NO_STATIC_CONSTS");
2797:                println("static const int NUM_TOKENS = "
2798:                        + grammar.tokenManager.getVocabulary().size() + ";");
2799:                _println("#else");
2800:                println("enum {");
2801:                println("\tNUM_TOKENS = "
2802:                        + grammar.tokenManager.getVocabulary().size());
2803:                println("};");
2804:                _println("#endif");
2805:
2806:                // Generate the bitsets used throughout the grammar
2807:                genBitsetsHeader(bitsetsUsed, grammar.tokenManager
2808:                        .maxTokenType());
2809:
2810:                // Generate the semantic predicate map for debugging
2811:                if (grammar.debuggingOutput)
2812:                    println("static const char* _semPredNames[];");
2813:
2814:                // Close class definition
2815:                tabs = 0;
2816:                println("};");
2817:                println("");
2818:                if (nameSpace != null)
2819:                    nameSpace.emitClosures(currentOutput);
2820:
2821:                // Generate a guard wrapper
2822:                println("#endif /*INC_" + grammar.getClassName() + "_hpp_*/");
2823:
2824:                // Close the parser output stream
2825:                currentOutput.close();
2826:                currentOutput = null;
2827:            }
2828:
2829:            public void genInclude(TreeWalkerGrammar g) throws IOException {
2830:                // Open the output stream for the parser and set the currentOutput
2831:                outputFile = grammar.getClassName() + ".hpp";
2832:                outputLine = 1;
2833:                currentOutput = antlrTool.openOutputFile(outputFile);
2834:                //SAS: changed for proper text file io
2835:
2836:                genAST = grammar.buildAST;
2837:                tabs = 0;
2838:
2839:                // Generate a guard wrapper
2840:                println("#ifndef INC_" + grammar.getClassName() + "_hpp_");
2841:                println("#define INC_" + grammar.getClassName() + "_hpp_");
2842:                println("");
2843:                printHeaderAction(preIncludeHpp);
2844:                println("#include <antlr/config.hpp>");
2845:                println("#include \"" + grammar.tokenManager.getName()
2846:                        + TokenTypesFileSuffix + ".hpp\"");
2847:
2848:                // Generate the header common to all output files.
2849:                genHeader(outputFile);
2850:
2851:                // Find the name of the super class
2852:                String sup = null;
2853:                if (grammar.super Class != null) {
2854:                    sup = grammar.super Class;
2855:                    println("\n// Include correct superclass header with a header statement for example:");
2856:                    println("// header \"post_include_hpp\" {");
2857:                    println("// #include \"" + sup + ".hpp\"");
2858:                    println("// }");
2859:                    println("// Or....");
2860:                    println("// header {");
2861:                    println("// #include \"" + sup + ".hpp\"");
2862:                    println("// }\n");
2863:                } else {
2864:                    sup = grammar.getSuperClass();
2865:                    if (sup.lastIndexOf('.') != -1)
2866:                        sup = sup.substring(sup.lastIndexOf('.') + 1);
2867:                    println("#include <antlr/" + sup + ".hpp>");
2868:                    sup = namespaceAntlr + sup;
2869:                }
2870:                println("");
2871:
2872:                // Generate header for the parser
2873:                //
2874:                // Do not use printAction because we assume tabs==0
2875:                printHeaderAction(postIncludeHpp);
2876:
2877:                if (nameSpace != null)
2878:                    nameSpace.emitDeclarations(currentOutput);
2879:
2880:                printHeaderAction("");
2881:
2882:                // print javadoc comment if any
2883:                if (grammar.comment != null) {
2884:                    _println(grammar.comment);
2885:                }
2886:
2887:                // Generate parser class definition
2888:                print("class CUSTOM_API " + grammar.getClassName()
2889:                        + " : public " + sup);
2890:                println(", public " + grammar.tokenManager.getName()
2891:                        + TokenTypesFileSuffix);
2892:
2893:                Token tsuffix = (Token) grammar.options
2894:                        .get("classHeaderSuffix");
2895:                if (tsuffix != null) {
2896:                    String suffix = StringUtils.stripFrontBack(tsuffix
2897:                            .getText(), "\"", "\"");
2898:                    if (suffix != null) {
2899:                        print(", " + suffix); // must be an interface name for Java
2900:                    }
2901:                }
2902:                println("{");
2903:
2904:                // Generate user-defined parser class members
2905:                if (grammar.classMemberAction != null) {
2906:                    genLineNo(grammar.classMemberAction.getLine());
2907:                    print(processActionForSpecialSymbols(
2908:                            grammar.classMemberAction.getText(),
2909:                            grammar.classMemberAction.getLine(), currentRule,
2910:                            null));
2911:                    genLineNo2();
2912:                }
2913:
2914:                // Generate default parser class constructor
2915:                tabs = 0;
2916:                println("public:");
2917:
2918:                if (noConstructors) {
2919:                    println("#if 0");
2920:                    println("// constructor creation turned of with 'noConstructor' option");
2921:                }
2922:                tabs = 1;
2923:                println(grammar.getClassName() + "();");
2924:                if (noConstructors) {
2925:                    tabs = 0;
2926:                    println("#endif");
2927:                    tabs = 1;
2928:                }
2929:
2930:                // Generate declaration for the initializeFactory method
2931:                println("static void initializeASTFactory( " + namespaceAntlr
2932:                        + "ASTFactory& factory );");
2933:
2934:                println("int getNumTokens() const");
2935:                println("{");
2936:                tabs++;
2937:                println("return " + grammar.getClassName() + "::NUM_TOKENS;");
2938:                tabs--;
2939:                println("}");
2940:                println("const char* getTokenName( int type ) const");
2941:                println("{");
2942:                tabs++;
2943:                println("if( type > getNumTokens() ) return 0;");
2944:                println("return " + grammar.getClassName()
2945:                        + "::tokenNames[type];");
2946:                tabs--;
2947:                println("}");
2948:                println("const char* const* getTokenNames() const");
2949:                println("{");
2950:                tabs++;
2951:                println("return " + grammar.getClassName() + "::tokenNames;");
2952:                tabs--;
2953:                println("}");
2954:
2955:                // Generate code for each rule in the grammar
2956:                Enumeration ids = grammar.rules.elements();
2957:                String ruleNameInits = "";
2958:                while (ids.hasMoreElements()) {
2959:                    GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
2960:                    if (sym instanceof  RuleSymbol) {
2961:                        RuleSymbol rs = (RuleSymbol) sym;
2962:                        genRuleHeader(rs, rs.references.size() == 0);
2963:                    }
2964:                    exitIfError();
2965:                }
2966:                tabs = 0;
2967:                println("public:");
2968:                tabs = 1;
2969:                println(namespaceAntlr + "RefAST getAST()");
2970:                println("{");
2971:                if (usingCustomAST) {
2972:                    tabs++;
2973:                    println("return " + namespaceAntlr + "RefAST(returnAST);");
2974:                    tabs--;
2975:                } else {
2976:                    tabs++;
2977:                    println("return returnAST;");
2978:                    tabs--;
2979:                }
2980:                println("}");
2981:                println("");
2982:
2983:                tabs = 0;
2984:                println("protected:");
2985:                tabs = 1;
2986:                println(labeledElementASTType + " returnAST;");
2987:                println(labeledElementASTType + " _retTree;");
2988:
2989:                // Make the rest private
2990:                tabs = 0;
2991:                println("private:");
2992:                tabs = 1;
2993:
2994:                // Generate the token names
2995:                println("static const char* tokenNames[];");
2996:                // and how many there are of them
2997:                _println("#ifndef NO_STATIC_CONSTS");
2998:                println("static const int NUM_TOKENS = "
2999:                        + grammar.tokenManager.getVocabulary().size() + ";");
3000:                _println("#else");
3001:                println("enum {");
3002:                println("\tNUM_TOKENS = "
3003:                        + grammar.tokenManager.getVocabulary().size());
3004:                println("};");
3005:                _println("#endif");
3006:
3007:                // Generate the bitsets used throughout the grammar
3008:                genBitsetsHeader(bitsetsUsed, grammar.tokenManager
3009:                        .maxTokenType());
3010:
3011:                // Close class definition
3012:                tabs = 0;
3013:                println("};");
3014:                println("");
3015:                if (nameSpace != null)
3016:                    nameSpace.emitClosures(currentOutput);
3017:
3018:                // Generate a guard wrapper
3019:                println("#endif /*INC_" + grammar.getClassName() + "_hpp_*/");
3020:
3021:                // Close the parser output stream
3022:                currentOutput.close();
3023:                currentOutput = null;
3024:            }
3025:
3026:            /// for convenience
3027:            protected void genASTDeclaration(AlternativeElement el) {
3028:                genASTDeclaration(el, labeledElementASTType);
3029:            }
3030:
3031:            /// for convenience
3032:            protected void genASTDeclaration(AlternativeElement el,
3033:                    String node_type) {
3034:                genASTDeclaration(el, el.getLabel(), node_type);
3035:            }
3036:
3037:            /// Generate (if not already done) a declaration for the AST for el.
3038:            protected void genASTDeclaration(AlternativeElement el,
3039:                    String var_name, String node_type) {
3040:                // already declared?
3041:                if (declaredASTVariables.contains(el))
3042:                    return;
3043:
3044:                String init = labeledElementASTInit;
3045:
3046:                if (el instanceof  GrammarAtom
3047:                        && ((GrammarAtom) el).getASTNodeType() != null)
3048:                    init = "Ref" + ((GrammarAtom) el).getASTNodeType() + "("
3049:                            + labeledElementASTInit + ")";
3050:
3051:                // emit code
3052:                println(node_type + " " + var_name + "_AST = " + init + ";");
3053:
3054:                // mark as declared
3055:                declaredASTVariables.put(el, el);
3056:            }
3057:
3058:            private void genLiteralsTest() {
3059:                println("_ttype = testLiteralsTable(_ttype);");
3060:            }
3061:
3062:            private void genLiteralsTestForPartialToken() {
3063:                println("_ttype = testLiteralsTable(text.substr(_begin, text.length()-_begin),_ttype);");
3064:            }
3065:
3066:            protected void genMatch(BitSet b) {
3067:            }
3068:
3069:            protected void genMatch(GrammarAtom atom) {
3070:                if (atom instanceof  StringLiteralElement) {
3071:                    if (grammar instanceof  LexerGrammar) {
3072:                        genMatchUsingAtomText(atom);
3073:                    } else {
3074:                        genMatchUsingAtomTokenType(atom);
3075:                    }
3076:                } else if (atom instanceof  CharLiteralElement) {
3077:                    if (grammar instanceof  LexerGrammar) {
3078:                        genMatchUsingAtomText(atom);
3079:                    } else {
3080:                        antlrTool
3081:                                .error("cannot ref character literals in grammar: "
3082:                                        + atom);
3083:                    }
3084:                } else if (atom instanceof  TokenRefElement) {
3085:                    genMatchUsingAtomTokenType(atom);
3086:                } else if (atom instanceof  WildcardElement) {
3087:                    gen((WildcardElement) atom);
3088:                }
3089:            }
3090:
3091:            protected void genMatchUsingAtomText(GrammarAtom atom) {
3092:                // match() for trees needs the _t cursor
3093:                String astArgs = "";
3094:                if (grammar instanceof  TreeWalkerGrammar) {
3095:                    if (usingCustomAST)
3096:                        astArgs = namespaceAntlr + "RefAST" + "(_t),";
3097:                    else
3098:                        astArgs = "_t,";
3099:                }
3100:
3101:                // if in lexer and ! on element, save buffer index to kill later
3102:                if (grammar instanceof  LexerGrammar
3103:                        && (!saveText || atom.getAutoGenType() == GrammarElement.AUTO_GEN_BANG)) {
3104:                    println("_saveIndex = text.length();");
3105:                }
3106:
3107:                print(atom.not ? "matchNot(" : "match(");
3108:                _print(astArgs);
3109:
3110:                // print out what to match
3111:                if (atom.atomText.equals("EOF")) {
3112:                    // horrible hack to handle EOF case
3113:                    _print(namespaceAntlr + "Token::EOF_TYPE");
3114:                } else {
3115:                    if (grammar instanceof  LexerGrammar) // lexer needs special handling
3116:                    {
3117:                        String cppstring = convertJavaToCppString(atom.atomText);
3118:                        _print(cppstring);
3119:                    } else
3120:                        _print(atom.atomText);
3121:                }
3122:
3123:                _println(");");
3124:
3125:                if (grammar instanceof  LexerGrammar
3126:                        && (!saveText || atom.getAutoGenType() == GrammarElement.AUTO_GEN_BANG)) {
3127:                    println("text.erase(_saveIndex);"); // kill text atom put in buffer
3128:                }
3129:            }
3130:
3131:            protected void genMatchUsingAtomTokenType(GrammarAtom atom) {
3132:                // match() for trees needs the _t cursor
3133:                String astArgs = "";
3134:                if (grammar instanceof  TreeWalkerGrammar) {
3135:                    if (usingCustomAST)
3136:                        astArgs = namespaceAntlr + "RefAST" + "(_t),";
3137:                    else
3138:                        astArgs = "_t,";
3139:                }
3140:
3141:                // If the literal can be mangled, generate the symbolic constant instead
3142:                String s = astArgs + getValueString(atom.getType());
3143:
3144:                // matching
3145:                println((atom.not ? "matchNot(" : "match(") + s + ");");
3146:            }
3147:
3148:            /** Generate the nextToken() rule.
3149:             * nextToken() is a synthetic lexer rule that is the implicit OR of all
3150:             * user-defined lexer rules.
3151:             * @param RuleBlock
3152:             */
3153:            public void genNextToken() {
3154:                // Are there any public rules?  If not, then just generate a
3155:                // fake nextToken().
3156:                boolean hasPublicRules = false;
3157:                for (int i = 0; i < grammar.rules.size(); i++) {
3158:                    RuleSymbol rs = (RuleSymbol) grammar.rules.elementAt(i);
3159:                    if (rs.isDefined() && rs.access.equals("public")) {
3160:                        hasPublicRules = true;
3161:                        break;
3162:                    }
3163:                }
3164:                if (!hasPublicRules) {
3165:                    println("");
3166:                    println(namespaceAntlr + "RefToken "
3167:                            + grammar.getClassName()
3168:                            + "::nextToken() { return " + namespaceAntlr
3169:                            + "RefToken(new " + namespaceAntlr + "CommonToken("
3170:                            + namespaceAntlr + "Token::EOF_TYPE, \"\")); }");
3171:                    println("");
3172:                    return;
3173:                }
3174:
3175:                // Create the synthesized nextToken() rule
3176:                RuleBlock nextTokenBlk = MakeGrammar.createNextTokenRule(
3177:                        grammar, grammar.rules, "nextToken");
3178:                // Define the nextToken rule symbol
3179:                RuleSymbol nextTokenRs = new RuleSymbol("mnextToken");
3180:                nextTokenRs.setDefined();
3181:                nextTokenRs.setBlock(nextTokenBlk);
3182:                nextTokenRs.access = "private";
3183:                grammar.define(nextTokenRs);
3184:                // Analyze the nextToken rule
3185:                boolean ok = grammar.theLLkAnalyzer.deterministic(nextTokenBlk);
3186:
3187:                // Generate the next token rule
3188:                String filterRule = null;
3189:                if (((LexerGrammar) grammar).filterMode) {
3190:                    filterRule = ((LexerGrammar) grammar).filterRule;
3191:                }
3192:
3193:                println("");
3194:                println(namespaceAntlr + "RefToken " + grammar.getClassName()
3195:                        + "::nextToken()");
3196:                println("{");
3197:                tabs++;
3198:                println(namespaceAntlr + "RefToken theRetToken;");
3199:                println("for (;;) {");
3200:                tabs++;
3201:                println(namespaceAntlr + "RefToken theRetToken;");
3202:                println("int _ttype = " + namespaceAntlr
3203:                        + "Token::INVALID_TYPE;");
3204:                if (((LexerGrammar) grammar).filterMode) {
3205:                    println("setCommitToPath(false);");
3206:                    if (filterRule != null) {
3207:                        // Here's a good place to ensure that the filter rule actually exists
3208:                        if (!grammar.isDefined(CodeGenerator
3209:                                .encodeLexerRuleName(filterRule))) {
3210:                            grammar.antlrTool.error("Filter rule " + filterRule
3211:                                    + " does not exist in this lexer");
3212:                        } else {
3213:                            RuleSymbol rs = (RuleSymbol) grammar
3214:                                    .getSymbol(CodeGenerator
3215:                                            .encodeLexerRuleName(filterRule));
3216:                            if (!rs.isDefined()) {
3217:                                grammar.antlrTool.error("Filter rule "
3218:                                        + filterRule
3219:                                        + " does not exist in this lexer");
3220:                            } else if (rs.access.equals("public")) {
3221:                                grammar.antlrTool.error("Filter rule "
3222:                                        + filterRule + " must be protected");
3223:                            }
3224:                        }
3225:                        println("int _m;");
3226:                        println("_m = mark();");
3227:                    }
3228:                }
3229:                println("resetText();");
3230:
3231:                // Generate try around whole thing to trap scanner errors
3232:                println("try {   // for lexical and char stream error handling");
3233:                tabs++;
3234:
3235:                // Test for public lexical rules with empty paths
3236:                for (int i = 0; i < nextTokenBlk.getAlternatives().size(); i++) {
3237:                    Alternative a = nextTokenBlk.getAlternativeAt(i);
3238:                    if (a.cache[1].containsEpsilon()) {
3239:                        antlrTool.warning("found optional path in nextToken()");
3240:                    }
3241:                }
3242:
3243:                // Generate the block
3244:                String newline = System.getProperty("line.separator");
3245:                CppBlockFinishingInfo howToFinish = genCommonBlock(
3246:                        nextTokenBlk, false);
3247:                String errFinish = "if (LA(1)==EOF_CHAR)" + newline
3248:                        + "\t\t\t\t{" + newline + "\t\t\t\t\tuponEOF();"
3249:                        + newline + "\t\t\t\t\t_returnToken = makeToken("
3250:                        + namespaceAntlr + "Token::EOF_TYPE);" + newline
3251:                        + "\t\t\t\t}";
3252:                errFinish += newline + "\t\t\t\t";
3253:                if (((LexerGrammar) grammar).filterMode) {
3254:                    if (filterRule == null) {
3255:                        errFinish += "else {consume(); goto tryAgain;}";
3256:                    } else {
3257:                        errFinish += "else {" + newline + "\t\t\t\t\tcommit();"
3258:                                + newline + "\t\t\t\t\ttry {m" + filterRule
3259:                                + "(false);}" + newline + "\t\t\t\t\tcatch("
3260:                                + namespaceAntlr + "RecognitionException& e) {"
3261:                                + newline
3262:                                + "\t\t\t\t\t	// catastrophic failure"
3263:                                + newline + "\t\t\t\t\t	reportError(e);"
3264:                                + newline + "\t\t\t\t\t	consume();" + newline
3265:                                + "\t\t\t\t\t}" + newline
3266:                                + "\t\t\t\t\tgoto tryAgain;" + newline
3267:                                + "\t\t\t\t}";
3268:                    }
3269:                } else {
3270:                    errFinish += "else {" + throwNoViable + "}";
3271:                }
3272:                genBlockFinish(howToFinish, errFinish);
3273:
3274:                // at this point a valid token has been matched, undo "mark" that was done
3275:                if (((LexerGrammar) grammar).filterMode && filterRule != null) {
3276:                    println("commit();");
3277:                }
3278:
3279:                // Generate literals test if desired
3280:                // make sure _ttype is set first; note _returnToken must be
3281:                // non-null as the rule was required to create it.
3282:                println("if ( !_returnToken )" + newline
3283:                        + "\t\t\t\tgoto tryAgain; // found SKIP token"
3284:                        + newline);
3285:                println("_ttype = _returnToken->getType();");
3286:                if (((LexerGrammar) grammar).getTestLiterals()) {
3287:                    genLiteralsTest();
3288:                }
3289:
3290:                // return token created by rule reference in switch
3291:                println("_returnToken->setType(_ttype);");
3292:                println("return _returnToken;");
3293:
3294:                // Close try block
3295:                tabs--;
3296:                println("}");
3297:                println("catch (" + namespaceAntlr
3298:                        + "RecognitionException& e) {");
3299:                tabs++;
3300:                if (((LexerGrammar) grammar).filterMode) {
3301:                    if (filterRule == null) {
3302:                        println("if ( !getCommitToPath() ) {");
3303:                        tabs++;
3304:                        println("consume();");
3305:                        println("goto tryAgain;");
3306:                        tabs--;
3307:                        println("}");
3308:                    } else {
3309:                        println("if ( !getCommitToPath() ) {");
3310:                        tabs++;
3311:                        println("rewind(_m);");
3312:                        println("resetText();");
3313:                        println("try {m" + filterRule + "(false);}");
3314:                        println("catch(" + namespaceAntlr
3315:                                + "RecognitionException& ee) {");
3316:                        println("	// horrendous failure: error in filter rule");
3317:                        println("	reportError(ee);");
3318:                        println("	consume();");
3319:                        println("}");
3320:                        // println("goto tryAgain;");
3321:                        tabs--;
3322:                        println("}");
3323:                        println("else");
3324:                    }
3325:                }
3326:                if (nextTokenBlk.getDefaultErrorHandler()) {
3327:                    println("{");
3328:                    tabs++;
3329:                    println("reportError(e);");
3330:                    println("consume();");
3331:                    tabs--;
3332:                    println("}");
3333:                } else {
3334:                    // pass on to invoking routine
3335:                    tabs++;
3336:                    println("throw " + namespaceAntlr
3337:                            + "TokenStreamRecognitionException(e);");
3338:                    tabs--;
3339:                }
3340:
3341:                // close CharStreamException try
3342:                tabs--;
3343:                println("}");
3344:                println("catch (" + namespaceAntlr
3345:                        + "CharStreamIOException& csie) {");
3346:                println("\tthrow " + namespaceAntlr
3347:                        + "TokenStreamIOException(csie.io);");
3348:                println("}");
3349:                println("catch (" + namespaceAntlr
3350:                        + "CharStreamException& cse) {");
3351:                println("\tthrow " + namespaceAntlr
3352:                        + "TokenStreamException(cse.getMessage());");
3353:                println("}");
3354:
3355:                // close for-loop
3356:                _println("tryAgain:;");
3357:                tabs--;
3358:                println("}");
3359:
3360:                // close method nextToken
3361:                tabs--;
3362:                println("}");
3363:                println("");
3364:            }
3365:
3366:            /** Gen a named rule block.
3367:             * ASTs are generated for each element of an alternative unless
3368:             * the rule or the alternative have a '!' modifier.
3369:             *
3370:             * If an alternative defeats the default tree construction, it
3371:             * must set <rule>_AST to the root of the returned AST.
3372:             *
3373:             * Each alternative that does automatic tree construction, builds
3374:             * up root and child list pointers in an ASTPair structure.
3375:             *
3376:             * A rule finishes by setting the returnAST variable from the
3377:             * ASTPair.
3378:             *
3379:             * @param rule The name of the rule to generate
3380:             * @param startSymbol true if the rule is a start symbol (i.e., not referenced elsewhere)
3381:             */
3382:            public void genRule(RuleSymbol s, boolean startSymbol, int ruleNum,
3383:                    String prefix) {
3384:                //		tabs=1; // JavaCodeGenerator needs this
3385:                if (DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR)
3386:                    System.out.println("genRule(" + s.getId() + ")");
3387:                if (!s.isDefined()) {
3388:                    antlrTool.error("undefined rule: " + s.getId());
3389:                    return;
3390:                }
3391:
3392:                // Generate rule return type, name, arguments
3393:                RuleBlock rblk = s.getBlock();
3394:
3395:                currentRule = rblk;
3396:                currentASTResult = s.getId();
3397:
3398:                // clear list of declared ast variables..
3399:                declaredASTVariables.clear();
3400:
3401:                // Save the AST generation state, and set it to that of the rule
3402:                boolean savegenAST = genAST;
3403:                genAST = genAST && rblk.getAutoGen();
3404:
3405:                // boolean oldsaveTest = saveText;
3406:                saveText = rblk.getAutoGen();
3407:
3408:                // print javadoc comment if any
3409:                if (s.comment != null) {
3410:                    _println(s.comment);
3411:                }
3412:
3413:                // Gen method return type (note lexer return action set at rule creation)
3414:                if (rblk.returnAction != null) {
3415:                    // Has specified return value
3416:                    _print(extractTypeOfAction(rblk.returnAction, rblk
3417:                            .getLine(), rblk.getColumn())
3418:                            + " ");
3419:                } else {
3420:                    // No specified return value
3421:                    _print("void ");
3422:                }
3423:
3424:                // Gen method name
3425:                _print(prefix + s.getId() + "(");
3426:
3427:                // Additional rule parameters common to all rules for this grammar
3428:                _print(commonExtraParams);
3429:                if (commonExtraParams.length() != 0 && rblk.argAction != null) {
3430:                    _print(",");
3431:                }
3432:
3433:                // Gen arguments
3434:                if (rblk.argAction != null) {
3435:                    // Has specified arguments
3436:                    _println("");
3437:                    // FIXME: make argAction also a token? Hmmmmm
3438:                    //			genLineNo(rblk);
3439:                    tabs++;
3440:
3441:                    // Process arguments for default arguments
3442:                    // newer gcc's don't accept these in two places (header/cpp)
3443:                    //
3444:                    // Old appraoch with StringBuffer gave trouble with gcj.
3445:                    //
3446:                    // RK: Actually this breaks with string default arguments containing
3447:                    // a comma's or equal signs. Then again the old StringBuffer method
3448:                    // suffered from the same.
3449:                    String oldarg = rblk.argAction;
3450:                    String newarg = "";
3451:
3452:                    String comma = "";
3453:                    int eqpos = oldarg.indexOf('=');
3454:                    if (eqpos != -1) {
3455:                        int cmpos = 0;
3456:                        while (cmpos != -1) {
3457:                            newarg = newarg + comma
3458:                                    + oldarg.substring(0, eqpos).trim();
3459:                            comma = ", ";
3460:                            cmpos = oldarg.indexOf(',', eqpos);
3461:                            if (cmpos != -1) {
3462:                                // cut off part we just handled
3463:                                oldarg = oldarg.substring(cmpos + 1).trim();
3464:                                eqpos = oldarg.indexOf('=');
3465:                            }
3466:                        }
3467:                    } else
3468:                        newarg = oldarg;
3469:
3470:                    println(newarg);
3471:
3472:                    //			println(rblk.argAction);
3473:                    tabs--;
3474:                    print(") ");
3475:                    //			genLineNo2();	// gcc gives error on the brace... hope it works for the others too
3476:                } else {
3477:                    // No specified arguments
3478:                    _print(") ");
3479:                }
3480:                _println("{");
3481:                tabs++;
3482:
3483:                if (grammar.traceRules) {
3484:                    if (grammar instanceof  TreeWalkerGrammar) {
3485:                        if (usingCustomAST)
3486:                            println("Tracer traceInOut(this,\"" + s.getId()
3487:                                    + "\"," + namespaceAntlr + "RefAST"
3488:                                    + "(_t));");
3489:                        else
3490:                            println("Tracer traceInOut(this,\"" + s.getId()
3491:                                    + "\",_t);");
3492:                    } else {
3493:                        println("Tracer traceInOut(this, \"" + s.getId()
3494:                                + "\");");
3495:                    }
3496:                }
3497:
3498:                // Convert return action to variable declaration
3499:                if (rblk.returnAction != null) {
3500:                    genLineNo(rblk);
3501:                    println(rblk.returnAction + ";");
3502:                    genLineNo2();
3503:                }
3504:
3505:                // print out definitions needed by rules for various grammar types
3506:                if (!commonLocalVars.equals(""))
3507:                    println(commonLocalVars);
3508:
3509:                if (grammar instanceof  LexerGrammar) {
3510:                    // RK: why is this here? It seems not supported in the rest of the
3511:                    // tool.
3512:                    // lexer rule default return value is the rule's token name
3513:                    // This is a horrible hack to support the built-in EOF lexer rule.
3514:                    if (s.getId().equals("mEOF"))
3515:                        println("_ttype = " + namespaceAntlr
3516:                                + "Token::EOF_TYPE;");
3517:                    else
3518:                        println("_ttype = " + s.getId().substring(1) + ";");
3519:                    println("int _saveIndex;"); // used for element! (so we can kill text matched for element)
3520:                    /*
3521:                     println("boolean old_saveConsumedInput=saveConsumedInput;");
3522:                     if ( !rblk.getAutoGen() ) {      // turn off "save input" if ! on rule
3523:                     println("saveConsumedInput=false;");
3524:                     }
3525:                     */
3526:
3527:                }
3528:
3529:                // if debugging, write code to mark entry to the rule
3530:                if (grammar.debuggingOutput)
3531:                    if (grammar instanceof  ParserGrammar)
3532:                        println("fireEnterRule(" + ruleNum + ",0);");
3533:                    else if (grammar instanceof  LexerGrammar)
3534:                        println("fireEnterRule(" + ruleNum + ",_ttype);");
3535:
3536:                // Generate trace code if desired
3537:                //		if ( grammar.debuggingOutput || grammar.traceRules) {
3538:                //			println("try { // debugging");
3539:                //			tabs++;
3540:                //		}
3541:
3542:                // Initialize AST variables
3543:                if (grammar instanceof  TreeWalkerGrammar) {
3544:                    // "Input" value for rule
3545:                    //			println(labeledElementASTType+" " + s.getId() + "_AST_in = "+labeledElementASTType+"(_t);");
3546:                    println(labeledElementASTType + " " + s.getId()
3547:                            + "_AST_in = (_t == ASTNULL) ? "
3548:                            + labeledElementASTInit + " : _t;");
3549:                }
3550:                if (grammar.buildAST) {
3551:                    // Parser member used to pass AST returns from rule invocations
3552:                    println("returnAST = " + labeledElementASTInit + ";");
3553:                    // Tracks AST construction
3554:                    println(namespaceAntlr + "ASTPair currentAST;"); // = new ASTPair();");
3555:                    // User-settable return value for rule.
3556:                    println(labeledElementASTType + " " + s.getId() + "_AST = "
3557:                            + labeledElementASTInit + ";");
3558:                }
3559:
3560:                genBlockPreamble(rblk);
3561:                genBlockInitAction(rblk);
3562:                println("");
3563:
3564:                // Search for an unlabeled exception specification attached to the rule
3565:                ExceptionSpec unlabeledUserSpec = rblk.findExceptionSpec("");
3566:
3567:                // Generate try block around the entire rule for  error handling
3568:                if (unlabeledUserSpec != null || rblk.getDefaultErrorHandler()) {
3569:                    println("try {      // for error handling");
3570:                    tabs++;
3571:                }
3572:
3573:                // Generate the alternatives
3574:                if (rblk.alternatives.size() == 1) {
3575:                    // One alternative -- use simple form
3576:                    Alternative alt = rblk.getAlternativeAt(0);
3577:                    String pred = alt.semPred;
3578:                    if (pred != null)
3579:                        genSemPred(pred, currentRule.line);
3580:                    if (alt.synPred != null) {
3581:                        antlrTool
3582:                                .warning(
3583:                                        "Syntactic predicate ignored for single alternative",
3584:                                        grammar.getFilename(), alt.synPred
3585:                                                .getLine(), alt.synPred
3586:                                                .getColumn());
3587:                    }
3588:                    genAlt(alt, rblk);
3589:                } else {
3590:                    // Multiple alternatives -- generate complex form
3591:                    boolean ok = grammar.theLLkAnalyzer.deterministic(rblk);
3592:
3593:                    CppBlockFinishingInfo howToFinish = genCommonBlock(rblk,
3594:                            false);
3595:                    genBlockFinish(howToFinish, throwNoViable);
3596:                }
3597:
3598:                // Generate catch phrase for error handling
3599:                if (unlabeledUserSpec != null || rblk.getDefaultErrorHandler()) {
3600:                    // Close the try block
3601:                    tabs--;
3602:                    println("}");
3603:                }
3604:
3605:                // Generate user-defined or default catch phrases
3606:                if (unlabeledUserSpec != null) {
3607:                    genErrorHandler(unlabeledUserSpec);
3608:                } else if (rblk.getDefaultErrorHandler()) {
3609:                    // Generate default catch phrase
3610:                    println("catch (" + exceptionThrown + "& ex) {");
3611:                    tabs++;
3612:                    // Generate code to handle error if not guessing
3613:                    if (grammar.hasSyntacticPredicate) {
3614:                        println("if( inputState->guessing == 0 ) {");
3615:                        tabs++;
3616:                    }
3617:                    println("reportError(ex);");
3618:                    if (!(grammar instanceof  TreeWalkerGrammar)) {
3619:                        // Generate code to consume until token in k==1 follow set
3620:                        Lookahead follow = grammar.theLLkAnalyzer.FOLLOW(1,
3621:                                rblk.endNode);
3622:                        String followSetName = getBitsetName(markBitsetForGen(follow.fset));
3623:                        println("consume();");
3624:                        println("consumeUntil(" + followSetName + ");");
3625:                    } else {
3626:                        // Just consume one token
3627:                        println("if ( _t != " + labeledElementASTInit + " )");
3628:                        tabs++;
3629:                        println("_t = _t->getNextSibling();");
3630:                        tabs--;
3631:                    }
3632:                    if (grammar.hasSyntacticPredicate) {
3633:                        tabs--;
3634:                        // When guessing, rethrow exception
3635:                        println("} else {");
3636:                        tabs++;
3637:                        println("throw;");
3638:                        tabs--;
3639:                        println("}");
3640:                    }
3641:                    // Close catch phrase
3642:                    tabs--;
3643:                    println("}");
3644:                }
3645:
3646:                // Squirrel away the AST "return" value
3647:                if (grammar.buildAST) {
3648:                    println("returnAST = " + s.getId() + "_AST;");
3649:                }
3650:
3651:                // Set return tree value for tree walkers
3652:                if (grammar instanceof  TreeWalkerGrammar) {
3653:                    println("_retTree = _t;");
3654:                }
3655:
3656:                // Generate literals test for lexer rules so marked
3657:                if (rblk.getTestLiterals()) {
3658:                    if (s.access.equals("protected")) {
3659:                        genLiteralsTestForPartialToken();
3660:                    } else {
3661:                        genLiteralsTest();
3662:                    }
3663:                }
3664:
3665:                // if doing a lexer rule, dump code to create token if necessary
3666:                if (grammar instanceof  LexerGrammar) {
3667:                    println("if ( _createToken && _token==" + namespaceAntlr
3668:                            + "nullToken && _ttype!=" + namespaceAntlr
3669:                            + "Token::SKIP ) {");
3670:                    println("   _token = makeToken(_ttype);");
3671:                    println("   _token->setText(text.substr(_begin, text.length()-_begin));");
3672:                    println("}");
3673:                    println("_returnToken = _token;");
3674:                    // It should be easy for an optimizing compiler to realize this does nothing
3675:                    // but it avoids the warning about the variable being unused.
3676:                    println("_saveIndex=0;");
3677:                }
3678:
3679:                // Gen the return statement if there is one (lexer has hard-wired return action)
3680:                if (rblk.returnAction != null) {
3681:                    println("return "
3682:                            + extractIdOfAction(rblk.returnAction, rblk
3683:                                    .getLine(), rblk.getColumn()) + ";");
3684:                }
3685:
3686:                //		if ( grammar.debuggingOutput || grammar.traceRules) {
3687:                ////			tabs--;
3688:                ////			println("} finally { // debugging");
3689:                ////			tabs++;
3690:                //
3691:                //			// Generate trace code if desired
3692:                //			if ( grammar.debuggingOutput)
3693:                //				if (grammar instanceof ParserGrammar)
3694:                //					println("fireExitRule(" + ruleNum + ",0);");
3695:                //				else if (grammar instanceof LexerGrammar)
3696:                //					println("fireExitRule(" + ruleNum + ",_ttype);");
3697:                //
3698:                ////			if (grammar.traceRules) {
3699:                ////				if ( grammar instanceof TreeWalkerGrammar ) {
3700:                ////					println("traceOut(\""+ s.getId() +"\",_t);");
3701:                ////				}
3702:                ////				else {
3703:                ////					println("traceOut(\""+ s.getId() +"\");");
3704:                ////				}
3705:                ////			}
3706:                ////
3707:                ////			tabs--;
3708:                ////			println("}");
3709:                //		}
3710:
3711:                tabs--;
3712:                println("}");
3713:                println("");
3714:
3715:                // Restore the AST generation state
3716:                genAST = savegenAST;
3717:
3718:                // restore char save state
3719:                // saveText = oldsaveTest;
3720:            }
3721:
3722:            public void genRuleHeader(RuleSymbol s, boolean startSymbol) {
3723:                tabs = 1;
3724:                if (DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR)
3725:                    System.out.println("genRuleHeader(" + s.getId() + ")");
3726:                if (!s.isDefined()) {
3727:                    antlrTool.error("undefined rule: " + s.getId());
3728:                    return;
3729:                }
3730:
3731:                // Generate rule return type, name, arguments
3732:                RuleBlock rblk = s.getBlock();
3733:                currentRule = rblk;
3734:                currentASTResult = s.getId();
3735:
3736:                // Save the AST generation state, and set it to that of the rule
3737:                boolean savegenAST = genAST;
3738:                genAST = genAST && rblk.getAutoGen();
3739:
3740:                // boolean oldsaveTest = saveText;
3741:                saveText = rblk.getAutoGen();
3742:
3743:                // Gen method access
3744:                print(s.access + ": ");
3745:
3746:                // Gen method return type (note lexer return action set at rule creation)
3747:                if (rblk.returnAction != null) {
3748:                    // Has specified return value
3749:                    _print(extractTypeOfAction(rblk.returnAction, rblk
3750:                            .getLine(), rblk.getColumn())
3751:                            + " ");
3752:                } else {
3753:                    // No specified return value
3754:                    _print("void ");
3755:                }
3756:
3757:                // Gen method name
3758:                _print(s.getId() + "(");
3759:
3760:                // Additional rule parameters common to all rules for this grammar
3761:                _print(commonExtraParams);
3762:                if (commonExtraParams.length() != 0 && rblk.argAction != null) {
3763:                    _print(",");
3764:                }
3765:
3766:                // Gen arguments
3767:                if (rblk.argAction != null) {
3768:                    // Has specified arguments
3769:                    _println("");
3770:                    tabs++;
3771:                    println(rblk.argAction);
3772:                    tabs--;
3773:                    print(")");
3774:                } else {
3775:                    // No specified arguments
3776:                    _print(")");
3777:                }
3778:                _println(";");
3779:
3780:                tabs--;
3781:
3782:                // Restore the AST generation state
3783:                genAST = savegenAST;
3784:
3785:                // restore char save state
3786:                // saveText = oldsaveTest;
3787:            }
3788:
3789:            private void GenRuleInvocation(RuleRefElement rr) {
3790:                // dump rule name
3791:                _print(rr.targetRule + "(");
3792:
3793:                // lexers must tell rule if it should set _returnToken
3794:                if (grammar instanceof  LexerGrammar) {
3795:                    // if labeled, could access Token, so tell rule to create
3796:                    if (rr.getLabel() != null) {
3797:                        _print("true");
3798:                    } else {
3799:                        _print("false");
3800:                    }
3801:                    if (commonExtraArgs.length() != 0 || rr.args != null) {
3802:                        _print(",");
3803:                    }
3804:                }
3805:
3806:                // Extra arguments common to all rules for this grammar
3807:                _print(commonExtraArgs);
3808:                if (commonExtraArgs.length() != 0 && rr.args != null) {
3809:                    _print(",");
3810:                }
3811:
3812:                // Process arguments to method, if any
3813:                RuleSymbol rs = (RuleSymbol) grammar.getSymbol(rr.targetRule);
3814:                if (rr.args != null) {
3815:                    // When not guessing, execute user arg action
3816:                    ActionTransInfo tInfo = new ActionTransInfo();
3817:                    // FIXME: fix line number passed to processActionForTreeSpecifiers here..
3818:                    // this one might be a bit off..
3819:                    String args = processActionForSpecialSymbols(rr.args,
3820:                            rr.line, currentRule, tInfo);
3821:                    if (tInfo.assignToRoot || tInfo.refRuleRoot != null) {
3822:                        antlrTool.error("Arguments of rule reference '"
3823:                                + rr.targetRule + "' cannot set or ref #"
3824:                                + currentRule.getRuleName() + " on line "
3825:                                + rr.getLine());
3826:                    }
3827:                    _print(args);
3828:
3829:                    // Warn if the rule accepts no arguments
3830:                    if (rs.block.argAction == null) {
3831:                        antlrTool.warning("Rule '" + rr.targetRule
3832:                                + "' accepts no arguments", grammar
3833:                                .getFilename(), rr.getLine(), rr.getColumn());
3834:                    }
3835:                } else {
3836:                    // For C++, no warning if rule has parameters, because there may be default
3837:                    // values for all of the parameters
3838:                    //if (rs.block.argAction != null) {
3839:                    //	tool.warning("Missing parameters on reference to rule "+rr.targetRule, rr.getLine());
3840:                    //}
3841:                }
3842:                _println(");");
3843:
3844:                // move down to the first child while parsing
3845:                if (grammar instanceof  TreeWalkerGrammar) {
3846:                    println("_t = _retTree;");
3847:                }
3848:            }
3849:
3850:            protected void genSemPred(String pred, int line) {
3851:                // translate $ and # references
3852:                ActionTransInfo tInfo = new ActionTransInfo();
3853:                pred = processActionForSpecialSymbols(pred, line, currentRule,
3854:                        tInfo);
3855:                // ignore translation info...we don't need to do anything with it.
3856:                String escapedPred = charFormatter.escapeString(pred);
3857:
3858:                // if debugging, wrap the semantic predicate evaluation in a method
3859:                // that can tell SemanticPredicateListeners the result
3860:                if (grammar.debuggingOutput
3861:                        && ((grammar instanceof  ParserGrammar) || (grammar instanceof  LexerGrammar)))
3862:                    pred = "fireSemanticPredicateEvaluated(persistence.antlr.debug.SemanticPredicateEvent.VALIDATING," //FIXME
3863:                            + addSemPred(escapedPred) + "," + pred + ")";
3864:                println("if (!(" + pred + "))");
3865:                tabs++;
3866:                println("throw " + namespaceAntlr + "SemanticException(\""
3867:                        + escapedPred + "\");");
3868:                tabs--;
3869:            }
3870:
3871:            /** Write an array of Strings which are the semantic predicate
3872:             *  expressions.  The debugger will reference them by number only
3873:             */
3874:            protected void genSemPredMap(String prefix) {
3875:                Enumeration e = semPreds.elements();
3876:                println("const char* " + prefix + "_semPredNames[] = {");
3877:                tabs++;
3878:                while (e.hasMoreElements())
3879:                    println("\"" + e.nextElement() + "\",");
3880:                println("0");
3881:                tabs--;
3882:                println("};");
3883:            }
3884:
3885:            protected void genSynPred(SynPredBlock blk, String lookaheadExpr) {
3886:                if (DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR)
3887:                    System.out.println("gen=>(" + blk + ")");
3888:
3889:                // Dump synpred result variable
3890:                println("bool synPredMatched" + blk.ID + " = false;");
3891:                // Gen normal lookahead test
3892:                println("if (" + lookaheadExpr + ") {");
3893:                tabs++;
3894:
3895:                // Save input state
3896:                if (grammar instanceof  TreeWalkerGrammar) {
3897:                    println(labeledElementType + " __t" + blk.ID + " = _t;");
3898:                } else {
3899:                    println("int _m" + blk.ID + " = mark();");
3900:                }
3901:
3902:                // Once inside the try, assume synpred works unless exception caught
3903:                println("synPredMatched" + blk.ID + " = true;");
3904:                println("inputState->guessing++;");
3905:
3906:                // if debugging, tell listeners that a synpred has started
3907:                if (grammar.debuggingOutput
3908:                        && ((grammar instanceof  ParserGrammar) || (grammar instanceof  LexerGrammar))) {
3909:                    println("fireSyntacticPredicateStarted();");
3910:                }
3911:
3912:                syntacticPredLevel++;
3913:                println("try {");
3914:                tabs++;
3915:                gen((AlternativeBlock) blk); // gen code to test predicate
3916:                tabs--;
3917:                //println("System.out.println(\"pred "+blk+" succeeded\");");
3918:                println("}");
3919:                println("catch (" + exceptionThrown + "& pe) {");
3920:                tabs++;
3921:                println("synPredMatched" + blk.ID + " = false;");
3922:                //println("System.out.println(\"pred "+blk+" failed\");");
3923:                tabs--;
3924:                println("}");
3925:
3926:                // Restore input state
3927:                if (grammar instanceof  TreeWalkerGrammar) {
3928:                    println("_t = __t" + blk.ID + ";");
3929:                } else {
3930:                    println("rewind(_m" + blk.ID + ");");
3931:                }
3932:
3933:                println("inputState->guessing--;");
3934:
3935:                // if debugging, tell listeners how the synpred turned out
3936:                if (grammar.debuggingOutput
3937:                        && ((grammar instanceof  ParserGrammar) || (grammar instanceof  LexerGrammar))) {
3938:                    println("if (synPredMatched" + blk.ID + ")");
3939:                    println("  fireSyntacticPredicateSucceeded();");
3940:                    println("else");
3941:                    println("  fireSyntacticPredicateFailed();");
3942:                }
3943:
3944:                syntacticPredLevel--;
3945:                tabs--;
3946:
3947:                // Close lookahead test
3948:                println("}");
3949:
3950:                // Test synpred result
3951:                println("if ( synPredMatched" + blk.ID + " ) {");
3952:            }
3953:
3954:            /** Generate a static array containing the names of the tokens,
3955:             * indexed by the token type values.  This static array is used
3956:             * to format error messages so that the token identifers or literal
3957:             * strings are displayed instead of the token numbers.
3958:             *
3959:             * If a lexical rule has a paraphrase, use it rather than the
3960:             * token label.
3961:             */
3962:            public void genTokenStrings(String prefix) {
3963:                // Generate a string for each token.  This creates a static
3964:                // array of Strings indexed by token type.
3965:                //		println("");
3966:                println("const char* " + prefix + "tokenNames[] = {");
3967:                tabs++;
3968:
3969:                // Walk the token vocabulary and generate a Vector of strings
3970:                // from the tokens.
3971:                Vector v = grammar.tokenManager.getVocabulary();
3972:                for (int i = 0; i < v.size(); i++) {
3973:                    String s = (String) v.elementAt(i);
3974:                    if (s == null) {
3975:                        s = "<" + String.valueOf(i) + ">";
3976:                    }
3977:                    if (!s.startsWith("\"") && !s.startsWith("<")) {
3978:                        TokenSymbol ts = (TokenSymbol) grammar.tokenManager
3979:                                .getTokenSymbol(s);
3980:                        if (ts != null && ts.getParaphrase() != null) {
3981:                            s = StringUtils.stripFrontBack(ts.getParaphrase(),
3982:                                    "\"", "\"");
3983:                        }
3984:                    }
3985:                    print(charFormatter.literalString(s));
3986:                    _println(",");
3987:                }
3988:                println("0");
3989:
3990:                // Close the string array initailizer
3991:                tabs--;
3992:                println("};");
3993:            }
3994:
3995:            /** Generate the token types C++ file */
3996:            protected void genTokenTypes(TokenManager tm) throws IOException {
3997:                // Open the token output header file and set the currentOutput stream
3998:                outputFile = tm.getName() + TokenTypesFileSuffix + ".hpp";
3999:                outputLine = 1;
4000:                currentOutput = antlrTool.openOutputFile(outputFile);
4001:                //SAS: changed for proper text file io
4002:
4003:                tabs = 0;
4004:
4005:                // Generate a guard wrapper
4006:                println("#ifndef INC_" + tm.getName() + TokenTypesFileSuffix
4007:                        + "_hpp_");
4008:                println("#define INC_" + tm.getName() + TokenTypesFileSuffix
4009:                        + "_hpp_");
4010:                println("");
4011:
4012:                if (nameSpace != null)
4013:                    nameSpace.emitDeclarations(currentOutput);
4014:
4015:                // Generate the header common to all C++ files
4016:                genHeader(outputFile);
4017:
4018:                // Encapsulate the definitions in an interface.  This can be done
4019:                // because they are all constants.
4020:                println("");
4021:                println("#ifndef CUSTOM_API");
4022:                println("# define CUSTOM_API");
4023:                println("#endif");
4024:                println("");
4025:                // In the case that the .hpp is included from C source (flexLexer!)
4026:                // we just turn things into a plain enum
4027:                println("#ifdef __cplusplus");
4028:                println("struct CUSTOM_API " + tm.getName()
4029:                        + TokenTypesFileSuffix + " {");
4030:                println("#endif");
4031:                tabs++;
4032:                println("enum {");
4033:                tabs++;
4034:
4035:                // Generate a definition for each token type
4036:                Vector v = tm.getVocabulary();
4037:
4038:                // Do special tokens manually
4039:                println("EOF_ = " + Token.EOF_TYPE + ",");
4040:
4041:                // Move the other special token to the end, so we can solve
4042:                // the superfluous comma problem easily
4043:
4044:                for (int i = Token.MIN_USER_TYPE; i < v.size(); i++) {
4045:                    String s = (String) v.elementAt(i);
4046:                    if (s != null) {
4047:                        if (s.startsWith("\"")) {
4048:                            // a string literal
4049:                            StringLiteralSymbol sl = (StringLiteralSymbol) tm
4050:                                    .getTokenSymbol(s);
4051:                            if (sl == null) {
4052:                                antlrTool.panic("String literal " + s
4053:                                        + " not in symbol table");
4054:                            } else if (sl.label != null) {
4055:                                println(sl.label + " = " + i + ",");
4056:                            } else {
4057:                                String mangledName = mangleLiteral(s);
4058:                                if (mangledName != null) {
4059:                                    // We were able to create a meaningful mangled token name
4060:                                    println(mangledName + " = " + i + ",");
4061:                                    // if no label specified, make the label equal to the mangled name
4062:                                    sl.label = mangledName;
4063:                                } else {
4064:                                    println("// " + s + " = " + i);
4065:                                }
4066:                            }
4067:                        } else if (!s.startsWith("<")) {
4068:                            println(s + " = " + i + ",");
4069:                        }
4070:                    }
4071:                }
4072:
4073:                // Moved from above
4074:                println("NULL_TREE_LOOKAHEAD = " + Token.NULL_TREE_LOOKAHEAD);
4075:
4076:                // Close the enum
4077:                tabs--;
4078:                println("};");
4079:
4080:                // Close the interface
4081:                tabs--;
4082:                println("#ifdef __cplusplus");
4083:                println("};");
4084:                println("#endif");
4085:
4086:                if (nameSpace != null)
4087:                    nameSpace.emitClosures(currentOutput);
4088:
4089:                // Generate a guard wrapper
4090:                println("#endif /*INC_" + tm.getName() + TokenTypesFileSuffix
4091:                        + "_hpp_*/");
4092:
4093:                // Close the tokens output file
4094:                currentOutput.close();
4095:                currentOutput = null;
4096:                exitIfError();
4097:            }
4098:
4099:            /** Process a string for an simple expression for use in xx/action.g
4100:             * it is used to cast simple tokens/references to the right type for
4101:             * the generated language. Basically called for every element in
4102:             * the vector to getASTCreateString(vector V)
4103:             * @param str A String.
4104:             */
4105:            public String processStringForASTConstructor(String str) {
4106:                if (usingCustomAST
4107:                        && ((grammar instanceof  TreeWalkerGrammar) || (grammar instanceof  ParserGrammar))
4108:                        && !(grammar.tokenManager.tokenDefined(str))) {
4109:                    //			System.out.println("processStringForASTConstructor: "+str+" with cast");
4110:                    return namespaceAntlr + "RefAST(" + str + ")";
4111:                } else {
4112:                    //			System.out.println("processStringForASTConstructor: "+str);
4113:                    return str;
4114:                }
4115:            }
4116:
4117:            /** Get a string for an expression to generate creation of an AST subtree.
4118:             * @param v A Vector of String, where each element is an expression
4119:             * in the target language yielding an AST node.
4120:             */
4121:            public String getASTCreateString(Vector v) {
4122:                if (v.size() == 0) {
4123:                    return "";
4124:                }
4125:                StringBuffer buf = new StringBuffer();
4126:                // the labeledElementASTType here can probably be a cast or nothing
4127:                // in the case of ! usingCustomAST
4128:                buf.append(labeledElementASTType + "(astFactory->make((new "
4129:                        + namespaceAntlr + "ASTArray(" + v.size() + "))");
4130:                for (int i = 0; i < v.size(); i++) {
4131:                    buf.append("->add(" + v.elementAt(i) + ")");
4132:                }
4133:                buf.append("))");
4134:                return buf.toString();
4135:            }
4136:
4137:            /** Get a string for an expression to generate creating of an AST node
4138:             * @param str The arguments to the AST constructor
4139:             */
4140:            public String getASTCreateString(GrammarAtom atom, String str) {
4141:                if (atom != null && atom.getASTNodeType() != null) {
4142:
4143:                    // this atom is using a heterogeneous AST type.
4144:                    // make note of the factory needed to generate it..
4145:                    // later this is inserted into the initializeFactory method.
4146:                    astTypes.appendElement("factory.registerFactory("
4147:                            + atom.getType() + ", \"" + atom.getASTNodeType()
4148:                            + "\", " + atom.getASTNodeType() + "::factory);");
4149:
4150:                    // after above init the factory knows what to generate...
4151:                    return "astFactory->create(" + str + ")";
4152:                } else {
4153:                    // FIXME: This is *SO* ugly! but it will have to do for now...
4154:                    // 2.7.2 will have better I hope
4155:                    // this is due to the usage of getASTCreateString from inside
4156:                    // actions/cpp/action.g
4157:                    boolean is_constructor = false;
4158:                    if (str.indexOf(',') != -1)
4159:                        is_constructor = grammar.tokenManager.tokenDefined(str
4160:                                .substring(0, str.indexOf(',')));
4161:
4162:                    //			System.out.println("getAstCreateString(as): "+str+" "+grammar.tokenManager.tokenDefined(str));
4163:                    if (usingCustomAST
4164:                            && (grammar instanceof  TreeWalkerGrammar)
4165:                            && !(grammar.tokenManager.tokenDefined(str))
4166:                            && !is_constructor)
4167:                        return "astFactory->create(" + namespaceAntlr
4168:                                + "RefAST(" + str + "))";
4169:                    else
4170:                        return "astFactory->create(" + str + ")";
4171:                }
4172:            }
4173:
4174:            /** Get a string for an expression to generate creating of an AST node
4175:             * @param str The arguments to the AST constructor
4176:             */
4177:            public String getASTCreateString(String str) {
4178:                //		System.out.println("getAstCreateString(str): "+str+" "+grammar.tokenManager.tokenDefined(str));
4179:                if (usingCustomAST)
4180:                    return labeledElementASTType + "(astFactory->create("
4181:                            + namespaceAntlr + "RefAST(" + str + ")))";
4182:                else
4183:                    return "astFactory->create(" + str + ")";
4184:            }
4185:
4186:            protected String getLookaheadTestExpression(Lookahead[] look, int k) {
4187:                StringBuffer e = new StringBuffer(100);
4188:                boolean first = true;
4189:
4190:                e.append("(");
4191:                for (int i = 1; i <= k; i++) {
4192:                    BitSet p = look[i].fset;
4193:                    if (!first) {
4194:                        e.append(") && (");
4195:                    }
4196:                    first = false;
4197:
4198:                    // Syn preds can yield <end-of-syn-pred> (epsilon) lookahead.
4199:                    // There is no way to predict what that token would be.  Just
4200:                    // allow anything instead.
4201:                    if (look[i].containsEpsilon()) {
4202:                        e.append("true");
4203:                    } else {
4204:                        e.append(getLookaheadTestTerm(i, p));
4205:                    }
4206:                }
4207:                e.append(")");
4208:
4209:                return e.toString();
4210:            }
4211:
4212:            /** Generate a lookahead test expression for an alternate.  This
4213:             * will be a series of tests joined by '&&' and enclosed by '()',
4214:             * the number of such tests being determined by the depth of the lookahead.
4215:             */
4216:            protected String getLookaheadTestExpression(Alternative alt,
4217:                    int maxDepth) {
4218:                int depth = alt.lookaheadDepth;
4219:                if (depth == GrammarAnalyzer.NONDETERMINISTIC) {
4220:                    // if the decision is nondeterministic, do the best we can: LL(k)
4221:                    // any predicates that are around will be generated later.
4222:                    depth = grammar.maxk;
4223:                }
4224:
4225:                if (maxDepth == 0) {
4226:                    // empty lookahead can result from alt with sem pred
4227:                    // that can see end of token.  E.g., A : {pred}? ('a')? ;
4228:                    return "true";
4229:                }
4230:
4231:                /*
4232:                 boolean first = true;
4233:                 for (int i=1; i<=depth && i<=maxDepth; i++) {
4234:                 BitSet p = alt.cache[i].fset;
4235:                 if (!first) {
4236:                 e.append(") && (");
4237:                 }
4238:                 first = false;
4239:
4240:                 // Syn preds can yield <end-of-syn-pred> (epsilon) lookahead.
4241:                 // There is no way to predict what that token would be.  Just
4242:                 // allow anything instead.
4243:                 if ( alt.cache[i].containsEpsilon() ) {
4244:                 e.append("true");
4245:                 }
4246:                 else {
4247:                 e.append(getLookaheadTestTerm(i, p));
4248:                 }
4249:                 }
4250:
4251:                 e.append(")");
4252:                 */
4253:
4254:                return "(" + getLookaheadTestExpression(alt.cache, depth) + ")";
4255:            }
4256:
4257:            /**Generate a depth==1 lookahead test expression given the BitSet.
4258:             * This may be one of:
4259:             * 1) a series of 'x==X||' tests
4260:             * 2) a range test using >= && <= where possible,
4261:             * 3) a bitset membership test for complex comparisons
4262:             * @param k The lookahead level
4263:             * @param p The lookahead set for level k
4264:             */
4265:            protected String getLookaheadTestTerm(int k, BitSet p) {
4266:                // Determine the name of the item to be compared
4267:                String ts = lookaheadString(k);
4268:
4269:                // Generate a range expression if possible
4270:                int[] elems = p.toArray();
4271:                if (elementsAreRange(elems)) {
4272:                    return getRangeExpression(k, elems);
4273:                }
4274:
4275:                // Generate a bitset membership test if possible
4276:                StringBuffer e;
4277:                int degree = p.degree();
4278:                if (degree == 0) {
4279:                    return "true";
4280:                }
4281:
4282:                if (degree >= bitsetTestThreshold) {
4283:                    int bitsetIdx = markBitsetForGen(p);
4284:                    return getBitsetName(bitsetIdx) + ".member(" + ts + ")";
4285:                }
4286:
4287:                // Otherwise, generate the long-winded series of "x==X||" tests
4288:                e = new StringBuffer();
4289:                for (int i = 0; i < elems.length; i++) {
4290:                    // Get the compared-to item (token or character value)
4291:                    String cs = getValueString(elems[i]);
4292:
4293:                    // Generate the element comparison
4294:                    if (i > 0)
4295:                        e.append(" || ");
4296:                    e.append(ts);
4297:                    e.append(" == ");
4298:                    e.append(cs);
4299:                }
4300:                return e.toString();
4301:            }
4302:
4303:            /** Return an expression for testing a contiguous renage of elements
4304:             * @param k The lookahead level
4305:             * @param elems The elements representing the set, usually from BitSet.toArray().
4306:             * @return String containing test expression.
4307:             */
4308:            public String getRangeExpression(int k, int[] elems) {
4309:                if (!elementsAreRange(elems)) {
4310:                    antlrTool.panic("getRangeExpression called with non-range");
4311:                }
4312:                int begin = elems[0];
4313:                int end = elems[elems.length - 1];
4314:                return "(" + lookaheadString(k) + " >= "
4315:                        + getValueString(begin) + " && " + lookaheadString(k)
4316:                        + " <= " + getValueString(end) + ")";
4317:            }
4318:
4319:            /** getValueString: get a string representation of a token or char value
4320:             * @param value The token or char value
4321:             */
4322:            private String getValueString(int value) {
4323:                String cs;
4324:                if (grammar instanceof  LexerGrammar) {
4325:                    cs = charFormatter.literalChar(value);
4326:                } else {
4327:                    TokenSymbol ts = grammar.tokenManager
4328:                            .getTokenSymbolAt(value);
4329:                    if (ts == null) {
4330:                        return "" + value; // return token type as string
4331:                        // tool.panic("vocabulary for token type " + value + " is null");
4332:                    }
4333:                    String tId = ts.getId();
4334:                    if (ts instanceof  StringLiteralSymbol) {
4335:                        // if string literal, use predefined label if any
4336:                        // if no predefined, try to mangle into LITERAL_xxx.
4337:                        // if can't mangle, use int value as last resort
4338:                        StringLiteralSymbol sl = (StringLiteralSymbol) ts;
4339:                        String label = sl.getLabel();
4340:                        if (label != null) {
4341:                            cs = label;
4342:                        } else {
4343:                            cs = mangleLiteral(tId);
4344:                            if (cs == null) {
4345:                                cs = String.valueOf(value);
4346:                            }
4347:                        }
4348:                    } else {
4349:                        if (tId.equals("EOF"))
4350:                            cs = namespaceAntlr + "Token::EOF_TYPE";
4351:                        else
4352:                            cs = tId;
4353:                    }
4354:                }
4355:                return cs;
4356:            }
4357:
4358:            /**Is the lookahead for this alt empty? */
4359:            protected boolean lookaheadIsEmpty(Alternative alt, int maxDepth) {
4360:                int depth = alt.lookaheadDepth;
4361:                if (depth == GrammarAnalyzer.NONDETERMINISTIC) {
4362:                    depth = grammar.maxk;
4363:                }
4364:                for (int i = 1; i <= depth && i <= maxDepth; i++) {
4365:                    BitSet p = alt.cache[i].fset;
4366:                    if (p.degree() != 0) {
4367:                        return false;
4368:                    }
4369:                }
4370:                return true;
4371:            }
4372:
4373:            private String lookaheadString(int k) {
4374:                if (grammar instanceof  TreeWalkerGrammar) {
4375:                    return "_t->getType()";
4376:                }
4377:                return "LA(" + k + ")";
4378:            }
4379:
4380:            /** Mangle a string literal into a meaningful token name.  This is
4381:             * only possible for literals that are all characters.  The resulting
4382:             * mangled literal name is literalsPrefix with the text of the literal
4383:             * appended.
4384:             * @return A string representing the mangled literal, or null if not possible.
4385:             */
4386:            private String mangleLiteral(String s) {
4387:                String mangled = antlrTool.literalsPrefix;
4388:                for (int i = 1; i < s.length() - 1; i++) {
4389:                    if (!Character.isLetter(s.charAt(i)) && s.charAt(i) != '_') {
4390:                        return null;
4391:                    }
4392:                    mangled += s.charAt(i);
4393:                }
4394:                if (antlrTool.upperCaseMangledLiterals) {
4395:                    mangled = mangled.toUpperCase();
4396:                }
4397:                return mangled;
4398:            }
4399:
4400:            /** Map an identifier to it's corresponding tree-node variable.
4401:             * This is context-sensitive, depending on the rule and alternative
4402:             * being generated
4403:             * @param idParam The identifier name to map
4404:             * @return The mapped id (which may be the same as the input), or null if the mapping is invalid due to duplicates
4405:             */
4406:            public String mapTreeId(String idParam, ActionTransInfo transInfo) {
4407:                // if not in an action of a rule, nothing to map.
4408:                if (currentRule == null)
4409:                    return idParam;
4410:                //		System.out.print("mapTreeId: "+idParam+" "+currentRule.getRuleName()+" ");
4411:
4412:                boolean in_var = false;
4413:                String id = idParam;
4414:                if (grammar instanceof  TreeWalkerGrammar) {
4415:                    //			RK: hmmm this seems odd. If buildAST is false it translates
4416:                    //			#rulename_in to 'rulename_in' else to 'rulename_AST_in' which indeed
4417:                    //			exists. disabling for now.. and hope it doesn't blow up somewhere.
4418:                    if (!grammar.buildAST) {
4419:                        in_var = true;
4420:                        //				System.out.println("in_var1");
4421:                    }
4422:                    // If the id ends with "_in", then map it to the input variable
4423:                    //			else
4424:                    if (id.length() > 3
4425:                            && id.lastIndexOf("_in") == id.length() - 3) {
4426:                        // Strip off the "_in"
4427:                        id = id.substring(0, id.length() - 3);
4428:                        in_var = true;
4429:                        //				System.out.println("in_var2");
4430:                    }
4431:                }
4432:                //		System.out.print(in_var+"\t");
4433:
4434:                // Check the rule labels.  If id is a label, then the output
4435:                // variable is label_AST, and the input variable is plain label.
4436:                for (int i = 0; i < currentRule.labeledElements.size(); i++) {
4437:                    AlternativeElement elt = (AlternativeElement) currentRule.labeledElements
4438:                            .elementAt(i);
4439:                    if (elt.getLabel().equals(id)) {
4440:                        //				if( in_var )
4441:                        //					System.out.println("returning (vec) "+(in_var ? id : id + "_AST"));
4442:                        return in_var ? id : id + "_AST";
4443:                    }
4444:                }
4445:
4446:                // Failing that, check the id-to-variable map for the alternative.
4447:                // If the id is in the map, then output variable is the name in the
4448:                // map, and input variable is name_in
4449:                String s = (String) treeVariableMap.get(id);
4450:                if (s != null) {
4451:                    if (s == NONUNIQUE) {
4452:                        //				if( in_var )
4453:                        //					System.out.println("returning null (nonunique)");
4454:                        // There is more than one element with this id
4455:                        antlrTool.error("Ambiguous reference to AST element "
4456:                                + id + " in rule " + currentRule.getRuleName());
4457:                        return null;
4458:                    } else if (s.equals(currentRule.getRuleName())) {
4459:                        // a recursive call to the enclosing rule is
4460:                        // ambiguous with the rule itself.
4461:                        //				if( in_var )
4462:                        //					System.out.println("returning null (rulename)");
4463:                        antlrTool.error("Ambiguous reference to AST element "
4464:                                + id + " in rule " + currentRule.getRuleName());
4465:                        return null;
4466:                    } else {
4467:                        //				if( in_var )
4468:                        //				System.out.println("returning "+(in_var?s+"_in":s));
4469:                        return in_var ? s + "_in" : s;
4470:                    }
4471:                }
4472:
4473:                //		System.out.println("Last check: "+id+" == "+currentRule.getRuleName());
4474:                // Failing that, check the rule name itself.  Output variable
4475:                // is rule_AST; input variable is rule_AST_in (treeparsers).
4476:                if (id.equals(currentRule.getRuleName())) {
4477:                    String r = in_var ? id + "_AST_in" : id + "_AST";
4478:                    if (transInfo != null) {
4479:                        if (!in_var) {
4480:                            transInfo.refRuleRoot = r;
4481:                        }
4482:                    }
4483:                    //			if( in_var )
4484:                    //				System.out.println("returning (r) "+r);
4485:                    return r;
4486:                } else {
4487:                    //			if( in_var )
4488:                    //			System.out.println("returning (last) "+id);
4489:                    // id does not map to anything -- return itself.
4490:                    return id;
4491:                }
4492:            }
4493:
4494:            /** Given an element and the name of an associated AST variable,
4495:             * create a mapping between the element "name" and the variable name.
4496:             */
4497:            private void mapTreeVariable(AlternativeElement e, String name) {
4498:                // For tree elements, defer to the root
4499:                if (e instanceof  TreeElement) {
4500:                    mapTreeVariable(((TreeElement) e).root, name);
4501:                    return;
4502:                }
4503:
4504:                // Determine the name of the element, if any, for mapping purposes
4505:                String elName = null;
4506:
4507:                // Don't map labeled items
4508:                if (e.getLabel() == null) {
4509:                    if (e instanceof  TokenRefElement) {
4510:                        // use the token id
4511:                        elName = ((TokenRefElement) e).atomText;
4512:                    } else if (e instanceof  RuleRefElement) {
4513:                        // use the rule name
4514:                        elName = ((RuleRefElement) e).targetRule;
4515:                    }
4516:                }
4517:                // Add the element to the tree variable map if it has a name
4518:                if (elName != null) {
4519:                    if (treeVariableMap.get(elName) != null) {
4520:                        // Name is already in the map -- mark it as duplicate
4521:                        treeVariableMap.remove(elName);
4522:                        treeVariableMap.put(elName, NONUNIQUE);
4523:                    } else {
4524:                        treeVariableMap.put(elName, name);
4525:                    }
4526:                }
4527:            }
4528:
4529:            /** Lexically process tree-specifiers in the action.
4530:             * This will replace #id and #(...) with the appropriate
4531:             * function calls and/or variables.
4532:             */
4533:            protected String processActionForSpecialSymbols(String actionStr,
4534:                    int line, RuleBlock currentRule, ActionTransInfo tInfo) {
4535:                if (actionStr == null || actionStr.length() == 0)
4536:                    return null;
4537:
4538:                // The action trans info tells us (at the moment) whether an
4539:                // assignment was done to the rule's tree root.
4540:                if (grammar == null)
4541:                    return actionStr;
4542:
4543:                if ((grammar.buildAST && actionStr.indexOf('#') != -1)
4544:                        || grammar instanceof  TreeWalkerGrammar
4545:                        || ((grammar instanceof  LexerGrammar || grammar instanceof  ParserGrammar) && actionStr
4546:                                .indexOf('$') != -1)) {
4547:                    // Create a lexer to read an action and return the translated version
4548:                    persistence.antlr.actions.cpp.ActionLexer lexer = new persistence.antlr.actions.cpp.ActionLexer(
4549:                            actionStr, currentRule, this , tInfo);
4550:                    lexer.setLineOffset(line);
4551:                    lexer.setFilename(grammar.getFilename());
4552:                    lexer.setTool(antlrTool);
4553:
4554:                    try {
4555:                        lexer.mACTION(true);
4556:                        actionStr = lexer.getTokenObject().getText();
4557:                        // System.out.println("action translated: "+actionStr);
4558:                        // System.out.println("trans info is "+tInfo);
4559:                    } catch (RecognitionException ex) {
4560:                        lexer.reportError(ex);
4561:                        return actionStr;
4562:                    } catch (TokenStreamException tex) {
4563:                        antlrTool.panic("Error reading action:" + actionStr);
4564:                        return actionStr;
4565:                    } catch (CharStreamException io) {
4566:                        antlrTool.panic("Error reading action:" + actionStr);
4567:                        return actionStr;
4568:                    }
4569:                }
4570:                return actionStr;
4571:            }
4572:
4573:            private String fixNameSpaceOption(String ns) {
4574:                ns = StringUtils.stripFrontBack(ns, "\"", "\"");
4575:                if (ns.length() > 2
4576:                        && !ns.substring(ns.length() - 2, ns.length()).equals(
4577:                                "::"))
4578:                    ns += "::";
4579:                return ns;
4580:            }
4581:
4582:            private void setupGrammarParameters(Grammar g) {
4583:                if (g instanceof  ParserGrammar || g instanceof  LexerGrammar
4584:                        || g instanceof  TreeWalkerGrammar) {
4585:                    /* RK: options also have to be added to Grammar.java and for options
4586:                     * on the file level entries have to be defined in
4587:                     * DefineGrammarSymbols.java and passed around via 'globals' in
4588:                     * antlrTool.java
4589:                     */
4590:                    if (antlrTool.nameSpace != null)
4591:                        nameSpace = antlrTool.nameSpace;
4592:
4593:                    if (antlrTool.namespaceStd != null)
4594:                        namespaceStd = fixNameSpaceOption(antlrTool.namespaceStd);
4595:
4596:                    if (antlrTool.namespaceAntlr != null)
4597:                        namespaceAntlr = fixNameSpaceOption(antlrTool.namespaceAntlr);
4598:
4599:                    genHashLines = antlrTool.genHashLines;
4600:
4601:                    /* let grammar level options override filelevel ones...
4602:                     */
4603:                    if (g.hasOption("namespace")) {
4604:                        Token t = g.getOption("namespace");
4605:                        if (t != null) {
4606:                            nameSpace = new NameSpace(t.getText());
4607:                        }
4608:                    }
4609:                    if (g.hasOption("namespaceAntlr")) {
4610:                        Token t = g.getOption("namespaceAntlr");
4611:                        if (t != null) {
4612:                            String ns = StringUtils.stripFrontBack(t.getText(),
4613:                                    "\"", "\"");
4614:                            if (ns != null) {
4615:                                if (ns.length() > 2
4616:                                        && !ns.substring(ns.length() - 2,
4617:                                                ns.length()).equals("::"))
4618:                                    ns += "::";
4619:                                namespaceAntlr = ns;
4620:                            }
4621:                        }
4622:                    }
4623:                    if (g.hasOption("namespaceStd")) {
4624:                        Token t = g.getOption("namespaceStd");
4625:                        if (t != null) {
4626:                            String ns = StringUtils.stripFrontBack(t.getText(),
4627:                                    "\"", "\"");
4628:                            if (ns != null) {
4629:                                if (ns.length() > 2
4630:                                        && !ns.substring(ns.length() - 2,
4631:                                                ns.length()).equals("::"))
4632:                                    ns += "::";
4633:                                namespaceStd = ns;
4634:                            }
4635:                        }
4636:                    }
4637:                    if (g.hasOption("genHashLines")) {
4638:                        Token t = g.getOption("genHashLines");
4639:                        if (t != null) {
4640:                            String val = StringUtils.stripFrontBack(
4641:                                    t.getText(), "\"", "\"");
4642:                            genHashLines = val.equals("true");
4643:                        }
4644:                    }
4645:                    noConstructors = antlrTool.noConstructors; // get the default
4646:                    if (g.hasOption("noConstructors")) {
4647:                        Token t = g.getOption("noConstructors");
4648:                        if ((t != null)
4649:                                && !(t.getText().equals("true") || t.getText()
4650:                                        .equals("false")))
4651:                            antlrTool
4652:                                    .error(
4653:                                            "noConstructors option must be true or false",
4654:                                            antlrTool.getGrammarFile(), t
4655:                                                    .getLine(), t.getColumn());
4656:                        noConstructors = t.getText().equals("true");
4657:                    }
4658:                }
4659:                if (g instanceof  ParserGrammar) {
4660:                    labeledElementASTType = namespaceAntlr + "RefAST";
4661:                    labeledElementASTInit = namespaceAntlr + "nullAST";
4662:                    if (g.hasOption("ASTLabelType")) {
4663:                        Token tsuffix = g.getOption("ASTLabelType");
4664:                        if (tsuffix != null) {
4665:                            String suffix = StringUtils.stripFrontBack(tsuffix
4666:                                    .getText(), "\"", "\"");
4667:                            if (suffix != null) {
4668:                                usingCustomAST = true;
4669:                                labeledElementASTType = suffix;
4670:                                labeledElementASTInit = suffix + "("
4671:                                        + namespaceAntlr + "nullAST)";
4672:                            }
4673:                        }
4674:                    }
4675:                    labeledElementType = namespaceAntlr + "RefToken ";
4676:                    labeledElementInit = namespaceAntlr + "nullToken";
4677:                    commonExtraArgs = "";
4678:                    commonExtraParams = "";
4679:                    commonLocalVars = "";
4680:                    lt1Value = "LT(1)";
4681:                    exceptionThrown = namespaceAntlr + "RecognitionException";
4682:                    throwNoViable = "throw " + namespaceAntlr
4683:                            + "NoViableAltException(LT(1), getFilename());";
4684:                } else if (g instanceof  LexerGrammar) {
4685:                    labeledElementType = "char ";
4686:                    labeledElementInit = "'\\0'";
4687:                    commonExtraArgs = "";
4688:                    commonExtraParams = "bool _createToken";
4689:                    commonLocalVars = "int _ttype; " + namespaceAntlr
4690:                            + "RefToken _token; int _begin=text.length();";
4691:                    lt1Value = "LA(1)";
4692:                    exceptionThrown = namespaceAntlr + "RecognitionException";
4693:                    throwNoViable = "throw "
4694:                            + namespaceAntlr
4695:                            + "NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());";
4696:                } else if (g instanceof  TreeWalkerGrammar) {
4697:                    labeledElementInit = namespaceAntlr + "nullAST";
4698:                    labeledElementASTInit = namespaceAntlr + "nullAST";
4699:                    labeledElementASTType = namespaceAntlr + "RefAST";
4700:                    labeledElementType = namespaceAntlr + "RefAST";
4701:                    commonExtraParams = namespaceAntlr + "RefAST _t";
4702:                    throwNoViable = "throw " + namespaceAntlr
4703:                            + "NoViableAltException(_t);";
4704:                    lt1Value = "_t";
4705:                    if (g.hasOption("ASTLabelType")) {
4706:                        Token tsuffix = g.getOption("ASTLabelType");
4707:                        if (tsuffix != null) {
4708:                            String suffix = StringUtils.stripFrontBack(tsuffix
4709:                                    .getText(), "\"", "\"");
4710:                            if (suffix != null) {
4711:                                usingCustomAST = true;
4712:                                labeledElementASTType = suffix;
4713:                                labeledElementType = suffix;
4714:                                labeledElementInit = suffix + "("
4715:                                        + namespaceAntlr + "nullAST)";
4716:                                labeledElementASTInit = labeledElementInit;
4717:                                commonExtraParams = suffix + " _t";
4718:                                throwNoViable = "throw " + namespaceAntlr
4719:                                        + "NoViableAltException("
4720:                                        + namespaceAntlr + "RefAST(_t));";
4721:                                lt1Value = "_t";
4722:                            }
4723:                        }
4724:                    }
4725:                    if (!g.hasOption("ASTLabelType")) {
4726:                        g.setOption("ASTLabelType", new Token(
4727:                                ANTLRTokenTypes.STRING_LITERAL, namespaceAntlr
4728:                                        + "RefAST"));
4729:                    }
4730:                    commonExtraArgs = "_t";
4731:                    commonLocalVars = "";
4732:                    exceptionThrown = namespaceAntlr + "RecognitionException";
4733:                } else {
4734:                    antlrTool.panic("Unknown grammar type");
4735:                }
4736:            }
4737:
4738:            // Convert a char or string constant to something C++ likes and
4739:            // check wether it's in range for the current charvocab size.
4740:            private String normalizeStringOrChar(String text) {
4741:                // check to see if the text is a single character
4742:                if (text.startsWith("'")) {
4743:                    // assume it also ends with '
4744:
4745:                    return charFormatter.literalChar(ANTLRLexer
4746:                            .tokenTypeForCharLiteral(text));
4747:                } else {
4748:                    // must be string literal strip of the quotes so
4749:                    // they won't get quoted
4750:                    return "\""
4751:                            + charFormatter.escapeString(StringUtils
4752:                                    .stripFrontBack(text, "\"", "\"")) + "\"";
4753:                }
4754:            }
4755:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.