Logo Search packages:      
Sourcecode: antlr version File versions

CppBlockFinishingInfo antlr::CppCodeGenerator::genCommonBlock ( AlternativeBlock  blk,
boolean  noTestForSingle 
) [inline]

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.

Parameters:
blk The block to generate
noTestForSingle If true, then it does not generate a test for a single alternative.

Definition at line 1724 of file CppCodeGenerator.java.

References addSemPred(), antlr::AlternativeBlock::alternatives, antlr::CodeGenerator::analyzer, antlr::Alternative::cache, antlr::CodeGenerator::charFormatter, antlr::Lookahead::containsEpsilon(), antlr::CodeGenerator::DEBUG_CODE_GENERATOR, antlr::collections::impl::BitSet::degree(), antlr::CharFormatter::escapeString(), antlr::Lookahead::fset, genAlt(), genCases(), genElementAST(), antlr::AlternativeBlock::getAlternativeAt(), antlr::AlternativeBlock::getAlternatives(), antlr::AlternativeBlock::getAutoGen(), antlr::CodeGenerator::getBitsetName(), antlr::AlternativeBlock::getLabel(), antlr::Alternative::head, antlr::GrammarElement::line, antlr::Alternative::lookaheadDepth, lookaheadIsEmpty(), antlr::CodeGenerator::makeSwitchThreshold, antlr::CodeGenerator::markBitsetForGen(), antlr::AlternativeBlock::not, println(), processActionForSpecialSymbols(), antlr::Alternative::semPred, and antlr::Alternative::synPred.

