Example usage for org.antlr.v4.runtime ParserRuleContext getChildCount

List of usage examples for org.antlr.v4.runtime ParserRuleContext getChildCount

Introduction

In this page you can find the example usage for org.antlr.v4.runtime ParserRuleContext getChildCount.

Prototype

@Override
    public int getChildCount() 

Source Link

Usage

From source file:br.beholder.memelang.model.visitor.TreePrinterListener.java

@Override
public void enterEveryRule(ParserRuleContext ctx) {
    if (builder.length() > 0) {
        builder.append(' ');
    }//from  w  w w . ja v a2 s. c  o m

    if (ctx.getChildCount() > 0) {
        builder.append('(');
    }

    int ruleIndex = ctx.getRuleIndex();
    String ruleName;
    if (ruleIndex >= 0 && ruleIndex < ruleNames.size()) {
        ruleName = ruleNames.get(ruleIndex);
    } else {
        ruleName = Integer.toString(ruleIndex);
    }

    builder.append(ruleName);
}

From source file:br.beholder.memelang.model.visitor.TreePrinterListener.java

@Override
public void exitEveryRule(ParserRuleContext ctx) {
    if (ctx.getChildCount() > 0) {
        Token positionToken = ctx.getStart();
        if (positionToken != null) {
            builder.append(" [line ");
            builder.append(positionToken.getLine());
            builder.append(", offset ");
            builder.append(positionToken.getStartIndex());
            builder.append(':');
            builder.append(positionToken.getStopIndex());
            builder.append("])");
        } else {/*from  ww  w  .  j  a  v a  2  s .co  m*/
            builder.append(')');
        }
    }
}

From source file:com.bacoder.parser.java.adapter.JavaAdapter.java

License:Apache License

protected void setAnnotations(ParserRuleContext context, final NodeWithModifiers node) {
    List<Annotation> annotations = transform(context, ClassOrInterfaceModifierContext.class,
            new Function<ClassOrInterfaceModifierContext, Annotation>() {
                @Override//  w w w .  j  a  v  a2 s  . co  m
                public Annotation apply(ClassOrInterfaceModifierContext context) {
                    if (context.getChildCount() > 0 && context.getChild(0) instanceof AnnotationContext) {
                        AnnotationContext annotationContext = (AnnotationContext) context.getChild(0);
                        return getAdapter(AnnotationAdapter.class).adapt(annotationContext);
                    } else {
                        return null;
                    }
                }
            });
    node.setAnnotations(annotations);
}

From source file:com.bacoder.parser.java.adapter.JavaAdapter.java

License:Apache License

protected void setClassOrInterfaceModifiers(ParserRuleContext context, final NodeWithModifiers node) {
    setAnnotations(context, node);//w ww  . jav a2s .  co  m

    forEachChild(context, ClassOrInterfaceModifierContext.class,
            new Function<ClassOrInterfaceModifierContext, Void>() {
                @Override
                public Void apply(ClassOrInterfaceModifierContext context) {
                    if (context.getChildCount() > 0 && context.getChild(0) instanceof TerminalNode) {
                        TerminalNode child = (TerminalNode) context.getChild(0);
                        int type = child.getSymbol().getType();
                        switch (type) {
                        case JavaParser.PUBLIC:
                            node.setPublic(true);
                            break;
                        case JavaParser.PROTECTED:
                            node.setProtected(true);
                            break;
                        case JavaParser.PRIVATE:
                            node.setPrivate(true);
                            break;
                        case JavaParser.STATIC:
                            node.setStatic(true);
                            break;
                        case JavaParser.ABSTRACT:
                            node.setAbstract(true);
                            break;
                        case JavaParser.FINAL:
                            node.setFinal(true);
                            break;
                        case JavaParser.STRICTFP:
                            node.setStrictfp(true);
                            break;
                        default:
                        }
                    }
                    return null;
                }
            });
}

From source file:com.bacoder.parser.java.adapter.JavaAdapter.java

License:Apache License

protected void setModifiers(ParserRuleContext context, final NodeWithModifiers node) {
    setClassOrInterfaceModifiers(context, node);

    forEachChild(context, ModifierContext.class, new Function<ModifierContext, Void>() {
        @Override/*w ww .  j  av  a  2s.c  o m*/
        public Void apply(ModifierContext context) {
            if (context.getChildCount() > 0 && context.getChild(0) instanceof TerminalNode) {
                TerminalNode child = (TerminalNode) context.getChild(0);
                int type = child.getSymbol().getType();
                switch (type) {
                case JavaParser.NATIVE:
                    node.setNative(true);
                    break;
                case JavaParser.SYNCHRONIZED:
                    node.setSynchronized(true);
                    break;
                case JavaParser.TRANSIENT:
                    node.setTransient(true);
                    break;
                case JavaParser.VOLATILE:
                    node.setVolatile(true);
                    break;
                default:
                }
            }
            return null;
        }
    });
}

