Logo Search packages:      
Sourcecode: antlr version File versions

void antlr::CSharpCodeGenerator::genRule ( RuleSymbol  s,
boolean  startSymbol,
int  ruleNum,
TokenManager  tm 
) [inline]

Gen a named rule block. ASTs are generated for each element of an alternative unless the rule or the alternative have a '!' modifier.

If an alternative defeats the default tree construction, it must set <rule>_AST to the root of the returned AST.

Each alternative that does automatic tree construction, builds up root and child list pointers in an ASTPair structure.

A rule finishes by setting the returnAST variable from the ASTPair.

Parameters:
rule The name of the rule to generate
startSymbol true if the rule is a start symbol (i.e., not referenced elsewhere)

Definition at line 2746 of file CSharpCodeGenerator.java.

References antlr::CodeGenerator::_print(), antlr::CodeGenerator::_println(), antlr::AlternativeBlock::alternatives, antlr::RuleBlock::argAction, antlr::CodeGenerator::DEBUG_CODE_GENERATOR, declaredASTVariables, antlr::RuleBlock::endNode, antlr::CodeGenerator::extractIdOfAction(), antlr::CodeGenerator::extractTypeOfAction(), antlr::RuleBlock::findExceptionSpec(), antlr::Lookahead::fset, genAlt(), genBlockFinish(), genBlockInitAction(), genBlockPreamble(), genCommonBlock(), genErrorHandler(), antlr::AlternativeBlock::getAlternativeAt(), antlr::AlternativeBlock::getAutoGen(), getBitsetName(), antlr::GrammarElement::getColumn(), antlr::RuleBlock::getDefaultErrorHandler(), antlr::GrammarElement::getLine(), antlr::RuleBlock::getTestLiterals(), antlr::GrammarElement::line, antlr::CodeGenerator::markBitsetForGen(), antlr::CodeGenerator::print(), antlr::CodeGenerator::println(), antlr::RuleBlock::returnAction, antlr::RuleBlock::ruleName, antlr::Alternative::semPred, antlr::Alternative::synPred, and antlr::RuleBlock::throwsSpec.

                                                                                           {
            tabs=1;
            if ( DEBUG_CODE_GENERATOR ) System.out.println("genRule("+ s.getId() +")");
            if ( !s.isDefined() ) {
                  antlrTool.error("undefined rule: "+ s.getId());
                  return;
            }

            // Generate rule return type, name, arguments
            RuleBlock rblk = s.getBlock();
            currentRule = rblk;
            currentASTResult = s.getId();

      // clear list of declared ast variables..
      declaredASTVariables.clear();

            // Save the AST generation state, and set it to that of the rule
            boolean savegenAST = genAST;
            genAST = genAST && rblk.getAutoGen();

            // boolean oldsaveTest = saveText;
            saveText = rblk.getAutoGen();

            // print javadoc comment if any
            if ( s.comment!=null ) {
                  _println(s.comment);
            }

            // Gen method access and final qualifier
            //print(s.access + " final ");
            print(s.access + " ");

            // Gen method return type (note lexer return action set at rule creation)
            if (rblk.returnAction != null)
            {
                  // Has specified return value
                  _print(extractTypeOfAction(rblk.returnAction, rblk.getLine(), rblk.getColumn()) + " ");
            } else {
                  // No specified return value
                  _print("void ");
            }

            // Gen method name
            _print(s.getId() + "(");

            // Additional rule parameters common to all rules for this grammar
            _print(commonExtraParams);
            if (commonExtraParams.length() != 0 && rblk.argAction != null ) {
                  _print(",");
            }

            // Gen arguments
            if (rblk.argAction != null)
            {
                  // Has specified arguments
                  _println("");
                  tabs++;
                  println(rblk.argAction);
                  tabs--;
                  print(")");
            }
            else {
                  // No specified arguments
                  _print(")");
            }

            // Gen throws clause and open curly
            _print(" //throws " + exceptionThrown);
            if ( grammar instanceof ParserGrammar ) {
                  _print(", TokenStreamException");
            }
            else if ( grammar instanceof LexerGrammar ) {
                  _print(", CharStreamException, TokenStreamException");
            }
            // Add user-defined exceptions unless lexer (for now)
            if ( rblk.throwsSpec!=null ) {
                  if ( grammar instanceof LexerGrammar ) {
                        antlrTool.error("user-defined throws spec not allowed (yet) for lexer rule "+rblk.ruleName);
                  }
                  else {
                        _print(", "+rblk.throwsSpec);
                  }
            }

            _println("");
            _println("{");
            tabs++;

            // Convert return action to variable declaration
            if (rblk.returnAction != null)
                  println(rblk.returnAction + ";");

            // print out definitions needed by rules for various grammar types
            println(commonLocalVars);

            if (grammar.traceRules) {
                  if ( grammar instanceof TreeWalkerGrammar ) {
                        if ( usingCustomAST )
                              println("traceIn(\""+ s.getId() +"\",(AST)_t);");
                        else
                              println("traceIn(\""+ s.getId() +"\",_t);");
                  }
                  else {
                        println("traceIn(\""+ s.getId() +"\");");
                  }
            }

            if ( grammar instanceof LexerGrammar ) {
                  // lexer rule default return value is the rule's token name
                  // This is a horrible hack to support the built-in EOF lexer rule.
                  if (s.getId().equals("mEOF"))
                        println("_ttype = Token.EOF_TYPE;");
                  else
                        println("_ttype = " + s.getId().substring(1)+";");

                  // delay creation of _saveIndex until we need it OK?
                  bSaveIndexCreated = false;

                  /*
                        println("boolean old_saveConsumedInput=saveConsumedInput;");
                        if ( !rblk.getAutoGen() ) {         // turn off "save input" if ! on rule
                        println("saveConsumedInput=false;");
                        }
                      */
            }

            // if debugging, write code to mark entry to the rule
            if ( grammar.debuggingOutput)
                  if (grammar instanceof ParserGrammar)
                        println("fireEnterRule(" + ruleNum + ",0);");
                  else if (grammar instanceof LexerGrammar)
                  println("fireEnterRule(" + ruleNum + ",_ttype);");


            // Generate trace code if desired
            if ( grammar.debuggingOutput || grammar.traceRules) {
                  println("try { // debugging");
                  tabs++;
            }

            // Initialize AST variables
            if (grammar instanceof TreeWalkerGrammar) {
                  // "Input" value for rule
                  println(labeledElementASTType+" " + s.getId() + "_AST_in = ("+labeledElementASTType+")_t;");
            }
            if (grammar.buildAST) {
                  // Parser member used to pass AST returns from rule invocations
                  println("returnAST = null;");
                  // Tracks AST construction
                  // println("ASTPair currentAST = (inputState.guessing==0) ? new ASTPair() : null;");
                  println("ASTPair currentAST = new ASTPair();");
                  // User-settable return value for rule.
                  println(labeledElementASTType+" " + s.getId() + "_AST = null;");
            }

            genBlockPreamble(rblk);
            genBlockInitAction(rblk);
            println("");

            // Search for an unlabeled exception specification attached to the rule
            ExceptionSpec unlabeledUserSpec = rblk.findExceptionSpec("");

            // Generate try block around the entire rule for  error handling
            if (unlabeledUserSpec != null || rblk.getDefaultErrorHandler() ) {
                  println("try {      // for error handling");
                  tabs++;
            }

            // Generate the alternatives
            if ( rblk.alternatives.size()==1 )
            {
                  // One alternative -- use simple form
                  Alternative alt = rblk.getAlternativeAt(0);
                  String pred = alt.semPred;
                  if ( pred!=null )
                        genSemPred(pred, currentRule.line);
                  if (alt.synPred != null) {
                        antlrTool.warning(
                              "Syntactic predicate ignored for single alternative",
                              grammar.getFilename(), alt.synPred.getLine(), alt.synPred.getColumn()
                              );
                  }
                  genAlt(alt, rblk);
            }
            else
            {
                  // Multiple alternatives -- generate complex form
                  boolean ok = grammar.theLLkAnalyzer.deterministic(rblk);

                  CSharpBlockFinishingInfo howToFinish = genCommonBlock(rblk, false);
                  genBlockFinish(howToFinish, throwNoViable);
            }

            // Generate catch phrase for error handling
            if (unlabeledUserSpec != null || rblk.getDefaultErrorHandler() ) {
                  // Close the try block
                  tabs--;
                  println("}");
            }

            // Generate user-defined or default catch phrases
            if (unlabeledUserSpec != null)
            {
                  genErrorHandler(unlabeledUserSpec);
            }
            else if (rblk.getDefaultErrorHandler())
            {
                  // Generate default catch phrase
                  println("catch (" + exceptionThrown + " ex)");
                  println("{");
                  tabs++;
                  // Generate code to handle error if not guessing
                  if (grammar.hasSyntacticPredicate) {
                        println("if (0 == inputState.guessing)");
                        println("{");
                        tabs++;
                  }
                  println("reportError(ex);");
                  if ( !(grammar instanceof TreeWalkerGrammar) )
                  {
                        // Generate code to consume until token in k==1 follow set
                        Lookahead follow = grammar.theLLkAnalyzer.FOLLOW(1, rblk.endNode);
                        String followSetName = getBitsetName(markBitsetForGen(follow.fset));
                        println("consume();");
                        println("consumeUntil(" + followSetName + ");");
                  }
                  else
                  {
                        // Just consume one token
                  println("if (null != _t)");
                  println("{");
                  tabs++;
                  println("_t = _t.getNextSibling();");
                  tabs--;
                  println("}");
                  }
                  if (grammar.hasSyntacticPredicate)
                  {
                        tabs--;
                        // When guessing, rethrow exception
                        println("}");
                        println("else");
                        println("{");
                        tabs++;
                        //println("throw ex;");
                        println("throw;");
                        tabs--;
                        println("}");
                  }
                  // Close catch phrase
                  tabs--;
                  println("}");
            }

            // Squirrel away the AST "return" value
            if (grammar.buildAST) {
                  println("returnAST = " + s.getId() + "_AST;");
            }

            // Set return tree value for tree walkers
            if ( grammar instanceof TreeWalkerGrammar ) {
                  println("retTree_ = _t;");
            }

            // Generate literals test for lexer rules so marked
            if (rblk.getTestLiterals()) {
                  if ( s.access.equals("protected") ) {
                        genLiteralsTestForPartialToken();
                  }
                  else {
                        genLiteralsTest();
                  }
            }

            // if doing a lexer rule, dump code to create token if necessary
            if ( grammar instanceof LexerGrammar ) {
                  println("if (_createToken && (null == _token) && (_ttype != Token.SKIP))");
                  println("{");
                  tabs++;
                  println("_token = makeToken(_ttype);");
                  println("_token.setText(text.ToString(_begin, text.Length-_begin));");
                  tabs--;
                  println("}");
                  println("returnToken_ = _token;");
            }

            // Gen the return statement if there is one (lexer has hard-wired return action)
            if (rblk.returnAction != null) {
                  println("return " + extractIdOfAction(rblk.returnAction, rblk.getLine(), rblk.getColumn()) + ";");
            }

            if ( grammar.debuggingOutput || grammar.traceRules) {
                  tabs--;
                  println("}");
                  println("finally");
                  println("{ // debugging");
                  tabs++;

                  // If debugging, generate calls to mark exit of rule
                  if ( grammar.debuggingOutput)
                        if (grammar instanceof ParserGrammar)
                              println("fireExitRule(" + ruleNum + ",0);");
                        else if (grammar instanceof LexerGrammar)
                        println("fireExitRule(" + ruleNum + ",_ttype);");

                  if (grammar.traceRules) {
                        if ( grammar instanceof TreeWalkerGrammar ) {
                              println("traceOut(\""+ s.getId() +"\",_t);");
                        }
                        else {
                              println("traceOut(\""+ s.getId() +"\");");
                        }
                  }

                  tabs--;
                  println("}");
            }

            tabs--;
            println("}");
            println("");

            // Restore the AST generation state
            genAST = savegenAST;

            // restore char save state
            // saveText = oldsaveTest;
      }


Generated by  Doxygen 1.6.0   Back to index