Logo Search packages:      
Sourcecode: antlr version File versions

void antlr::CppCodeGenerator::genRule ( RuleSymbol  s,
boolean  startSymbol,
int  ruleNum,
String  prefix 
) [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 3171 of file CppCodeGenerator.java.

References _print(), _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(), genLineNo(), genLineNo2(), antlr::AlternativeBlock::getAlternativeAt(), antlr::AlternativeBlock::getAutoGen(), antlr::CodeGenerator::getBitsetName(), antlr::GrammarElement::getColumn(), antlr::RuleBlock::getDefaultErrorHandler(), antlr::GrammarElement::getLine(), antlr::RuleBlock::getTestLiterals(), antlr::GrammarElement::line, antlr::CodeGenerator::markBitsetForGen(), antlr::CodeGenerator::print(), println(), antlr::RuleBlock::returnAction, antlr::Alternative::semPred, and antlr::Alternative::synPred.

                                                                                         {
//          tabs=1; // JavaCodeGenerator needs this
            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 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(prefix + 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("");
// FIXME: make argAction also a token? Hmmmmm
//                genLineNo(rblk);
                  tabs++;
                  println(rblk.argAction);
                  tabs--;
                  print(") ");
//                genLineNo2();     // gcc gives error on the brace... hope it works for the others too
            } else {
                  // No specified arguments
                  _print(") ");
            }

            // Gen throws clause and open curly
//          _print(" throws " + exceptionThrown);
//          if ( !(grammar instanceof TreeWalkerGrammar) ) {
//                _print(", IOException");
//          }
            _println("{");
            tabs++;

            if (grammar.traceRules) {
                  if ( grammar instanceof TreeWalkerGrammar ) {
                        if ( usingCustomAST )
                              println("Tracer traceInOut(this,\""+ s.getId() +"\",static_cast<"+namespaceAntlr+"RefAST"+">(_t));");
                        else
                              println("Tracer traceInOut(this,\""+ s.getId() +"\",_t);");
                  }
                  else {
                        println("Tracer traceInOut(this, \""+ s.getId() +"\");");
                  }
            }

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

            // print out definitions needed by rules for various grammar types
            if (!commonLocalVars.equals(""))
                  println(commonLocalVars);

            if ( grammar instanceof LexerGrammar ) {
                  // RK: why is this here? It seems not supported in the rest of the
                  // tool.
                  // 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 = "+namespaceAntlr+"Token::EOF_TYPE;");
                  else
                        println("_ttype = "+ s.getId().substring(1)+";");
                  println("int _saveIndex;");         // used for element! (so we can kill text matched for element)
/*
                  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);");
                  println(labeledElementASTType+" " + s.getId() + "_AST_in = _t;");
            }
            if (grammar.buildAST) {
                  // Parser member used to pass AST returns from rule invocations
                  println("returnAST = "+labeledElementASTInit+";");
                  // Tracks AST construction
                  println(namespaceAntlr+"ASTPair currentAST;"); // = new ASTPair();");
                  // User-settable return value for rule.
                  println(labeledElementASTType+" " + s.getId() + "_AST = "+labeledElementASTInit+";");
            }

            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);

                  CppBlockFinishingInfo 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) {");
                  tabs++;
                  // Generate code to handle error if not guessing
                  if (grammar.hasSyntacticPredicate) {
                        println("if( inputState->guessing == 0 ) {");
                        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 ( _t != "+labeledElementASTInit+" )");
                        tabs++;
                        println("_t = _t->getNextSibling();");
                        tabs--;
                  }
                  if (grammar.hasSyntacticPredicate)
                  {
                        tabs--;
                        // When guessing, rethrow exception
                        println("} else {");
                        tabs++;
                        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 && _token=="+namespaceAntlr+"nullToken && _ttype!="+namespaceAntlr+"Token::SKIP ) {");
                  println("   _token = makeToken(_ttype);");
                  println("   _token->setText(text.substr(_begin, text.length()-_begin));");
                  println("}");
                  println("_returnToken = _token;");
                  // It should be easy for an optimizing compiler to realize this does nothing
                  // but it avoids the warning about the variable being unused.
                  println("_saveIndex=0;");
            }

            // 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("} finally { // debugging");
////              tabs++;
//
//                // Generate trace code if desired
//                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