/lib/antlr-2.7.5/antlr/PythonCodeGenerator.java
Java | 4107 lines | 3929 code | 78 blank | 100 comment | 55 complexity | 82d84ee163e77c6b587e424dcb8da8da MD5 | raw file
Possible License(s): GPL-2.0
Large files files are truncated, but you can click here to view the full file
- // This file is part of PyANTLR. See LICENSE.txt for license
- // details..........Copyright (C) Wolfgang Haefelinger, 2004.
- //
- // $Id:$
- package antlr;
- import java.util.Enumeration;
- import java.util.Hashtable;
- import antlr.collections.impl.BitSet;
- import antlr.collections.impl.Vector;
- import java.io.PrintWriter; //SAS: changed for proper text file io
- import java.io.IOException;
- import java.io.FileWriter;
- /**Generate MyParser.java, MyLexer.java and MyParserTokenTypes.java */
- public class PythonCodeGenerator extends CodeGenerator {
-
- // non-zero if inside syntactic predicate generation
- protected int syntacticPredLevel = 0;
- // Are we generating ASTs (for parsers and tree parsers) right now?
- protected boolean genAST = false;
- // Are we saving the text consumed (for lexers) right now?
- protected boolean saveText = false;
- // Grammar parameters set up to handle different grammar classes.
- // These are used to get instanceof tests out of code generation
- String labeledElementType;
- String labeledElementASTType;
- String labeledElementInit;
- String commonExtraArgs;
- String commonExtraParams;
- String commonLocalVars;
- String lt1Value;
- String exceptionThrown;
- String throwNoViable;
- public static final String initHeaderAction = "__init__";
- public static final String mainHeaderAction = "__main__";
- String lexerClassName;
- String parserClassName;
- String treeWalkerClassName;
- /** Tracks the rule being generated. Used for mapTreeId */
- RuleBlock currentRule;
- /** Tracks the rule or labeled subrule being generated. Used for
- AST generation. */
- String currentASTResult;
- /** Mapping between the ids used in the current alt, and the
- * names of variables used to represent their AST values.
- */
- Hashtable treeVariableMap = new Hashtable();
- /** Used to keep track of which AST variables have been defined in a rule
- * (except for the #rule_name and #rule_name_in var's
- */
- Hashtable declaredASTVariables = new Hashtable();
- /* Count of unnamed generated variables */
- int astVarNumber = 1;
- /** Special value used to mark duplicate in treeVariableMap */
- protected static final String NONUNIQUE = new String();
- public static final int caseSizeThreshold = 127; // ascii is max
- private Vector semPreds;
- /** Create a Java code-generator using the given Grammar.
- * The caller must still call setTool, setBehavior, and setAnalyzer
- * before generating code.
- */
-
- protected void printTabs() {
- for (int i = 0; i < tabs; i++) {
- // don't print tabs ever - replace a tab by ' '
- currentOutput.print(" ");
- }
- }
- public PythonCodeGenerator() {
- super();
- charFormatter = new antlr.PythonCharFormatter();
- DEBUG_CODE_GENERATOR = true;
- }
- /** Adds a semantic predicate string to the sem pred vector
- These strings will be used to build an array of sem pred names
- when building a debugging parser. This method should only be
- called when the debug option is specified
- */
- protected int addSemPred(String predicate) {
- semPreds.appendElement(predicate);
- return semPreds.size() - 1;
- }
- public void exitIfError() {
- if (antlrTool.hasError()) {
- antlrTool.fatalError("Exiting due to errors.");
- }
- }
- protected void checkCurrentOutputStream() {
- try
- {
- if(currentOutput == null)
- throw new NullPointerException();
- }
- catch(Exception e)
- {
- System.err.println("error: current output is not set");
- e.printStackTrace(System.err);
- System.exit(1);
- }
- }
-
- /** Get the identifier portion of an argument-action.
- * For Python the ID of an action is assumed to be everything before
- * the assignment, as Python does not support a type.
- * @param s The action text
- * @param line Line used for error reporting.
- * @param column Line used for error reporting.
- * @return A string containing the text of the identifier
- */
- protected String extractIdOfAction(String s, int line, int column) {
- s = removeAssignmentFromDeclaration(s);
- //wh: removeAssignmentFromDeclaration returns an indentifier that
- //wh: may start with whitespace.
- s = s.trim();
- // println("###ZZZZZ \""+s+"\"");
- return s;
- }
- /** Get the type portion of an argument-action.
- * Python does not have a type declaration before an identifier, so we
- * just return the empty string.
- * @param s The action text
- * @param line Line used for error reporting.
- * @return A string containing the text of the type
- */
- protected String extractTypeOfAction(String s, int line, int column) {
- return "";
- }
- protected void flushTokens() {
- try
- {
- boolean generated = false;
- checkCurrentOutputStream();
- println("");
- println("### import antlr.Token ");
- println("from antlr import Token");
- println("### >>>The Known Token Types <<<");
- /* save current stream */
- PrintWriter cout = currentOutput;
- // Loop over all token managers (some of which are lexers)
- Enumeration tmIter =
- behavior.tokenManagers.elements();
- while (tmIter.hasMoreElements())
- {
- TokenManager tm =
- (TokenManager)tmIter.nextElement();
- if (!tm.isReadOnly())
- {
- // Write the token manager tokens as Java
- // this must appear before genTokenInterchange so that
- // labels are set on string literals
- if(! generated) {
- genTokenTypes(tm);
- generated = true;
- }
- /* restore stream */
- currentOutput = cout;
- // Write the token manager tokens as plain text
- genTokenInterchange(tm);
- currentOutput = cout;
- }
- exitIfError();
- }
- }
- catch(Exception e) {
- exitIfError();
- }
- checkCurrentOutputStream();
- println("");
- }
- /**Generate the parser, lexer, treeparser, and token types in Java */
- public void gen() {
- // Do the code generation
- try {
- // Loop over all grammars
- Enumeration grammarIter = behavior.grammars.elements();
- while (grammarIter.hasMoreElements()) {
- Grammar g = (Grammar)grammarIter.nextElement();
- // Connect all the components to each other
- g.setGrammarAnalyzer(analyzer);
- g.setCodeGenerator(this);
- analyzer.setGrammar(g);
- // To get right overloading behavior across hetrogeneous grammars
- setupGrammarParameters(g);
- g.generate();
- // print out the grammar with lookahead sets (and FOLLOWs)
- // System.out.print(g.toString());
- exitIfError();
- }
-
-
- }
- catch (IOException e) {
- antlrTool.reportException(e, null);
- }
- }
- /** Generate code for the given grammar element.
- * @param blk The {...} action to generate
- */
- public void gen(ActionElement action) {
- if (action.isSemPred) {
- genSemPred(action.actionText, action.line);
- }
- else
- {
- if (grammar.hasSyntacticPredicate) {
- println("if not self.inputState.guessing:");
- tabs++;
- }
- // get the name of the followSet for the current rule so that we
- // can replace $FOLLOW in the .g file.
- ActionTransInfo tInfo = new ActionTransInfo();
- String actionStr = processActionForSpecialSymbols(action.actionText,
- action.getLine(),
- currentRule,
- tInfo);
- if (tInfo.refRuleRoot != null) {
- // Somebody referenced "#rule", make sure translated var is valid
- // assignment to #rule is left as a ref also, meaning that assignments
- // with no other refs like "#rule = foo();" still forces this code to be
- // generated (unnecessarily).
- println(tInfo.refRuleRoot + " = currentAST.root");
- }
- // dump the translated action
- printAction(actionStr);
- if (tInfo.assignToRoot) {
- // Somebody did a "#rule=", reset internal currentAST.root
- println("currentAST.root = " + tInfo.refRuleRoot + "");
- println("if (" + tInfo.refRuleRoot + " != None) and (" + tInfo.refRuleRoot + ".getFirstChild() != None):");
- tabs++;
- println("currentAST.child = " + tInfo.refRuleRoot + ".getFirstChild()");
- tabs--;
- println("else:");
- tabs++;
- println("currentAST.child = " + tInfo.refRuleRoot);
- tabs--;
- println("currentAST.advanceChildToEnd()");
- }
- if (grammar.hasSyntacticPredicate) {
- tabs--;
- }
- }
- }
- /** Generate code for the given grammar element.
- * @param blk The "x|y|z|..." block to generate
- */
- public void gen(AlternativeBlock blk) {
- if (DEBUG_CODE_GENERATOR) System.out.println("gen(" + blk + ")");
- genBlockPreamble(blk);
- genBlockInitAction(blk);
-
- // Tell AST generation to build subrule result
- String saveCurrentASTResult = currentASTResult;
- if (blk.getLabel() != null) {
- currentASTResult = blk.getLabel();
- }
- boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
- {
- int _tabs_ = tabs;
- PythonBlockFinishingInfo howToFinish = genCommonBlock(blk, true);
- genBlockFinish(howToFinish, throwNoViable);
- tabs = _tabs_;
- }
- // Restore previous AST generation
- currentASTResult = saveCurrentASTResult;
- }
- /** Generate code for the given grammar element.
- * @param blk The block-end element to generate. Block-end
- * elements are synthesized by the grammar parser to represent
- * the end of a block.
- */
- public void gen(BlockEndElement end) {
- if (DEBUG_CODE_GENERATOR) System.out.println("genRuleEnd(" + end + ")");
- }
- /** Generate code for the given grammar element.
- * @param blk The character literal reference to generate
- */
- public void gen(CharLiteralElement atom) {
- if (DEBUG_CODE_GENERATOR) System.out.println("genChar(" + atom + ")");
- if (atom.getLabel() != null) {
- println(atom.getLabel() + " = " + lt1Value );
- }
- boolean oldsaveText = saveText;
- saveText = saveText && atom.getAutoGenType() == GrammarElement.AUTO_GEN_NONE;
- genMatch(atom);
- saveText = oldsaveText;
- }
- String toString(boolean v) {
- String s;
- if(v)
- s = "True";
- else
- s = "False";
- return s;
- }
-
- /** Generate code for the given grammar element.
- * @param blk The character-range reference to generate
- */
- public void gen(CharRangeElement r) {
- if (r.getLabel() != null && syntacticPredLevel == 0) {
- println(r.getLabel() + " = " + lt1Value);
- }
- boolean flag = ( grammar instanceof LexerGrammar &&
- ( !saveText ||
- r.getAutoGenType() ==
- GrammarElement.AUTO_GEN_BANG ) );
- if (flag) {
- println("_saveIndex = self.text.length()");
- }
- println("self.matchRange(u" + r.beginText + ", u" + r.endText + ")");
- if (flag) {
- println("self.text.setLength(_saveIndex)");
- }
- }
- /** Generate the lexer Java file */
- public void gen(LexerGrammar g) throws IOException
- {
- // If debugging, create a new sempred vector for this grammar
- if (g.debuggingOutput)
- semPreds = new Vector();
- setGrammar(g);
- if (!(grammar instanceof LexerGrammar)) {
- antlrTool.panic("Internal error generating lexer");
- }
- // SAS: moved output creation to method so a subclass can change
- // how the output is generated (for VAJ interface)
- setupOutput(grammar.getClassName());
- genAST = false; // no way to gen trees.
- saveText = true; // save consumed characters.
- tabs = 0;
- // Generate header common to all Python output files
- genHeader();
- // Generate header specific to lexer Python file
- println("### import antlr and other modules ..");
- println("import sys");
- println("import antlr");
- println("");
- println("version = sys.version.split()[0]");
- println("if version < '2.2.1':");
- tabs++;
- println("False = 0");
- tabs--;
- println("if version < '2.3':");
- tabs++;
- println("True = not False");
- tabs--;
- println("### header action >>> ");
- printActionCode(behavior.getHeaderAction(""),0);
- println("### header action <<< ");
-
- // Generate user-defined lexer file preamble
- println("### preamble action >>> ");
- printActionCode(grammar.preambleAction.getText(),0);
- println("### preamble action <<< ");
- // Generate lexer class definition
- String sup = null;
- if (grammar.superClass != null) {
- sup = grammar.superClass;
- }
- else {
- sup = "antlr." + grammar.getSuperClass();
- }
- // get prefix (replaces "public" and lets user specify)
- String prefix = "";
- Token tprefix = (Token)grammar.options.get("classHeaderPrefix");
- if (tprefix != null) {
- String p = StringUtils.stripFrontBack(tprefix.getText(), "\"", "\"");
- if (p != null) {
- prefix = p;
- }
- }
- // print my literals
- println("### >>>The Literals<<<");
- println("literals = {}");
- Enumeration keys = grammar.tokenManager.getTokenSymbolKeys();
- while (keys.hasMoreElements()) {
- String key = (String)keys.nextElement();
- if (key.charAt(0) != '"') {
- continue;
- }
- TokenSymbol sym = grammar.tokenManager.getTokenSymbol(key);
- if (sym instanceof StringLiteralSymbol) {
- StringLiteralSymbol s = (StringLiteralSymbol)sym;
- println("literals[u" + s.getId() + "] = " + s.getTokenType());
- }
- }
- println("");
- flushTokens();
- // print javadoc comment if any
- genJavadocComment(grammar);
- // class name remains the same, it's the module that changes in python.
- println("class " + lexerClassName + "(" + sup + ") :");
- tabs++;
-
- printGrammarAction(grammar);
- // Generate the constructor from InputStream, which in turn
- // calls the ByteBuffer constructor
- //
- println("def __init__(self, *argv, **kwargs) :");
- tabs++;
- println(sup + ".__init__(self, *argv, **kwargs)");
- // Generate the setting of various generated options.
- // These need to be before the literals since ANTLRHashString depends on
- // the casesensitive stuff.
- println("self.caseSensitiveLiterals = " + toString(g.caseSensitiveLiterals));
- println("self.setCaseSensitive(" + toString(g.caseSensitive) + ")" );
- println("self.literals = literals");
- Enumeration ids;
- // generate the rule name array for debugging
- if (grammar.debuggingOutput) {
- println("ruleNames[] = [");
- ids = grammar.rules.elements();
- int ruleNum = 0;
- tabs++;
- while (ids.hasMoreElements()) {
- GrammarSymbol sym = (GrammarSymbol)ids.nextElement();
- if (sym instanceof RuleSymbol)
- println("\"" + ((RuleSymbol)sym).getId() + "\",");
- }
- tabs--;
- println("]");
- }
-
- genHeaderInit(grammar);
- tabs--;
- // wh: iterator moved to base class as proposed by mk.
- // println("");
- // Generate the __iter__ method for Python CharScanner (sub)classes.
- // genIterator();
- // Generate nextToken() rule.
- // nextToken() is a synthetic lexer rule that is the implicit OR of all
- // user-defined lexer rules.
- genNextToken();
- println("");
- // Generate code for each rule in the lexer
- ids = grammar.rules.elements();
- int ruleNum = 0;
- while (ids.hasMoreElements()) {
- RuleSymbol sym = (RuleSymbol)ids.nextElement();
- // Don't generate the synthetic rules
- if (!sym.getId().equals("mnextToken")) {
- genRule(sym, false, ruleNum++);
- }
- exitIfError();
- }
- // Generate the semantic predicate map for debugging
- if (grammar.debuggingOutput)
- genSemPredMap();
- // Generate the bitsets used throughout the lexer
- genBitsets(bitsetsUsed, ((LexerGrammar)grammar).charVocabulary.size());
- println("");
- genHeaderMain(grammar);
- // Close the lexer output stream
- currentOutput.close();
- currentOutput = null;
- }
- protected void genHeaderMain(Grammar grammar)
- {
- String h = grammar.getClassName() + "." + mainHeaderAction;
- String s = behavior.getHeaderAction(h);
- if (isEmpty(s)) {
- s = behavior.getHeaderAction(mainHeaderAction);
- }
- if(isEmpty(s)) {
- if(grammar instanceof LexerGrammar) {
- int _tabs = tabs;
- tabs = 0;
- println("### __main__ header action >>> ");
- genLexerTest();
- tabs = 0;
- println("### __main__ header action <<< ");
- tabs = _tabs;
- }
- } else {
- int _tabs = tabs;
- tabs = 0;
- println("");
- println("### __main__ header action >>> ");
- printMainFunc(s);
- tabs = 0;
- println("### __main__ header action <<< ");
- tabs = _tabs;
- }
- }
- protected void genHeaderInit(Grammar grammar)
- {
- String h = grammar.getClassName() + "." + initHeaderAction;
- String s = behavior.getHeaderAction(h);
-
- if (isEmpty(s)) {
- s = behavior.getHeaderAction(initHeaderAction);
- }
- if(isEmpty(s)) {
- /* nothing gets generated by default */
- } else {
- int _tabs = tabs;
- println("### __init__ header action >>> ");
- printActionCode(s,0);
- tabs = _tabs;
- println("### __init__ header action <<< ");
- }
- }
-
- protected void printMainFunc(String s) {
- int _tabs = tabs;
- tabs = 0;
- println("if __name__ == '__main__':");
- tabs++;
- printActionCode(s,0);
- tabs--;
- tabs = _tabs;
- }
- /** Generate code for the given grammar element.
- * @param blk The (...)+ block to generate
- */
- public void gen(OneOrMoreBlock blk) {
- String label;
- String cnt;
- /* save current tabs */
- int _tabs_ = tabs;
- genBlockPreamble(blk);
- if (blk.getLabel() != null)
- {
- cnt = "_cnt_" + blk.getLabel();
- }
- else {
- cnt = "_cnt" + blk.ID;
- }
- println("" + cnt + "= 0");
- println("while True:");
- tabs++;
- _tabs_ = tabs;
- // generate the init action for ()+ ()* inside the loop
- // this allows us to do usefull EOF checking...
- genBlockInitAction(blk);
- // Tell AST generation to build subrule result
- String saveCurrentASTResult = currentASTResult;
- if (blk.getLabel() != null) {
- currentASTResult = blk.getLabel();
- }
- boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
- // generate exit test if greedy set to false
- // and an alt is ambiguous with exit branch
- // or when lookahead derived purely from end-of-file
- // Lookahead analysis stops when end-of-file is hit,
- // returning set {epsilon}. Since {epsilon} is not
- // ambig with any real tokens, no error is reported
- // by deterministic() routines and we have to check
- // for the case where the lookahead depth didn't get
- // set to NONDETERMINISTIC (this only happens when the
- // FOLLOW contains real atoms + epsilon).
- boolean generateNonGreedyExitPath = false;
- int nonGreedyExitDepth = grammar.maxk;
- if (!blk.greedy &&
- blk.exitLookaheadDepth <= grammar.maxk &&
- blk.exitCache[blk.exitLookaheadDepth].containsEpsilon())
- {
- generateNonGreedyExitPath = true;
- nonGreedyExitDepth = blk.exitLookaheadDepth;
- }
- else
- {
- if (!blk.greedy &&
- blk.exitLookaheadDepth == LLkGrammarAnalyzer.NONDETERMINISTIC) {
- generateNonGreedyExitPath = true;
- }
- }
- // generate exit test if greedy set to false
- // and an alt is ambiguous with exit branch
- if (generateNonGreedyExitPath)
- {
- println("### nongreedy (...)+ loop; exit depth is " + blk.exitLookaheadDepth);
- String predictExit =
- getLookaheadTestExpression(
- blk.exitCache,
- nonGreedyExitDepth);
-
- println("### nongreedy exit test");
- println("if " + cnt + " >= 1 and " + predictExit + ":");
- tabs++;
- println("break");
- tabs--;
- }
- {
- int _tabs = tabs;
- PythonBlockFinishingInfo howToFinish = genCommonBlock(blk, false);
- genBlockFinish(howToFinish, "break");
- tabs = _tabs;
- }
- /* no matter what previous block did, here we have to continue
- ** one the 'while block' level. Reseting tabs .. */
- tabs = _tabs_;
- println(cnt + " += 1");
- tabs = _tabs_;
- tabs--;
- println("if " + cnt + " < 1:");
- tabs++;
- println(throwNoViable);
- tabs--;
- // Restore previous AST generation
- currentASTResult = saveCurrentASTResult;
- }
- /** Generate the parser Java file */
- public void gen(ParserGrammar g)
- throws IOException {
- // if debugging, set up a new vector to keep track of sempred
- // strings for this grammar
- if (g.debuggingOutput)
- semPreds = new Vector();
- setGrammar(g);
- if (!(grammar instanceof ParserGrammar)) {
- antlrTool.panic("Internal error generating parser");
- }
- // Open the output stream for the parser and set the currentOutput
- // SAS: moved file setup so subclass could do it (for VAJ interface)
- setupOutput(grammar.getClassName());
- genAST = grammar.buildAST;
- tabs = 0;
- // Generate the header common to all output files.
- genHeader();
- // Generate header specific to lexer Java file
- println("### import antlr and other modules ..");
- println("import sys");
- println("import antlr");
- println("");
- println("version = sys.version.split()[0]");
- println("if version < '2.2.1':");
- tabs++;
- println("False = 0");
- tabs--;
- println("if version < '2.3':");
- tabs++;
- println("True = not False");
- tabs--;
- println("### header action >>> ");
- printActionCode(behavior.getHeaderAction(""),0);
- println("### header action <<< ");
- println("### preamble action>>>");
- // Output the user-defined parser preamble
- printActionCode(grammar.preambleAction.getText(),0);
- println("### preamble action <<<");
-
- flushTokens();
- // Generate parser class definition
- String sup = null;
- if (grammar.superClass != null)
- sup = grammar.superClass;
- else
- sup = "antlr." + grammar.getSuperClass();
- // print javadoc comment if any
- genJavadocComment(grammar);
- // get prefix (replaces "public" and lets user specify)
- String prefix = "";
- Token tprefix = (Token)grammar.options.get("classHeaderPrefix");
- if (tprefix != null) {
- String p = StringUtils.stripFrontBack(tprefix.getText(), "\"", "\"");
- if (p != null) {
- prefix = p;
- }
- }
- print("class " + parserClassName + "(" + sup);
- println("):");
- tabs++;
- // set up an array of all the rule names so the debugger can
- // keep track of them only by number -- less to store in tree...
- if (grammar.debuggingOutput) {
- println("_ruleNames = [");
- Enumeration ids = grammar.rules.elements();
- int ruleNum = 0;
- tabs++;
- while (ids.hasMoreElements()) {
- GrammarSymbol sym = (GrammarSymbol)ids.nextElement();
- if (sym instanceof RuleSymbol)
- println("\"" + ((RuleSymbol)sym).getId() + "\",");
- }
- tabs--;
- println("]");
- }
- // Generate user-defined parser class members
- printGrammarAction(grammar);
- // Generate parser class constructor from TokenBuffer
- println("");
- println("def __init__(self, *args, **kwargs):");
- tabs++;
- println(sup + ".__init__(self, *args, **kwargs)");
- println("self.tokenNames = _tokenNames");
- // if debugging, set up arrays and call the user-overridable
- // debugging setup method
- if (grammar.debuggingOutput) {
- println("self.ruleNames = _ruleNames");
- println("self.semPredNames = _semPredNames");
- println("self.setupDebugging(self.tokenBuf)");
- }
- if (grammar.buildAST) {
- println("self.buildTokenTypeASTClassMap()");
- println("self.astFactory = antlr.ASTFactory(self.getTokenTypeToASTClassMap())");
- if(labeledElementASTType != null)
- {
- println("self.astFactory.setASTNodeClass("+
- labeledElementASTType+")");
- }
- }
- genHeaderInit(grammar);
- println("");
- // Generate code for each rule in the grammar
- Enumeration ids = grammar.rules.elements();
- int ruleNum = 0;
- while (ids.hasMoreElements()) {
- GrammarSymbol sym = (GrammarSymbol)ids.nextElement();
- if (sym instanceof RuleSymbol) {
- RuleSymbol rs = (RuleSymbol)sym;
- genRule(rs, rs.references.size() == 0, ruleNum++);
- }
- exitIfError();
- }
- if ( grammar.buildAST ) {
- genTokenASTNodeMap();
- }
-
- // Generate the token names
- genTokenStrings();
- // Generate the bitsets used throughout the grammar
- genBitsets(bitsetsUsed, grammar.tokenManager.maxTokenType());
- // Generate the semantic predicate map for debugging
- if (grammar.debuggingOutput)
- genSemPredMap();
- // Close class definition
- println("");
- tabs = 0;
- genHeaderMain(grammar);
- // Close the parser output stream
- currentOutput.close();
- currentOutput = null;
- }
- /** Generate code for the given grammar element.
- * @param blk The rule-reference to generate
- */
- public void gen(RuleRefElement rr) {
- if (DEBUG_CODE_GENERATOR) System.out.println("genRR(" + rr + ")");
- RuleSymbol rs = (RuleSymbol)grammar.getSymbol(rr.targetRule);
- if (rs == null || !rs.isDefined()) {
- // Is this redundant???
- antlrTool.error("Rule '" + rr.targetRule + "' is not defined", grammar.getFilename(), rr.getLine(), rr.getColumn());
- return;
- }
- if (!(rs instanceof RuleSymbol)) {
- // Is this redundant???
- antlrTool.error("'" + rr.targetRule + "' does not name a grammar rule", grammar.getFilename(), rr.getLine(), rr.getColumn());
- return;
- }
- genErrorTryForElement(rr);
- // AST value for labeled rule refs in tree walker.
- // This is not AST construction; it is just the input tree node value.
- if (grammar instanceof TreeWalkerGrammar &&
- rr.getLabel() != null &&
- syntacticPredLevel == 0) {
- println(rr.getLabel() + " = antlr.ifelse(_t == antlr.ASTNULL, None, " + lt1Value + ")");
- }
- // if in lexer and ! on rule ref or alt or rule, save buffer index to kill later
- if (grammar instanceof LexerGrammar && (!saveText || rr.getAutoGenType() == GrammarElement.AUTO_GEN_BANG)) {
- println("_saveIndex = self.text.length()");
- }
- // Process return value assignment if any
- printTabs();
- if (rr.idAssign != null) {
- // Warn if the rule has no return type
- if (rs.block.returnAction == null) {
- antlrTool.warning("Rule '" + rr.targetRule + "' has no return type", grammar.getFilename(), rr.getLine(), rr.getColumn());
- }
- _print(rr.idAssign + "=");
- }
- else {
- // Warn about return value if any, but not inside syntactic predicate
- if (!(grammar instanceof LexerGrammar) && syntacticPredLevel == 0 && rs.block.returnAction != null) {
- antlrTool.warning("Rule '" + rr.targetRule + "' returns a value", grammar.getFilename(), rr.getLine(), rr.getColumn());
- }
- }
- // Call the rule
- GenRuleInvocation(rr);
- // if in lexer and ! on element or alt or rule, save buffer index to kill later
- if (grammar instanceof LexerGrammar && (!saveText || rr.getAutoGenType() == GrammarElement.AUTO_GEN_BANG)) {
- println("self.text.setLength(_saveIndex)");
- }
- // if not in a syntactic predicate
- if (syntacticPredLevel == 0) {
- boolean doNoGuessTest = (
- grammar.hasSyntacticPredicate && (
- grammar.buildAST && rr.getLabel() != null ||
- (genAST && rr.getAutoGenType() == GrammarElement.AUTO_GEN_NONE)
- )
- );
- if (doNoGuessTest) {
- // println("if (inputState.guessing==0) {");
- // tabs++;
- }
- if (grammar.buildAST && rr.getLabel() != null) {
- // always gen variable for rule return on labeled rules
- println(rr.getLabel() + "_AST = self.returnAST");
- }
- if (genAST) {
- switch (rr.getAutoGenType()) {
- case GrammarElement.AUTO_GEN_NONE:
- println("self.addASTChild(currentAST, self.returnAST)");
- break;
- case GrammarElement.AUTO_GEN_CARET:
- antlrTool.error("Internal: encountered ^ after rule reference");
- break;
- default:
- break;
- }
- }
- // if a lexer and labeled, Token label defined at rule level, just set it here
- if (grammar instanceof LexerGrammar && rr.getLabel() != null) {
- println(rr.getLabel() + " = self._returnToken");
- }
- if (doNoGuessTest) {
- }
- }
- genErrorCatchForElement(rr);
- }
- /** Generate code for the given grammar element.
- * @param blk The string-literal reference to generate
- */
- public void gen(StringLiteralElement atom) {
- if (DEBUG_CODE_GENERATOR) System.out.println("genString(" + atom + ")");
- // Variable declarations for labeled elements
- if (atom.getLabel() != null && syntacticPredLevel == 0) {
- println(atom.getLabel() + " = " + lt1Value + "");
- }
- // AST
- genElementAST(atom);
- // is there a bang on the literal?
- boolean oldsaveText = saveText;
- saveText = saveText && atom.getAutoGenType() == GrammarElement.AUTO_GEN_NONE;
- // matching
- genMatch(atom);
- saveText = oldsaveText;
- // tack on tree cursor motion if doing a tree walker
- if (grammar instanceof TreeWalkerGrammar) {
- println("_t = _t.getNextSibling()");
- }
- }
- /** Generate code for the given grammar element.
- * @param blk The token-range reference to generate
- */
- public void gen(TokenRangeElement r) {
- genErrorTryForElement(r);
- if (r.getLabel() != null && syntacticPredLevel == 0) {
- println(r.getLabel() + " = " + lt1Value);
- }
- // AST
- genElementAST(r);
- // match
- println("self.matchRange(u" + r.beginText + ", u" + r.endText + ")");
- genErrorCatchForElement(r);
- }
- /** Generate code for the given grammar element.
- * @param blk The token-reference to generate
- */
- public void gen(TokenRefElement atom) {
- if (DEBUG_CODE_GENERATOR) System.out.println("genTokenRef(" + atom + ")");
- if (grammar instanceof LexerGrammar) {
- antlrTool.panic("Token reference found in lexer");
- }
- genErrorTryForElement(atom);
- // Assign Token value to token label variable
- if (atom.getLabel() != null && syntacticPredLevel == 0) {
- println(atom.getLabel() + " = " + lt1Value + "");
- }
- // AST
- genElementAST(atom);
- // matching
- genMatch(atom);
- genErrorCatchForElement(atom);
- // tack on tree cursor motion if doing a tree walker
- if (grammar instanceof TreeWalkerGrammar) {
- println("_t = _t.getNextSibling()");
- }
- }
- public void gen(TreeElement t) {
- // save AST cursor
- println("_t" + t.ID + " = _t");
- // If there is a label on the root, then assign that to the variable
- if (t.root.getLabel() != null) {
- println(t.root.getLabel() + " = antlr.ifelse(_t == antlr.ASTNULL, None, _t)");
- }
- // check for invalid modifiers ! and ^ on tree element roots
- if ( t.root.getAutoGenType() == GrammarElement.AUTO_GEN_BANG ) {
- antlrTool.error("Suffixing a root node with '!' is not implemented",
- grammar.getFilename(), t.getLine(), t.getColumn());
- t.root.setAutoGenType(GrammarElement.AUTO_GEN_NONE);
- }
- if ( t.root.getAutoGenType() == GrammarElement.AUTO_GEN_CARET ) {
- antlrTool.warning("Suffixing a root node with '^' is redundant; already a root",
- grammar.getFilename(), t.getLine(), t.getColumn());
- t.root.setAutoGenType(GrammarElement.AUTO_GEN_NONE);
- }
- // Generate AST variables
- genElementAST(t.root);
- if (grammar.buildAST) {
- // Save the AST construction state
- println("_currentAST" + t.ID + " = currentAST.copy()");
- // Make the next item added a child of the TreeElement root
- println("currentAST.root = currentAST.child");
- println("currentAST.child = None");
- }
- // match root
- if ( t.root instanceof WildcardElement ) {
- println("if not _t: raise antlr.MismatchedTokenException()");
- }
- else {
- genMatch(t.root);
- }
- // move to list of children
- println("_t = _t.getFirstChild()");
- // walk list of children, generating code for each
- for (int i = 0; i < t.getAlternatives().size(); i++) {
- Alternative a = t.getAlternativeAt(i);
- AlternativeElement e = a.head;
- while (e != null) {
- e.generate();
- e = e.next;
- }
- }
- if (grammar.buildAST) {
- // restore the AST construction state to that just after the
- // tree root was added
- println("currentAST = _currentAST" + t.ID + "");
- }
- // restore AST cursor
- println("_t = _t" + t.ID + "");
- // move cursor to sibling of tree just parsed
- println("_t = _t.getNextSibling()");
- }
- /** Generate the tree-parser Java file */
- public void gen(TreeWalkerGrammar g) throws IOException {
- // SAS: debugging stuff removed for now...
- setGrammar(g);
- if (!(grammar instanceof TreeWalkerGrammar)) {
- antlrTool.panic("Internal error generating tree-walker");
- }
- // Open the output stream for the parser and set the currentOutput
- // SAS: move file open to method so subclass can override it
- // (mainly for VAJ interface)
- setupOutput(grammar.getClassName());
- genAST = grammar.buildAST;
- tabs = 0;
- // Generate the header common to all output files.
- genHeader();
- // Generate header specific to lexer Java file
- println("### import antlr and other modules ..");
- println("import sys");
- println("import antlr");
- println("");
- println("version = sys.version.split()[0]");
- println("if version < '2.2.1':");
- tabs++;
- println("False = 0");
- tabs--;
- println("if version < '2.3':");
- tabs++;
- println("True = not False");
- tabs--;
- println("### header action >>> ");
- printActionCode(behavior.getHeaderAction(""),0);
- println("### header action <<< ");
- flushTokens();
- println("### user code>>>");
- // Output the user-defined parser preamble
- printActionCode(grammar.preambleAction.getText(),0);
- println("### user code<<<");
- // Generate parser class definition
- String sup = null;
- if (grammar.superClass != null) {
- sup = grammar.superClass;
- }
- else {
- sup = "antlr." + grammar.getSuperClass();
- }
- println("");
- // get prefix (replaces "public" and lets user specify)
- String prefix = "";
- Token tprefix = (Token)grammar.options.get("classHeaderPrefix");
- if (tprefix != null) {
- String p = StringUtils.stripFrontBack(tprefix.getText(), "\"", "\"");
- if (p != null) {
- prefix = p;
- }
- }
-
- // print javadoc comment if any
- genJavadocComment(grammar);
- println("class " + treeWalkerClassName + "(" + sup + "):");
- tabs++;
-
- // Generate default parser class constructor
- println("");
- println("# ctor ..");
- println("def __init__(self, *args, **kwargs):");
- tabs++;
- println(sup + ".__init__(self, *args, **kwargs)");
- println("self.tokenNames = _tokenNames");
- genHeaderInit(grammar);
- tabs--;
- println("");
- // print grammar specific action
- printGrammarAction(grammar);
- // Generate code for each rule in the grammar
- Enumeration ids = grammar.rules.elements();
- int ruleNum = 0;
- String ruleNameInits = "";
- while (ids.hasMoreElements()) {
- GrammarSymbol sym = (GrammarSymbol)ids.nextElement();
- if (sym instanceof RuleSymbol) {
- RuleSymbol rs = (RuleSymbol)sym;
- genRule(rs, rs.references.size() == 0, ruleNum++);
- }
- exitIfError();
- }
- // Generate the token names
- genTokenStrings();
- // Generate the bitsets used throughout the grammar
- genBitsets(bitsetsUsed, grammar.tokenManager.maxTokenType());
-
- tabs = 0;
- genHeaderMain(grammar);
- // Close the parser output stream
- currentOutput.close();
- currentOutput = null;
- }
- /** Generate code for the given grammar element.
- * @param wc The wildcard element to generate
- */
- public void gen(WildcardElement wc) {
- // Variable assignment for labeled elements
- if (wc.getLabel() != null && syntacticPredLevel == 0) {
- println(wc.getLabel() + " = " + lt1Value + "");
- }
- // AST
- genElementAST(wc);
- // Match anything but EOF
- if (grammar instanceof TreeWalkerGrammar) {
- println("if not _t:");
- tabs++;
- println("raise MismatchedTokenException()");
- tabs--;
- }
- else if (grammar instanceof LexerGrammar) {
- if (grammar instanceof LexerGrammar &&
- (!saveText || wc.getAutoGenType() == GrammarElement.AUTO_GEN_BANG)) {
- println("_saveIndex = self.text.length()");
- }
- println("self.matchNot(antlr.EOF_CHAR)");
- if (grammar instanceof LexerGrammar &&
- (!saveText || wc.getAutoGenType() == GrammarElement.AUTO_GEN_BANG)) {
- println("self.text.setLength(_saveIndex)"); // kill text atom put in buffer
- }
- }
- else {
- println("self.matchNot(" + getValueString(Token.EOF_TYPE,false) + ")");
- }
- // tack on tree cursor motion if doing a tree walker
- if (grammar instanceof TreeWalkerGrammar) {
- println("_t = _t.getNextSibling()");
- }
- }
- /** Generate code for the given grammar element.
- * @param blk The (...)* block to generate
- */
- public void gen(ZeroOrMoreBlock blk) {
- int _tabs_ = tabs;
- genBlockPreamble(blk);
- String label;
- println("while True:");
- tabs++;
- _tabs_ = tabs;
- // generate the init action for ()* inside the loop
- // this allows us to do usefull EOF checking...
- genBlockInitAction(blk);
- // Tell AST generation to build subrule result
- String saveCurrentASTResult = currentASTResult;
- if (blk.getLabel() != null) {
- currentASTResult = blk.getLabel();
- }
- boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
- // generate exit test if greedy set to false
- // and an alt is ambiguous with exit branch
- // or when lookahead derived purely from end-of-file
- // Lookahead analysis stops when end-of-file is hit,
- // returning set {epsilon}. Since {epsilon} is not
- // ambig with any real tokens, no error is reported
- // by deterministic() routines and we have to check
- // for the case where the lookahead depth didn't get
- // set to NONDETERMINISTIC (this only happens when the
- // FOLLOW contains real atoms + epsilon).
- boolean generateNonGreedyExitPath = false;
- int nonGreedyExitDepth = grammar.maxk;
- if (!blk.greedy &&
- blk.exitLookaheadDepth <= grammar.maxk &&
- blk.exitCache[blk.exitLookaheadDepth].containsEpsilon()) {
- generateNonGreedyExitPath = true;
- nonGreedyExitDepth = blk.exitLookaheadDepth;
- }
- else if (!blk.greedy &&
- blk.exitLookaheadDepth == LLkGrammarAnalyzer.NONDETERMINISTIC) {
- generateNonGreedyExitPath = true;
- }
- if (generateNonGreedyExitPath) {
- if (DEBUG_CODE_GENERATOR) {
- System.out.println("nongreedy (...)* loop; exit depth is " +
- blk.exitLookaheadDepth);
- }
- String predictExit =
- getLookaheadTestExpression(blk.exitCache,
- nonGreedyExitDepth);
- println("### nongreedy exit test");
- println("if (" + predictExit + "):");
- tabs++;
- println("break");
- tabs--;
- }
- {
- int _tabs = tabs;
- PythonBlockFinishingInfo howToFinish = genCommonBlock(blk, false);
- genBlockFinish(howToFinish, "break");
- tabs = _tabs;
- }
- tabs = _tabs_; /* no matter where we are */
- tabs--;
- // Restore previous AST generation
- currentASTResult = saveCurrentASTResult;
- }
- /** Generate an alternative.
- * @param alt The alternative to generate
- * @param blk The block to which the alternative belongs
- */
- protected void genAlt(Alternative alt, AlternativeBlock blk) {
- // Save the AST generation state, and set it to that of the alt
- boolean savegenAST = genAST;
- genAST = genAST && alt.getAutoGen();
- boolean oldsaveTest = saveText;
- saveText = saveText && alt.getAutoGen();
- // Reset the variable name map for the alternative
- Hashtable saveMap = treeVariableMap;
- treeVariableMap = new Hashtable();
- // Generate try block around the alt for error handling
- if (alt.exceptionSpec != null) {
- println("try:");
- tabs++;
- }
- println("pass"); // make sure that always something gets generated ..
- AlternativeElement elem = alt.head;
- while (!(elem instanceof BlockEndElement)) {
- elem.generate(); // alt can begin with anything. Ask target to gen.
- elem = elem.next;
- }
- if (genAST) {
- if (blk instanceof RuleBlock) {
- // Set the AST return value for the rule
- RuleBlock rblk = (RuleBlock)blk;
- if (grammar.hasSyntacticPredicate) {
- }
- println(rblk.getRuleName() + "_AST = currentAST.root");
- if (grammar.hasSyntacticPredicate) {
- }
- }
- else if (blk.getLabel() != null) {
- antlrTool.warning(
- "Labeled subrules not yet supported",
- grammar.getFilename(), blk.getLine(), blk.getColumn());
- }
- }
- if (alt.exceptionSpec != null) {
- tabs--;
- genErrorHandler(alt.exceptionSpec);
- }
- genAST = savegenAST;
- saveText = oldsaveTest;
- treeVariableMap = saveMap;
- }
- /** Generate all the bitsets to be used in the parser or lexer
- * Generate the raw bitset data like "long _tokenSet1_data[] = {...}"
- * and the BitSet object declarations like "BitSet _tokenSet1 = new BitSet(_tokenSet1_data)"
- * Note that most languages do not support object initialization inside a
- * class definition, so other code-generators may have to separate the
- * bitset declarations from the initializations (e.g., put the initializations
- * in the generated constructor instead).
- * @param bitsetList The list of bitsets to generate.
- * @param maxVocabulary Ensure that each generated bitset can contain at least this value.
- */
- protected void genBitsets(Vector bitsetList,
- int maxVocabulary
- ) {
- println("");
- for (int i = 0; i < bitsetList.size(); i++) {
- BitSet p = (BitSet)bitsetList.elementAt(i);
- // Ensure that generated BitSet is large enough for vocabulary
- p.growToInclude(maxVocabulary);
- genBitSet(p, i);
- }
- }
- /** Do something simple like:
- * private static final long[] mk_tokenSet_0() {
- * long[] data = { -2305839160922996736L, 63L, 16777216L, 0L, 0L, 0L };
- * return data;
- * }
- * public static final BitSet _tokenSet_0 = new BitSet(mk_tokenSet_0());
- *
- * Or, for large bitsets, optimize init so ranges are collapsed into loops.
- * This is most useful for lexers using unicode.
- */
- private void genBitSet(BitSet p, int id) {
- int _tabs_ = tabs;
- // wanna have bitsets on module scope, so they are available
- // when module gets loaded.
- tabs = 0;
- println("");
- println("### generate bit set");
- println(
- "def mk" + getBitsetName(id) + "(): " );
- tabs++;
- int n = p.lengthInLongWords();
- if ( n<BITSET_OPTIMIZE_INIT_THRESHOLD )
- {
- println("### var1");
- println("data = [ " + p.toStringOfWords() + "]");
- }
- else
- {
- // will init manually, allocate space then set values
- println("data = [0L] * " + n + " ### init list");
- long[] elems = p.toPackedArray();
- for (int i = 0; i < elems.length;)
- {
- if ( elems[i]==0 )
- {
- // done automatically by Java, don't waste time/code
- i++;
- continue;
- }
- if ( (i+1)==elems.length || elems[i]!=elems[i+1] )
- {
- // last number or no run of numbers, just dump assignment
- println("data["+ i + "] =" + elems[i] + "L");
- i++;
- continue;
- }
- // scan to find end of run
- int j;
- for (j = i + 1;j < elems.length && elems[j]==elems[i];j++)
- {}
- long e = elems[i];
- // E0007: fixed
- println("for x in xrange(" + i+", " + j + "):");
- tabs++;
- println("data[x] = " + e + "L");
- tabs--;
- i = j;
- }
- }
- println("return data");
- tabs--;
- // BitSet object
- println(
- getBitsetName(id) + " = antlr.BitSet(mk" + getBitsetName(id) + "())" );
- // restore tabs
- tabs = _tabs_;
- }
- private void genBlockFinish(PythonBlockFinishingInfo howToFinish,
- String noViableAction) {
- if (howToFinish.needAnErrorClause &&
- (howToFinish.generatedAnIf || howToFinish.generatedSwitch)) {
- if (howToFinish.generatedAnIf)
- {
- println("else:" );
- }
- tabs++;
- println(noViableAction);
- tabs--;
- }
- if (howToFinish.postscript != null) {
- println(howToFinish.postscript);
- }
- }
- /* just to be called by nextToken */
- private void genBlockFinish1(PythonBlockFinishingInfo howToFinish,
- String noViableAction) {
- if (howToFinish.needAnErrorClause &&
- (howToFinish.generatedAnIf || howToFinish.generatedSwitch))
- {
- if (howToFinish.generatedAnIf)
- {
- // tabs++;
- println("else:" );
- }
- tabs++;
- println(noViableAction);
- tabs--;
- if (howToFinish.generatedAnIf)
- {
- // tabs--;
- // println("### tabs--");
- }
- }
- if (howToFinish.postscript != null) {
- println(howToFinish.postscript);
- }
- }
- /** Generate the init action for a block, which may be a RuleBlock or a
- * plain AlternativeBLock.
- * @blk The block for which the preamble is to be generated.
- */
- protected void genBlockInitAction(AlternativeBlock blk) {
- // dump out init action
- if (blk.initAction != null) {
- printAction(processActionForSpecialSymbols(blk.initAction, blk.getLine(), currentRule, null));
- }
- }
- /** Generate the header for a block, which may be a RuleBlock or a
- * plain AlternativeBLock. This generates any variable declarations
- * and syntactic-predicate-testing variables.
- * @blk The block for which the preamble is to be generated.
- */
- protected void genBlockPreamble(AlternativeBlock blk) {
- // define labels for rule blocks.
- if (blk instanceof RuleBlock) {
- RuleBlock rblk = (RuleBlock)blk;
- if (rblk.labeledElements != null) {
- for (int i = 0; i < rblk.labeledElements.size(); i++) {
- AlternativeElement a = (AlternativeElement)rblk.labeledElements.elementAt(i);
- // System.out.println("looking at labeled element: "+a);
- // Variables for labeled rule refs and
- // subrules are different than variables for
- // grammar atoms. This test is a little tricky
- // because we want to get all rule refs and ebnf,
- // but not rule blocks or syntactic predicates
- if (
- a instanceof RuleRefElement ||
- a instanceof AlternativeBlock &&
- !(a instanceof RuleBlock) &&
- !(a instanceof SynPredBlock)
- ) {
- if (
- !(a instanceof RuleRefElement) &&
- ((AlternativeBlock)a).not &&
- analyzer.subruleCanBeInverted(((AlternativeBlock)a), grammar instanceof LexerGrammar)
- ) {
- // Special case for inverted subrules that
- // will be inlined. Treat these like
- // token or char literal references
- println(a.getLabel() + " = " + labeledElementInit);
- if (grammar.buildAST) {
- genASTDeclaration(a);
- }
- }
- else {
- if (grammar.buildAST) {
- // Always gen AST variables for
- // labeled elements, even if the
- // element itself is marked with !
- genASTDeclaration(a);
- }
- if (grammar instanceof LexerGrammar) {
- println(a.getLabel() + " = None");
- }
- if (grammar instanceof TreeWalkerGrammar) {
- // always generate rule-ref variables
- // for tree walker
- println(a.getLabel() + " = " + labeledElementInit);
- }
- }
- }
- else {
- // It is a token or literal reference. Generate the
- // correct variable type for this grammar
- println(a.getLabel() + " = " + labeledElementInit);
- // In addition, generate *_AST variables if
- // building ASTs
- if (grammar.buildAST) {
- if (a instanceof GrammarAtom &&
- ((GrammarAtom)a).getASTNodeType() != null) {
- GrammarAtom ga = (GrammarAtom)a;
- genASTDeclaration(a, ga.getASTNodeType());
- }
- else {
- genASTDeclaration(a);
- }
- }
- }
- }
- }
- }
- }
- /** Generate a series of case statements that implement a BitSet test.
- * @param p The Bitset for which cases are to be generated
- */
- protected void genCases(BitSet p) {
- if (DEBUG_CODE_GENERATOR) System.out.println("genCases(" + p + ")");
- int[] elems;
- elems = p.toArray();
- // Wrap cases four-per-line for lexer, one-per-line for parser
- int wrap = (grammar instanceof LexerGrammar) ? 4 : 1;
- int j = 1;
- boolean startOfLine = true;
- print("elif la1 and la1 in ");
-
- if (grammar instanceof LexerGrammar)
- {
- _print("u'");
- for (int i = 0; i < elems.length; i++) {
- _print(getValueString(elems[i],false));
- }
- _print("':\n");
- return;
- }
- // Parser or TreeParser ..
- _print("[");
- for (int i = 0; i < elems.length; i++) {
- _print(getValueString(elems[i],false));
- if(i+1<elems.length)
- _print(",");
- }
- _print("]:\n");
- }
- /**Generate common code for a block of alternatives; return a
- * postscript that needs to be generated at the end of the
- * block. Other routines may append else-clauses and such for
- * error checking before the postfix is generated. If the
- * grammar is a lexer, then generate alternatives in an order
- * where alternatives requiring deeper lookahead are generated
- * first, and EOF in the lookahead set reduces the depth of
- * the lookahead. @param blk The block to generate @param
- * noTestForSingle If true, then it does not generate a test
- * for a single alternative.
- */
- public PythonBlockFinishingInfo genCommonBlock(AlternativeBlock blk,
- boolean noTestForSingle) {
- int _tabs_ = tabs; // remember where we are ..
- int nIF = 0;
- boolean createdLL1Switch = false;
- int closingBracesOfIFSequence = 0;
- PythonBlockFinishingInfo finishingInfo =
- new PythonBlockFinishingInfo();
- // Save the AST generation state, and set it to that of the block
- boolean savegenAST = genAST;
- genAST = genAST && blk.getAutoGen();
- boolean oldsaveTest = saveText;
- saveText = saveText && blk.getAutoGen();
- // Is this block inverted? If so, generate special-case code
- if (
- blk.not &&
- analyzer.subruleCanBeInverted(blk, grammar instanceof LexerGrammar)
- )
- {
- if (DEBUG_CODE_GENERATOR) System.out.println("special case: ~(subrule)");
- Lookahead p = analyzer.look(1, blk);
- // Variable assignment for labeled elements
- if (blk.getLabel() != null && syntacticPredLevel == 0)
- {
- println(blk.getLabel() + " = " + lt1Value);
- }
- // AST
- genElementAST(blk);
- String astArgs = "";
- if (grammar instanceof TreeWalkerGrammar) {
- astArgs = "_t, ";
- }
- // match the bitset for the alternative
- println("self.match(" + astArgs + getBitsetName(markBitsetForGen(p.fset)) + ")");
- // tack on tree cursor motion if doing a tree walker
- if (grammar instanceof TreeWalkerGrammar) {
- println("_t = _t.getNextSibling()");
- }
- return finishingInfo;
- }
- // Special handling for single alt
- if (blk.getAlternatives().size() == 1)
- {
- Alternative alt = blk.getAlternativeAt(0);
- // Generate a warning if there is a synPred for single alt.
- if (alt.synPred != null) {
- antlrTool.warning(
- "Syntactic predicate superfluous for single alternative",
- grammar.getFilename(),
- blk.getAlternativeAt(0).synPred.getLine(),
- blk.getAlternativeAt(0).synPred.getColumn()
- );
- }
- if (noTestForSingle)
- {
- if (alt.semPred != null) {
- // Generate validating predicate
- genSemPred(alt.semPred, blk.line);
- }
- genAlt(alt, blk);
- return finishingInfo;
- }
- }
- // count number of simple LL(1) cases; only do switch …
Large files files are truncated, but you can click here to view the full file