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: }
|