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

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

Introduction

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

Prototype

public int getRuleIndex() 

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. j  av  a 2 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:ch.raffael.contracts.devtools.ast.AstInspector.java

License:Apache License

public void parse(final String source) {
    final StringBuilder errors = new StringBuilder();
    final StringBuilder trace = new StringBuilder("Log:\n");
    ANTLRErrorListener errorListener = new BaseErrorListener() {
        @Override//w  w w .  j  ava 2 s  .com
        public void syntaxError(Recognizer<?, ?> recognizer, @Nullable Object offendingSymbol, int line,
                int charPositionInLine, String msg, @Nullable RecognitionException e) {
            errors.append("Line ").append(line).append(':').append(charPositionInLine).append(": ").append(msg)
                    .append('\n');
        }
    };
    final CelLexer lexer = new CelLexer(new ANTLRInputStream(source));
    final CelParser parser = new CelParser(new CommonTokenStream(lexer));
    lexer.addErrorListener(errorListener);
    parser.addErrorListener(errorListener);
    parser.addParseListener(new ParseTreeListener() {
        @Override
        public void enterEveryRule(ParserRuleContext ctx) {
            trace.append("    enter\t").append(parser.getRuleNames()[ctx.getRuleIndex()]).append(", LT(1)=")
                    .append(parser.getTokenStream().LT(1).getText()).append('\n');
        }

        @Override
        public void visitTerminal(TerminalNode node) {
            trace.append("    consume\t").append(node.getSymbol()).append(" rule ")
                    .append(parser.getRuleNames()[parser.getContext().getRuleIndex()]).append('\n');
        }

        @Override
        public void visitErrorNode(ErrorNode node) {
        }

        @Override
        public void exitEveryRule(ParserRuleContext ctx) {
            trace.append("    exit\t").append(parser.getRuleNames()[ctx.getRuleIndex()]).append(", LT(1)=")
                    .append(parser.getTokenStream().LT(1).getText()).append('\n');
        }
    });
    parser.setBuildParseTree(true);
    AstBuilder builder = new AstBuilder();
    builder.install(parser);
    final CelParser.ClauseContext rootContext = parser.clause();
    if (errors.length() != 0) {
        errors.append('\n');
    }
    Runnable guiUpdate = new Runnable() {
        @Override
        public void run() {
            log.setText(errors.toString() + trace.toString());
            log.setSelectionStart(0);
            log.setSelectionEnd(0);
            if (rootContext == null || rootContext.node == null) {
                syntaxTree.setModel(new DefaultTreeModel(AstTreeNode.empty()));
                updateParseTree(null);
            } else {
                syntaxTree.setModel(new DefaultTreeModel(AstTreeNode.from(rootContext.node)));
                updateParseTree(new TreeViewer(Arrays.asList(parser.getRuleNames()), rootContext));
            }
            for (int i = 0; i < syntaxTree.getRowCount(); i++) {
                syntaxTree.expandRow(i);
            }
        }
    };
    if (SwingUtilities.isEventDispatchThread()) {
        guiUpdate.run();
    } else {
        SwingUtilities.invokeLater(guiUpdate);
    }
}

From source file:codemate.Fortran.FortranTemplater.java

License:Open Source License

@SuppressWarnings("unused")
private Stack<ParserRuleContext> findRoute(ParserRuleContext startNode, int endNodeRuleIndex) {
    Stack<ParserRuleContext> route = new Stack<ParserRuleContext>();
    ParserRuleContext node = startNode;
    boolean isFound = false;
    while (!isFound && node != null) {
        route.push(node);/*www.j  a va2  s . c o m*/
        if (node.getRuleIndex() == endNodeRuleIndex)
            isFound = true;
        else
            for (ParseTree child : node.children)
                if (child instanceof ParserRuleContext) {
                    if (((ParserRuleContext) child).getRuleIndex() == endNodeRuleIndex) {
                        route.pop(); // throw the useless parent node away
                        route.push((ParserRuleContext) child);
                        // I push a null into the stack to indicate that
                        // the end node is a sibling node.
                        route.push(null);
                        isFound = true;
                        break;
                    }
                }
        if (!isFound)
            node = node.getParent();
    }
    if (false) {
        if (route.lastElement() != null)
            System.out.println("Route (local):");
        else
            System.out.println("Route (non-local):");
        for (ParserRuleContext node_ : route)
            if (node_ != null)
                System.out.println("* " + FortranParser.ruleNames[node_.getRuleIndex()]);
    }
    return route;
}