From source file:com.blazebit.persistence.parser.expression.JPQLSelectExpressionVisitorImpl.java

License:Apache License

public Expression visitMacroExpression(String macroName, ParserRuleContext ctx) {
    List<Expression> funcArgs = new ArrayList<Expression>(ctx.getChildCount());
    // Special handling of empty invocation, the position 2 contains an empty child node
    if (ctx.getChildCount() != 4 || !ctx.getChild(2).getText().isEmpty()) {
        for (int i = 0; i < ctx.getChildCount(); i++) {
            if (!(ctx.getChild(i) instanceof TerminalNode)) {
                funcArgs.add(ctx.getChild(i).accept(this));
            }/*from   w  ww . j av a 2 s  .  co  m*/
        }
    }

    MacroFunction macro = macros.get(macroName);
    if (macro == null) {
        throw new SyntaxErrorException("The macro '" + macroName + "' could not be found in the macro map!");
    }
    if (usedMacros != null) {
        usedMacros.add(macroName);
    }
    try {
        return macro.apply(funcArgs);
    } catch (RuntimeException ex) {
        throw new IllegalArgumentException("Could not apply the macro for the expression: " + ctx.getText(),
                ex);
    }
}

From source file:com.gigaspaces.persistency.parser.SQL2MongoBaseVisitor.java

License:Open Source License

private boolean IsLogic(ParserRuleContext ctx, String text) {

    for (int i = 0; i < ctx.getChildCount(); i++) {
        ParseTree c = ctx.getChild(i);/*  w ww .  j a v a  2  s .c om*/

        if (c.getText().equals(text))
            return true;
    }
    return false;
}

From source file:com.satisfyingstructures.J2S.J2SConvertBasicFor.java

License:Open Source License

