public Ust VisitStatement(JavaParser.StatementContext context)
        {
            var              textSpan = context.GetTextSpan();
            Statement        result;
            Expression       expression;
            Statement        statement;
            List <Statement> statements;

            if (context.blockLabel != null)
            {
                result = (Statement)Visit(context.blockLabel);
                return(result);
            }

            if (context.statementExpression != null)
            {
                result = Visit(context.statementExpression).ToStatementIfRequired();
                return(result);
            }

            if (context.identifierLabel != null)
            {
                var defaultResult = VisitChildren(context);
                return(new WrapperStatement(defaultResult, textSpan));
            }

            int firstTokenType = context.GetChild <ITerminalNode>(0).Symbol.Type;

            if (firstTokenType == JavaLexer.ASSERT)
            {
                var defaultResult = VisitChildren(context);
                return(new WrapperStatement(defaultResult, textSpan));
            }

            if (firstTokenType == JavaLexer.IF)
            {
                var condition     = (Expression)Visit(context.parExpression());
                var trueStatement = (Statement)Visit(context.statement(0));
                var falseStatment = context.ELSE() == null
                    ? null
                    : (Statement)Visit(context.statement(1));

                result = new IfElseStatement(condition, trueStatement, textSpan)
                {
                    FalseStatement = falseStatment
                };
                return(result);
            }

            if (firstTokenType == JavaLexer.FOR)
            {
                result = (Statement)Visit(context.forControl());
                return(result);
            }

            if (firstTokenType == JavaLexer.WHILE)
            {
                var conditionWhile = (Expression)Visit(context.parExpression());
                statement = (Statement)Visit(context.statement(0));

                result = new WhileStatement(conditionWhile, statement, textSpan);
                return(result);
            }

            if (firstTokenType == JavaLexer.DO)
            {
                statement  = (Statement)Visit(context.statement(0));
                expression = (Expression)Visit(context.parExpression());

                result = new DoWhileStatement(statement, expression, textSpan);
                return(result);
            }

            if (firstTokenType == JavaLexer.TRY)
            {
                // TODO: implement 'try' resourceSpecification block catchClause* finallyBlock? (C# using)

                var block = (BlockStatement)Visit(context.block());
                JavaParser.ResourceSpecificationContext resSpec = context.resourceSpecification();

                List <CatchClause> catchClauses = context.catchClause()
                                                  ?.Select(cc => (CatchClause)Visit(cc))
                                                  .Where(cc => cc != null).ToList();

                var finallyBlock = context.finallyBlock() == null ? null
                    : (BlockStatement)Visit(context.finallyBlock());

                if (resSpec == null)
                {
                    result = new TryCatchStatement(block, textSpan)
                    {
                        CatchClauses = catchClauses,
                        FinallyBlock = finallyBlock
                    };
                }
                else
                {
                    // C# using conversion to tryCatch
                    statements = new List <Statement>();
                    statements.AddRange(resSpec.resources().resource()
                                        .Select(res =>
                    {
                        var e = (VariableDeclarationExpression)Visit(res);
                        return(e == null ? null : new ExpressionStatement(e));
                    })
                                        .Where(res => res != null));
                    statements.AddRange(block.Statements);
                    var blockStatement = new BlockStatement(statements, context.GetTextSpan());

                    result = new TryCatchStatement(block, textSpan)
                    {
                        CatchClauses = catchClauses,
                        FinallyBlock = finallyBlock
                    };
                }
                return(result);
            }

            if (firstTokenType == JavaLexer.SWITCH)
            {
                expression = (Expression)Visit(context.parExpression());
                SwitchSection[] switchSections = context.switchBlockStatementGroup()
                                                 .Select(group => (SwitchSection)Visit(group))
                                                 .Where(group => group != null).ToArray();

                result = new SwitchStatement(expression, switchSections, textSpan);
                return(result);
            }

            if (firstTokenType == JavaLexer.SYNCHRONIZED) // synchronized(a) { b; c; } => { a; b; c; }
            {
                var resultStatements = new List <Statement>();
                expression = (Expression)Visit(context.parExpression());
                statements = context.block().blockStatement()
                             .Select(s => (Statement)Visit(s))
                             .Where(s => s != null).ToList();
                resultStatements.Add(new ExpressionStatement(expression, expression.TextSpan));
                resultStatements.AddRange(statements);

                result = new BlockStatement(resultStatements, textSpan);
                return(result);
            }

            if (firstTokenType == JavaLexer.RETURN)
            {
                expression = context.expression(0) != null
                            ? (Expression)Visit(context.expression(0))
                            : null;
                result = new ReturnStatement(expression, textSpan);
                return(result);
            }

            if (firstTokenType == JavaLexer.THROW)
            {
                expression = (Expression)Visit(context.expression(0));
                result     = new ThrowStatement(expression, textSpan);
                return(result);
            }

            if (firstTokenType == JavaLexer.BREAK)
            {
                result = new BreakStatement(textSpan);
                return(result);
            }

            if (firstTokenType == JavaLexer.CONTINUE)
            {
                result = new ContinueStatement(textSpan);
                return(result);
            }

            if (firstTokenType == JavaLexer.SEMI)
            {
                result = new EmptyStatement(textSpan);
                return(result);
            }

            return(VisitShouldNotBeVisited(context));
        }
 public Ust VisitResourceSpecification([NotNull] JavaParser.ResourceSpecificationContext context)
 {
     return(VisitChildren(context));
 }