From source file:com.espertech.esper.epl.parse.ASTUtil.java

License:Open Source License

public static boolean isRecursiveParentRule(ParserRuleContext ctx, Set<Integer> rulesIds) {
    ParserRuleContext parent = ctx.getParent();
    if (parent == null) {
        return false;
    }//  ww w.jav  a 2  s.c  o  m
    return rulesIds.contains(parent.getRuleIndex()) || isRecursiveParentRule(parent, rulesIds);
}

From source file:com.espertech.esper.epl.parse.ASTUtil.java

License:Open Source License

private static void renderNode(char[] ident, Tree node, PrintWriter printer) {
    printer.print(ident);/*  w ww .  ja v  a  2  s .co  m*/
    if (node == null) {
        printer.print("NULL NODE");
    } else {
        if (node instanceof ParserRuleContext) {
            ParserRuleContext ctx = (ParserRuleContext) node;
            int ruleIndex = ctx.getRuleIndex();
            String ruleName = EsperEPL2GrammarParser.ruleNames[ruleIndex];
            printer.print(ruleName);
        } else {
            TerminalNode terminal = (TerminalNode) node;
            printer.print(terminal.getSymbol().getText());
            printer.print(" [");
            printer.print(terminal.getSymbol().getType());
            printer.print("]");
        }

        if (node instanceof ParseTree) {
            ParseTree parseTree = (ParseTree) node;
            if (parseTree.getText() == null) {
                printer.print(" (null value in text)");
            } else if (parseTree.getText().contains("\\")) {
                int count = 0;
                for (int i = 0; i < parseTree.getText().length(); i++) {
                    if (parseTree.getText().charAt(i) == '\\') {
                        count++;
                    }
                }
                printer.print(" (" + count + " backlashes)");
            }
        }
    }
    printer.println();
}

From source file:com.khubla.jvmbasic.jvmbasicc.compiler.Dispatcher.java

License:Open Source License

/**
 * dispatch//from  w w  w .  ja v  a  2s .  c  o m
 */
public static boolean dispatch(GenerationContext generationContext) throws Exception {
    try {
        if (null != generationContext.getParseTree()) {
            final Object o = generationContext.getParseTree().getPayload();
            if (o.getClass() == CommonToken.class) {
                final CommonToken commonToken = (CommonToken) o;
                final Function function = FunctionRegistry.getInstance()
                        .getTokenFunction(commonToken.getType());
                logger.info("Dispatching to '" + function.getClass().getSimpleName() + "' for token '"
                        + jvmBasicParser.tokenNames[commonToken.getType()] + "'");
                return function.execute(generationContext);
            } else {
                final ParserRuleContext parserRuleContext = (ParserRuleContext) o;
                final Function function = FunctionRegistry.getInstance()
                        .getRuleFunction(parserRuleContext.getRuleIndex());
                logger.info("Dispatching to '" + function.getClass().getSimpleName() + "' for rule '"
                        + jvmBasicParser.ruleNames[parserRuleContext.getRuleIndex()] + "'");
                return function.execute(generationContext);
            }
        }
        return true;
    } catch (final Exception e) {
        throw new Exception("Exception in dispatch at line " + generationContext.getLineNumber(), e);
    }
}

From source file:com.khubla.jvmbasic.jvmbasicc.compiler.TreePrinter.java

License:Open Source License