private String convertBasicForStatementToForInLoopOrSayWhyNot(ParserRuleContext ctx) {
    int forRule = ctx.getRuleIndex();
    if (forRule != Java8Parser.RULE_basicForStatement && forRule != Java8Parser.RULE_basicForStatementNoShortIf)
        return "statement kind is not as expected"; // not our expected parameter type
    // Get to know more about our for statement
    // 'for' '(' forInit? ';' expression? ';' forUpdate? ')' ( statement | statementNoShortIf )
    Boolean noShortIf = forRule == Java8Parser.RULE_basicForStatementNoShortIf;
    Java8Parser.ForInitContext forInitCtx = ctx.getChild(Java8Parser.ForInitContext.class, 0);
    Java8Parser.ExpressionContext expressionCtx = ctx.getChild(Java8Parser.ExpressionContext.class, 0);
    Java8Parser.ForUpdateContext forUpdateCtx = ctx.getChild(Java8Parser.ForUpdateContext.class, 0);
    ParserRuleContext statementCtx = ctx.getChild(
            noShortIf ? Java8Parser.StatementNoShortIfContext.class : Java8Parser.StatementContext.class, 0);
    ParserRuleContext statementSubCtx = statementCtx.getChild(ParserRuleContext.class, 0);
    ParserRuleContext statementSubSubCtx = statementSubCtx.getChild(ParserRuleContext.class, 0);
    Boolean statementisEmpty = statementSubSubCtx.getRuleIndex() == Java8Parser.RULE_emptyStatement;
    /*/*from  w ww. j  av  a 2  s .  co  m*/
    'for' '(' forInit? ';' expression? ';' forUpdate? ')' ( statement | statementNoShortIf )
            
    Swift 3.0 has got rid of for(;;) statements for stong business cases such as...
        'It is rarely used'
        'not very Swift-like'
        'The value of this construct is limited'
    ...and other total crap.
            
    We can convert simple equivalents of
        for ( i = startvalue ; i < endvalue ; i += step)
    to
        for i in start..<end
    or
        for i in start.stride(to: end by: step)
            
    To identify this we look for
    1) have a forUpdate, which...
        a) operates on a single loop variable
            forUpdate().statementExpressionList().statementExpression().count()==1
        b) incorporates increment or decrement by a constant step (++i,i++,i+=step,--i,i--,i-=step,)
            statementExpression rule is RULE_(assignment|preinc|postinc|predec|postdec)
        c) operates on the same variable tested in expression (compare - 2b)
    2) have an expression, which...
        a) should be a simple comparison (<,<=,!=,>,>=, implicit non-zero)
        b) one side should be same as the loop var (compare - 1c)
        c) other side should not mutate within the loop - we can't tell this, too difficult
    3) forInit
        a) must be
            i) empty(start with loop var existing value), or
            ii) simple init of a single loop var, or
            iii) simple declaration of a loop var
    */
    // 1) Update statement. We need one...
    if (null == forUpdateCtx)
        return "it lacks an update statement";
    // 1a) and it must operate on a single variable
    if (forUpdateCtx.statementExpressionList().getChildCount() != 1)
        return "there is more than one expression in the update statement";
    // 1b) and it must be a simple increment or decrement
    Java8Parser.StatementExpressionContext updateStatementExpressionCtx = forUpdateCtx.statementExpressionList()
            .statementExpression(0);
    //  statementExpression : assignment | preIncrementExpression | preDecrementExpression
    //                                   | postIncrementExpression | postDecrementExpression
    //                                   | methodInvocation | classInstanceCreationExpression
    ParserRuleContext updateExpressionCtx = updateStatementExpressionCtx.getChild(ParserRuleContext.class, 0);
    int updateExpressionRule = updateExpressionCtx.getRuleIndex();
    boolean ascending_sequence;
    boolean open_interval;
    ParserRuleContext stepExpressionCtx = null;
    switch (updateExpressionRule) {

    // unaryExpression : preIncrementExpression | preDecrementExpression
    //                 | '+' unaryExpression | '-' unaryExpression
    //                 | unaryExpressionNotPlusMinus
    // preDecrementExpression : '--' unaryExpression
    // preIncrementExpression : '++' unaryExpression
    case Java8Parser.RULE_preDecrementExpression:
        ascending_sequence = false;
        break;
    case Java8Parser.RULE_preIncrementExpression:
        ascending_sequence = true;
        break;

    // postfixExpression : ( primary | expressionName ) ( '++' | '--')*
    // postIncrementExpression : postfixExpression '++'
    // postDecrementExpression : postfixExpression '--'
    case Java8Parser.RULE_postDecrementExpression:
        ascending_sequence = false;
        break;
    case Java8Parser.RULE_postIncrementExpression:
        ascending_sequence = true;
        break;

    // assignment : leftHandSide assignmentOperator expression
    // leftHandSide : expressionName | fieldAccess | arrayAccess
    case Java8Parser.RULE_assignment:
        if (null != updateStatementExpressionCtx.assignment().leftHandSide().arrayAccess())
            return "cant convert a loop variable that is an array element";
        TerminalNode node = updateStatementExpressionCtx.assignment().assignmentOperator()
                .getChild(TerminalNode.class, 0);
        switch (node.getSymbol().getType()) {
        case Java8Parser.ADD_ASSIGN:
            ascending_sequence = true;
            break;
        case Java8Parser.SUB_ASSIGN:
            ascending_sequence = false;
            break;
        case Java8Parser.ASSIGN: // possibilities too complex to warrant extracting simple a=a+1 cases
        default:
            return "potentially too complex to create a sequence from this update operation";
        }
        stepExpressionCtx = updateStatementExpressionCtx.assignment().expression();
        break;
    default: // methodInvocation | classInstanceCreationExpression
        return "the expression in the update statement is too complex";
    }
    // In each of the cases that we have not rejected, the loop variable is in the first child rule context of the
    // update statement. Get the text of the variable, rather than analysing the graph any further, as the
    // possibilities are endless; all that we require is that the loop variable text matches that in the text
    // expression and the init expression.
    ParserRuleContext loopVariable_updated_Ctx = updateExpressionCtx.getChild(ParserRuleContext.class, 0);
    String loopVariableTxt = loopVariable_updated_Ctx.getText(); // we want original text

    // 2) Expression
    if (null == expressionCtx)
        return "it lacks a test expression";
    // expression : lambdaExpression | assignmentExpression
    if (null != expressionCtx.lambdaExpression())
        return "cannot convert a lambda expression";
    // assignmentExpression : conditionalExpression | assignment
    if (null != expressionCtx.assignmentExpression().assignment())
        return "cannot convert an assignment within the test expression";
    // 2a) must be a simple relation:
    // Descend the chain of expression rule pass-through branches until we find the one that is significant, then
    // test to see if expression contains a terminal that is one of !=, <, <=, >, >=.
    ParserRuleContext testExpressionCtx = J2SGrammarUtils.descendToSignificantExpression(expressionCtx);
    int testExpressionRule = testExpressionCtx.getRuleIndex();
    TerminalNode node = testExpressionCtx.getChild(TerminalNode.class, 0);
    int testOperatorType = null != node ? node.getSymbol().getType() : 0;
    switch (testOperatorType) {
    case Java8Parser.NOTEQUAL:
        open_interval = true;
        break;
    case Java8Parser.LE:
        open_interval = false;
        break;
    case Java8Parser.GE:
        open_interval = false;
        break;

    case Java8Parser.LT: // can occur in relational and shift expressions
    case Java8Parser.GT: // can occur in relational and shift expressions
        if (testExpressionRule == Java8Parser.RULE_relationalExpression) {
            open_interval = true;
            break;
        }
    default:
        return "can only convert test expressions that use !=, <, <=, > or >=";
    }
    // 2b) relation must be testing same var as changed in update expression
    // The loop variable could be on the left or the right of the comparison operator
    int i;
    ParserRuleContext loopVariable_tested_Ctx = null;
    for (i = 0; i < 2; i++) {
        loopVariable_tested_Ctx = testExpressionCtx.getChild(ParserRuleContext.class, i);
        if (null != loopVariable_tested_Ctx && loopVariableTxt.equals(loopVariable_tested_Ctx.getText()))
            break; // found matching loop variable
        loopVariable_tested_Ctx = null;
    }
    if (null == loopVariable_tested_Ctx || (i == 1 && testExpressionCtx.getChildCount() > 3))
        return "the test expression must be testing the same variable as changed in update expression";
    ParserRuleContext terminalValueCtx = testExpressionCtx.getChild(ParserRuleContext.class, i ^ 1);
    // 2c) the terminal value side should not mutate within the loop
    // - way too difficult for us to determine this

    // 3) Loop init expression. Must be either...
    ParserRuleContext initialValueCtx;
    if (null == forInitCtx) // a) empty
    {
        // Using the loop variable's existing value from outside the scope
        initialValueCtx = loopVariable_tested_Ctx;
    } else if (null != forInitCtx.statementExpressionList()) // b) a simple init of a single loop var
    {
        /*
                // Could not convert...
                // for (i = 0; i<10; i++)
                // ...to a for..in statement because can only work with an assignment expression for loop variable initialisation.
                i = 0; while i<10  {j += 1 i += 1; }
        */
        if (forInitCtx.statementExpressionList().getChildCount() != 1)
            return "can only work with initialisation of a single loop variable";
        Java8Parser.StatementExpressionContext initExpressionCtx = forInitCtx.statementExpressionList()
                .statementExpression(0);
        if (null == initExpressionCtx.assignment())
            return "can only work with an assignment expression for loop variable initialisation";
        if (!loopVariableTxt.equals(initExpressionCtx.assignment().leftHandSide().getText()))
            return "the initialised variable is different from the updated variable"; // different to the loop variable
        initialValueCtx = initExpressionCtx.assignment().expression();
    } else if (null != forInitCtx.localVariableDeclaration()) // c) a simple decl of a single loop var
    {
        // localVariableDeclaration : variableModifier* unannType variableDeclaratorList
        Java8Parser.VariableDeclaratorListContext vdlc = forInitCtx.localVariableDeclaration()
                .variableDeclaratorList();
        // variableDeclaratorList : variableDeclarator (',' variableDeclarator)*
        if (vdlc.getChildCount() != 1)
            return "can only work with declaration of a single loop variable";
        Java8Parser.VariableDeclaratorContext vdc = vdlc.variableDeclarator(0);
        // variableDeclarator : variableDeclaratorId ('=' variableInitializer)?
        if (!loopVariableTxt.equals(vdc.getChild(0).getText()))
            return "the declared loop variable is be different from the updated variable";
        initialValueCtx = vdc.variableInitializer();
        if (null == initialValueCtx)
            return "there is no initialiser for the loop variable";
    } else
        return "loop initialisation is in unexpected form";

    // Now we have all the components we need
    String forInLoopText;
    // Use actual text with replacements
    String initialValueTxt = rewriter.getText(initialValueCtx);
    String terminalValueTxt = rewriter.getText(terminalValueCtx);
    // !!!: watch out...
    // if we use the actual text from the update expression, we can find that the pre/post-inc/dec has been
    // converted to the add/sub-assign form and because structure is lost when rewriting, the new form can
    // stick to the variable when we retrieve it. There's no easy solution for this (and any similar occurrences),
    // but we side step it by getting the text of loop variable from the test expression:
    loopVariableTxt = rewriter.getText(loopVariable_tested_Ctx);
    if (null != stepExpressionCtx || !ascending_sequence) {
        String stepExpressionText = stepExpressionCtx == null ? "-1"
                : ascending_sequence ? rewriter.getText(stepExpressionCtx)
                        : "-(" + rewriter.getText(stepExpressionCtx) + ")";
        forInLoopText = "for " + loopVariableTxt + " in " + loopVariableTxt + ".stride(from: " + initialValueTxt
                + (open_interval ? ", to: " : ", through: ") + terminalValueTxt + ", by: " + stepExpressionText
                + ")";
    } else {
        forInLoopText = "for " + loopVariableTxt + " in " + initialValueTxt
                + (open_interval ? " ..< " : " ... ") + terminalValueTxt;
    }

    Token startToken = ctx.getToken(Java8Parser.FOR, 0).getSymbol();
    Token endToken = ctx.getToken(Java8Parser.RPAREN, 0).getSymbol();

    CharStream cs = startToken.getInputStream();
    String originalExpressionTxt = cs.getText(Interval.of(startToken.getStartIndex(), endToken.getStopIndex()));
    rewriter.insertComment(originalExpressionTxt + " converted to", ctx,
            J2SRewriter.CommentWhere.beforeLineBreak);

    int startIndex = startToken.getTokenIndex();
    int endIndex = endToken.getTokenIndex();

    // Problem: (see notes in J2SRewriter.replaceAndAdjustWhitespace) Before converting to for-in, the loop will
    // also have had parentheses removed (and other transforms); rewriter may have coallesced some of the changes
    // so that the old end boundary no longer exists. (- a shortcoming of TokenStreamRewriter)
    // Workaround: test if endIndex is straddled by changed interval, and if so, extend our interval to the end of
    // the change. (Pretty horrendous to have to work around this here, but I don't yet see an easy way of fixing
    // the underlying problem or a generalised way of working around it.)
    Interval interval = rewriter.getChangedIntervalContaining(endIndex, endIndex);
    if (null != interval && interval.a <= endIndex && interval.b > endIndex)
        endIndex = interval.b;

    rewriter.replaceAndAdjustWhitespace(startIndex, endIndex, forInLoopText);

    return null;
}