Referenced by gen(), genNextToken(), and genRule().

      {
            int nIF=0;
            boolean createdLL1Switch = false;
            int closingBracesOfIFSequence = 0;
            CppBlockFinishingInfo finishingInfo = new CppBlockFinishingInfo();
            if ( DEBUG_CODE_GENERATOR ) System.out.println("genCommonBlk("+blk+")");

            // 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) )
            {
                  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) {
                        if( usingCustomAST )
                              astArgs="static_cast<"+namespaceAntlr+"RefAST"+">(_t),";
                        else
                              astArgs="_t,";
                  }

                  // match the bitset for the alternative
                  println("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 for
            // many LL(1) cases (no preds, no end of token refs)
            // We don't care about exit paths for (...)*, (...)+
            // because we don't explicitly have a test for them
            // as an alt in the loop.
            //
            // Also, we now count how many unicode lookahead sets
            // there are--they must be moved to DEFAULT or ELSE
            // clause.

            int nLL1 = 0;
            for (int i=0; i<blk.getAlternatives().size(); i++)
            {
                  Alternative a = blk.getAlternativeAt(i);
                  if ( suitableForCaseExpression(a) )
                        nLL1++;
            }

            // do LL(1) cases
            if ( nLL1 >= makeSwitchThreshold )
            {
                  // Determine the name of the item to be compared
                  String testExpr = lookaheadString(1);
                  createdLL1Switch = true;
                  // when parsing trees, convert null to valid tree node with NULL lookahead
                  if ( grammar instanceof TreeWalkerGrammar )
                  {
                        println("if (_t == "+labeledElementASTInit+" )");
                        tabs++;
                        println("_t = ASTNULL;");
                        tabs--;
                  }
                  println("switch ( "+testExpr+") {");
                  for (int i=0; i<blk.alternatives.size(); i++)
                  {
                        Alternative alt = blk.getAlternativeAt(i);
                        // ignore any non-LL(1) alts, predicated alts or end-of-token alts
                        // or end-of-token alts for case expressions
                        if ( !suitableForCaseExpression(alt) )
                        {
                              continue;
                        }
                        Lookahead p = alt.cache[1];
                        if (p.fset.degree() == 0 && !p.containsEpsilon())
                        {
                              antlrTool.warning("Alternate omitted due to empty prediction set",
                                    grammar.getFilename(),
                                    alt.head.getLine(), alt.head.getColumn());
                        }
                        else
                        {
                              genCases(p.fset);
                              println("{");
                              tabs++;
                              genAlt(alt, blk);
                              println("break;");
                              tabs--;
                              println("}");
                        }
                  }
                  println("default:");
                  tabs++;
            }

            // do non-LL(1) and nondeterministic cases
            // This is tricky in the lexer, because of cases like:
            //     STAR : '*' ;
            //     ASSIGN_STAR : "*=";
            // Since nextToken is generated without a loop, then the STAR will
            // have end-of-token as it's lookahead set for LA(2).  So, we must generate the
            // alternatives containing trailing end-of-token in their lookahead sets *after*
            // the alternatives without end-of-token.  This implements the usual
            // lexer convention that longer matches come before shorter ones, e.g.
            // "*=" matches ASSIGN_STAR not STAR
            //
            // For non-lexer grammars, this does not sort the alternates by depth
            // Note that alts whose lookahead is purely end-of-token at k=1 end up
            // as default or else clauses.
            int startDepth = (grammar instanceof LexerGrammar) ? grammar.maxk : 0;
            for (int altDepth = startDepth; altDepth >= 0; altDepth--) {
                  if ( DEBUG_CODE_GENERATOR ) System.out.println("checking depth "+altDepth);
                  for (int i=0; i<blk.alternatives.size(); i++) {
                        Alternative alt = blk.getAlternativeAt(i);
                        if ( DEBUG_CODE_GENERATOR ) System.out.println("genAlt: "+i);
                        // if we made a switch above, ignore what we already took care
                        // of.  Specifically, LL(1) alts with no preds
                        // that do not have end-of-token in their prediction set
                        if ( createdLL1Switch &&
                               suitableForCaseExpression(alt) )
                        {
                              if ( DEBUG_CODE_GENERATOR )
                                    System.out.println("ignoring alt because it was in the switch");
                              continue;
                        }
                        String e;

                        boolean unpredicted = false;

                        if (grammar instanceof LexerGrammar) {
                              // Calculate the "effective depth" of the alt, which is the max
                              // depth at which cache[depth]!=end-of-token
                              int effectiveDepth = alt.lookaheadDepth;
                              if (effectiveDepth == GrammarAnalyzer.NONDETERMINISTIC)
                              {
                                    // use maximum lookahead
                                    effectiveDepth = grammar.maxk;
                              }
                              while ( effectiveDepth >= 1 &&
                                           alt.cache[effectiveDepth].containsEpsilon() )
                              {
                                    effectiveDepth--;
                              }
                              // Ignore alts whose effective depth is other than the ones we
                              // are generating for this iteration.
                              if (effectiveDepth != altDepth)
                              {
                                    if ( DEBUG_CODE_GENERATOR )
                                          System.out.println("ignoring alt because effectiveDepth!=altDepth;"+effectiveDepth+"!="+altDepth);
                                    continue;
                              }
                              unpredicted = lookaheadIsEmpty(alt, effectiveDepth);
                              e = getLookaheadTestExpression(alt, effectiveDepth);
                        }
                        else
                        {
                              unpredicted = lookaheadIsEmpty(alt, grammar.maxk);
                              e = getLookaheadTestExpression(alt, grammar.maxk);
                        }

                        // Was it a big unicode range that forced unsuitability
                        // for a case expression?
                        if ( alt.cache[1].fset.degree() > caseSizeThreshold &&
                                suitableForCaseExpression(alt))
                        {
                              if ( nIF==0 )
                              {
                                    // generate this only for the first if the elseif's
                                    // are covered by this one
                                    if ( grammar instanceof TreeWalkerGrammar ) {
                                          println("if (_t == "+labeledElementASTInit+" )");
                                          tabs++;
                                          println("_t = ASTNULL;");
                                          tabs--;
                                    }
                                    println("if " + e + " {");
                              }
                              else
                                    println("else if " + e + " {");
                        }
                        else if (unpredicted &&
                                          alt.semPred==null &&
                                          alt.synPred==null)
                        {
                              // The alt has empty prediction set and no
                              // predicate to help out.  if we have not
                              // generated a previous if, just put {...} around
                              // the end-of-token clause
                              if ( nIF==0 ) {
                                    println("{");
                              }
                              else {
                                    println("else {");
                              }
                              finishingInfo.needAnErrorClause = false;
                        }
                        else
                        {
                              // check for sem and syn preds
                              // Add any semantic predicate expression to the lookahead test
                              if ( alt.semPred != null ) {
                                    // if debugging, wrap the evaluation of the predicate in a method
                                    //
                                    // translate $ and # references
                                    ActionTransInfo tInfo = new ActionTransInfo();
                                    String actionStr = processActionForSpecialSymbols(alt.semPred,
                                                                                                              blk.line,
                                                                                                              currentRule,
                                                                                                              tInfo);
                                    // ignore translation info...we don't need to do anything with it.

                                    // call that will inform SemanticPredicateListeners of the result
                                    if (((grammar instanceof ParserGrammar) || (grammar instanceof LexerGrammar)) && grammar.debuggingOutput)
                                          e = "("+e+"&& fireSemanticPredicateEvaluated(antlr.debug.SemanticPredicateEvent.PREDICTING,"+ //FIXME
                                                      addSemPred(charFormatter.escapeString(actionStr))+","+actionStr+"))";
                                    else
                                          e = "("+e+"&&("+actionStr +"))";
                              }

                              // Generate any syntactic predicates
                              if ( nIF>0 ) {
                                    if ( alt.synPred != null ) {
                                          println("else {");
                                          tabs++;
                                          genSynPred( alt.synPred, e );
                                          closingBracesOfIFSequence++;
                                    }
                                    else {
                                          println("else if " + e + " {");
                                    }
                              }
                              else {
                                    if ( alt.synPred != null ) {
                                          genSynPred( alt.synPred, e );
                                    }
                                    else {
                                          // when parsing trees, convert null to valid tree node
                                          // with NULL lookahead.
                                          if ( grammar instanceof TreeWalkerGrammar ) {
                                                println("if (_t == "+labeledElementASTInit+" )");
                                                tabs++;
                                                println("_t = ASTNULL;");
                                                tabs--;
                                          }
                                          println("if " + e + " {");
                                    }
                              }

                        }

                        nIF++;
                        tabs++;
                        genAlt(alt, blk);
                        tabs--;
                        println("}");
                  }
            }
            String ps = "";
            for (int i=1; i<=closingBracesOfIFSequence; i++) {
                  tabs--; // does JavaCodeGenerator need this?
                  ps+="}";
            }

            // Restore the AST generation state
            genAST = savegenAST;

            // restore save text state
            saveText=oldsaveTest;

            // Return the finishing info.
            if ( createdLL1Switch ) {
                  tabs--;
                  finishingInfo.postscript = ps+"}";
                  finishingInfo.generatedSwitch = true;
                  finishingInfo.generatedAnIf = nIF>0;
                  //return new CppBlockFinishingInfo(ps+"}",true,nIF>0); // close up switch statement

            }
            else {
                  finishingInfo.postscript = ps;
                  finishingInfo.generatedSwitch = false;
                  finishingInfo.generatedAnIf = nIF>0;
                  //return new CppBlockFinishingInfo(ps, false,nIF>0);
            }
            return finishingInfo;
      }


Generated by  Doxygen 1.6.0   Back to index