@Override
public void parserRule(ParserRuleContext parserRuleContext, int ctxlevel) {
    logger.info(indentString(ctxlevel) + "[" + parserRuleContext.getRuleIndex() + " "
            + jvmBasicParser.ruleNames[parserRuleContext.getRuleIndex()] + "]");
}

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   www  .  java2s  .c o 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 mapInitialModifiersInContext(ParserRuleContext ctx) {
    ParseTree pt;/*  ww w . j  ava  2  s . co m*/
    int i = 0;
    while (null != (pt = ctx.getChild(i++)) && ParserRuleContext.class.isInstance(pt)) {
        ParserRuleContext context = (ParserRuleContext) pt;
        int contextRuleIndex = context.getRuleIndex();
        switch (contextRuleIndex) {
        case Java8Parser.RULE_interfaceModifier:
        case Java8Parser.RULE_interfaceMethodModifier:
        case Java8Parser.RULE_classModifier:
        case Java8Parser.RULE_constructorModifier:
        case Java8Parser.RULE_methodModifier:
        case Java8Parser.RULE_annotationTypeElementModifier:
        case Java8Parser.RULE_variableModifier:
        case Java8Parser.RULE_constantModifier:
        case Java8Parser.RULE_fieldModifier:
            break;
        default:
            return;
        }
        TerminalNode tn = context.getChild(TerminalNode.class, 0);
        if (null == tn)
            continue; // annotation - dealt with separately
        Token token = tn.getSymbol();
        // Handle special token cases
        switch (token.getType()) {
        case Java8Parser.STATIC:
            if (contextRuleIndex == Java8Parser.RULE_classModifier) {
                rewriter.deleteAndAdjustWhitespace(tn); // static not allowed for classes in Swift
                continue;
            }
            break;
        case Java8Parser.PRIVATE:
        case Java8Parser.PROTECTED:
        case Java8Parser.PUBLIC:
            if (contextRuleIndex == Java8Parser.RULE_interfaceMethodModifier) {
                rewriter.deleteAndAdjustWhitespace(tn); // access control not allowed for protocols in Swift
                continue;
            }
            break;
        }
        mapModifierToken(token);
    }

}

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

License:Open Source License