From source file:com.satisfyingstructures.J2S.J2SConverter.java

License:Open Source License

private void addBracesAroundStatementIfNecessary(ParserRuleContext ctx) {
    // Ensure the statement(s) with if(else), for, while and do is always wrapped in braces.
    // At the same time, remove the parentheses around the test/control part for the statement
    int statementRule = ctx.getRuleIndex();
    if (statementRule != Java8Parser.RULE_statement && statementRule != Java8Parser.RULE_statementNoShortIf)
        return; // not our expected parameter type
    ParserRuleContext parent = ctx.getParent();
    int parentRule = parent.getRuleIndex();
    switch (parentRule) {
    case Java8Parser.RULE_ifThenElseStatement:
    case Java8Parser.RULE_ifThenElseStatementNoShortIf: {
        // if this statement is an ifThen or an ifThenElse sitting within an ifThenElse, then 
        // check if it follows the else, because we don't wrap the trailing 'if' part of 'else if'
        int statementSubRule = ctx.getChild(ParserRuleContext.class, 0).getRuleIndex();
        if (statementSubRule == Java8Parser.RULE_ifThenStatement
                || statementSubRule == Java8Parser.RULE_ifThenElseStatement
                || statementSubRule == Java8Parser.RULE_ifThenElseStatementNoShortIf) {
            // the statement after else is the last child
            if (parent.getChild(parent.getChildCount() - 1) == ctx)
                break;
        }/*from  w  w  w .jav a  2s .c om*/
    }
    // fallthru
    case Java8Parser.RULE_ifThenStatement:
    case Java8Parser.RULE_basicForStatement:
    case Java8Parser.RULE_basicForStatementNoShortIf:
    case Java8Parser.RULE_enhancedForStatement:
    case Java8Parser.RULE_enhancedForStatementNoShortIf:
    case Java8Parser.RULE_whileStatement:
    case Java8Parser.RULE_whileStatementNoShortIf:
    case Java8Parser.RULE_doStatement:
        if (ctx.start.getType() != Java8Parser.LBRACE) {
            rewriter.insertBefore(ctx.start, "{ ");
            // rewriter.insertAfter( ctx.stop, " }" );
            // ...we don't insert, because it binds to the following token and we may need to change/modify it
            // higher up the stack. Instead, we replace the current content of the stop token. This is necessary
            // because the stop can be the end of more than one statement, e.g. last semicolon in...
            //  for(;;i++)
            //      if (i%7)
            //          break;
            // ...gets wrapped twice to give
            //  for(;;i++)
            //      { if (i%7)
            //          { break; } }
            String current = rewriter.getText(ctx.stop);
            rewriter.replace(ctx.stop, current + " }");
        }
        break;
    default:
        return;
    }

    // Remove the parentheses around the test/control part for the statement
    removeParenthesesAroundExpression(parent);
}

From source file:com.satisfyingstructures.J2S.J2SConverter.java

License:Open Source License

private boolean statementEndsWithSwitchExit(ParserRuleContext ctx) {
    ParserRuleContext subCtx = ctx;//  www  .ja  v a2 s.c  o  m
    for (ctx = subCtx; ctx != null; ctx = subCtx) {
        switch (ctx.getRuleIndex()) {
        case Java8Parser.RULE_blockStatements:
            subCtx = ctx.getChild(Java8Parser.BlockStatementContext.class, ctx.getChildCount() - 1);
            continue;
        case Java8Parser.RULE_blockStatement:
            subCtx = ctx.getChild(ParserRuleContext.class, 0); // class or local var decl, or other statement
            continue;
        case Java8Parser.RULE_localVariableDeclarationStatement:
            return false;
        case Java8Parser.RULE_classDeclaration:
            return false;
        case Java8Parser.RULE_statement:
        case Java8Parser.RULE_statementNoShortIf:
            subCtx = ctx.getChild(ParserRuleContext.class, 0);
            continue;
        case Java8Parser.RULE_statementWithoutTrailingSubstatement:
            subCtx = ctx.getChild(ParserRuleContext.class, 0);
            continue;
        case Java8Parser.RULE_labeledStatement:
        case Java8Parser.RULE_labeledStatementNoShortIf:
            // Identifier ':' (statement|statementNoShortIf)
            // nodes 1 & 2 are terminal nodes; node 3 is first rule node
            subCtx = ctx.getChild(ParserRuleContext.class, 0);
            continue;
        case Java8Parser.RULE_breakStatement:
        case Java8Parser.RULE_continueStatement:
        case Java8Parser.RULE_returnStatement:
        case Java8Parser.RULE_throwStatement:
            return true;
        case Java8Parser.RULE_ifThenStatement:
            return false;
        case Java8Parser.RULE_ifThenElseStatement:
        case Java8Parser.RULE_ifThenElseStatementNoShortIf:
            // 'if' '(' expression ')' statementNoShortIf 'else' statement
            // if-statement is second rule node; else-statement is third rule node; others are terminal nodes
            return statementEndsWithSwitchExit(ctx.getChild(ParserRuleContext.class, 1))
                    && statementEndsWithSwitchExit(ctx.getChild(ParserRuleContext.class, 2));
        case Java8Parser.RULE_whileStatement:
        case Java8Parser.RULE_whileStatementNoShortIf:
        case Java8Parser.RULE_forStatement:
        case Java8Parser.RULE_forStatementNoShortIf:
        case Java8Parser.RULE_doStatement:
            // indeterminate: whether a nested exit is hit depends on data
            return false;
        case Java8Parser.RULE_block:
            // '{' blockStatements? '}'
            // ctx.getChildCount() counts both rule and terminal nodes; nbr of rule nodes is two less here;
            subCtx = ctx.getChild(ParserRuleContext.class, ctx.getChildCount() - 3);
            continue;
        case Java8Parser.RULE_emptyStatement:
        case Java8Parser.RULE_expressionStatement:
        case Java8Parser.RULE_assertStatement:
            return false;
        case Java8Parser.RULE_switchStatement:
            // too much work
            return false;
        case Java8Parser.RULE_synchronizedStatement:
            // 'synchronized' '(' expression ')' block
        case Java8Parser.RULE_tryStatement:
            // 'try' block catches | 'try' block catches? finally_ | tryWithResourcesStatement
            subCtx = ctx.getChild(Java8Parser.BlockContext.class, 0);
            continue;
        default:
            return false;
        }
    }
    return false;
}