@Override
public void exitVariableDeclaratorId(Java8Parser.VariableDeclaratorIdContext ctx) {/*
                                                                                           
                                                                                      variableDeclaratorId is used in two main ways:
                                                                                           
                                                                                      a)  in constant, field and local variable declarations it has zero or more siblings all under the same 
                                                                                   type, and each sibling may optionally have an initialiser; in terms of the grammar, its parentage is 
                                                                                   ((constant|field|localVariable)Declaration).variableDeclaratorList.variableDeclarator.variableDeclaratorId
                                                                                   e.g.:
                                                                                       public final float r360 = 2*M_PI, r180 = M_PI, r90 = M_PIL/2;
                                                                                                          ^              ^            ^
                                                                                           
                                                                                      b)  in a (normal|catch) formal parameter, a resource definition, and as the variable in an enhanced for 
                                                                                   loop, it has no siblings and (except in resource def) no initialiser; in terms of the grammar, its 
                                                                                   parentage is
                                                                                   ((formal|lastFormal|catchFormal)Parameter|enhancedForStatement(NoShortIf|)|resource).variableDeclaratorId
                                                                                   e.g.:
                                                                                       void f(@NotNull List<Shape> shapes) { ... }
                                                                                                                   ^
                                                                                           
                                                                                      The outer parents named in a) and b) each have a unannType (=type without annotations) as earlier sibling 
                                                                                      of the branch containing the variableDeclaratorId(s), and before the unannType, a list of zero or more
                                                                                      modifiers that are legal in the context.
                                                                                           
                                                                                      The transformations we need to do to variable definitions (without yet deciding where they need to be done) are:
                                                                                      i)  swap type and name:   int a --> a: int
                                                                                      ii) map the type:   a: int --> a: Int
                                                                                      iii)suffix optionality indicator onto the type if known to be needed:   a: Int --> a: Int?
                                                                                      iv) omit the type if there is an initialiser which is explicitly of the same type:   a: Int = 1 --> a = 1
                                                                                      v)  precede the variable definition(s list) with 'var' (=variable) or 'let' (=constant), or nothing if mutability
                                                                                   is implied
                                                                                      vi) only in a formal parameter, precede the variable with the argument label suppressor '_'
                                                                                           
                                                                                      Handling i), ii) & iv):
                                                                                      The type is given by the unannType at outer parent level. If we knew it was going to stay in the same place, we
                                                                                      could map it to Swift type in exitUnannType. However, theoretically, we might need to suffix it to every
                                                                                      variable, e.g.:
                                                                                   int a = 1, b = f(), c = g();
                                                                                      --> var a = 1, b: Int = f(), c: Int = g()
                                                                                      we don't know the return types of f() and g(), and java allows a type widening when assigning (intvar = shortvar;
                                                                                      objectvar = shapevar) so for guaranteed compilation we need to have explicit types. However, it would be more
                                                                                      pragmatic to assume that they are of compatible type, and that no fancy conversion is going on, as we can't
                                                                                      reach perfection and this assumption would cover 90% of the cases. But... what about variations of:
                                                                                   List<SomeClass> list = new ArrayList<>();
                                                                                      ...this is a common pattern - the declaration type is specific about conformity to an expected interface, but
                                                                                      the concrete type in the initialiser doesn't hold any of that information.
                                                                                      Hence, if there is an initialiser then we can drop the unannType only if we are sure that it is the same as the
                                                                                      initialiser type, otherwise it moves to suffix the last of the uninitialised variable declarations and gets
                                                                                      mapped at the same time. For variableDeclaratorId used in a) above (const, field or local), this is best handled
                                                                                      in exitVariableDeclaratorList; for variableDeclaratorId use b) above (formal params / enhanced for), the
                                                                                      unannType is retained, but moved and mapped, and this could be handled here, as a common handling bottleneck.
                                                                                           
                                                                                      Handling iii): nullability
                                                                                      Java variables are assumed to be nullable if they lack a @NotNull annotation. However, there is a lot of code
                                                                                      which has not had appropriate annotations added. Some compilers (IntelliJ, ...) show annotations inferred by
                                                                                      analysing code paths, but these inferences need to be added as explicit annotations. For better porting, a
                                                                                      pass over the java source to add annotations might be well advised.
                                                                                      The annotations are in the modifiers held by the parent rules, however, their effect needs to be applied to
                                                                                      the relocated mapped unannType. Hence, this is maybe best handled where the unannType is handled, i.e. along
                                                                                      with i), ii) & iv) above.
                                                                                           
                                                                                      Handling v): var or let
                                                                                      A 'final' keyword in the modifiers before the unannType indicates const value and that 'let' should user, otherwise
                                                                                      use var. The enhanced for is translated elsewhere to Swift's for-in loop, which has complications: the default is
                                                                                      that a loop variable is considered implicitly const through each pass of the loop's statement and the 'let' is
                                                                                      omitted; however, if the loop variable is to be modified in the statement, then it has to be preceded with 'var'
                                                                                      at declaration. A formal parameter in Swift is always implicitly constant (hidden let).
                                                                                      As 'let' or 'var' have to occupy the original position of the unannType it is reasonable to handle this and the
                                                                                      special cases when unannType is moved and transformed.
                                                                                           
                                                                                      Handling iv): argument label
                                                                                      In Swift, the variableDeclaratorId in a formal parameter doubles up: the first is the label to precede the
                                                                                      argument when calling, and the second is the name to use for the parameter inside the function; java doesn't
                                                                                      use argument labelling, so suppress with '_'. Hence the variableDeclaratorId has to be preceded by '_ ' when
                                                                                      found in a formalParameter. Handle here.
                                                                                           
                                                                                   */

    ParserRuleContext parentCtx = ctx.getParent();
    if (parentCtx.getRuleIndex() == Java8Parser.RULE_variableDeclarator) {
        // Call convertVariableDeclaration() from exitDeclaratorList() instead, so that sibling
        // declarators can be dealt with together.
        //  ParserRuleContext declaratorListCtx = parentCtx.getParent();
        //  ParserRuleContext declarationCtx = declaratorListCtx.getParent();
        //  convertVariableDeclaration(declarationCtx);
        ;//from  w  w  w.j a v a 2s. c o m
    } else {
        // Parent context is (resource|(formal|lastFormal|catchFormal)Parameter|enhancedForStatement(NoShortIf|))
        convertVariableDeclaration(parentCtx);
    }
}