Code review comment: I think the error given at the default case is okay to use for this as well.

Code under review:
private STNode parseIdentifierRhsInStmtStartingBrace(STNode readonlyKeyword) {
        STNode identifier = parseIdentifier(ParserRuleContext.VARIABLE_REF);
        switch (peek().kind) {
            case COMMA_TOKEN: 
                
                STNode colon = STNodeFactory.createEmptyNode();
                STNode value = STNodeFactory.createEmptyNode();
                return STNodeFactory.createSpecificFieldNode(readonlyKeyword, identifier, colon, value);
            case COLON_TOKEN:
                
                colon = parseColon();
                if (!isEmpty(readonlyKeyword)) {
                    value = parseExpression();
                    return STNodeFactory.createSpecificFieldNode(readonlyKeyword, identifier, colon, value);
                }

                switch (peek().kind) {
                    case OPEN_BRACKET_TOKEN: 
                        STNode bindingPatternOrExpr = parseListBindingPatternOrListConstructor();
                        return getMappingField(identifier, colon, bindingPatternOrExpr);
                    case OPEN_BRACE_TOKEN: 
                        bindingPatternOrExpr = parseMappingBindingPatterOrMappingConstructor();
                        return getMappingField(identifier, colon, bindingPatternOrExpr);
                    case ERROR_KEYWORD: 
                        bindingPatternOrExpr = parseErrorBindingPatternOrErrorConstructor();
                        return getMappingField(identifier, colon, bindingPatternOrExpr);
                    case IDENTIFIER_TOKEN: 
                        return parseQualifiedIdentifierRhsInStmtStartBrace(identifier, colon);
                    default:
                        STNode expr = parseExpression();
                        return getMappingField(identifier, colon, expr);
                }
            default:
                switchContext(ParserRuleContext.BLOCK_STMT);
                if (!isEmpty(readonlyKeyword)) {
                    startContext(ParserRuleContext.VAR_DECL_STMT);
                    STNode bindingPattern = STNodeFactory.createCaptureBindingPatternNode(identifier);
                    STNode typedBindingPattern =
                            STNodeFactory.createTypedBindingPatternNode(readonlyKeyword, bindingPattern);
                    STNode annots = STNodeFactory.createEmptyNodeList();
                    List<STNode> varDeclQualifiers = new ArrayList<>();
                    return parseVarDeclRhs(annots, varDeclQualifiers, typedBindingPattern, false);
                }

                startContext(ParserRuleContext.AMBIGUOUS_STMT);
                STNode qualifiedIdentifier = parseQualifiedIdentifier(identifier, false);
                STNode expr = parseTypedBindingPatternOrExprRhs(qualifiedIdentifier, true);
                STNode annots = STNodeFactory.createEmptyNodeList();
                return parseStmtStartsWithTypedBPOrExprRhs(annots, expr);
        }
    }

    /**
     * Parse the rhs components of "<code>{ identifier : identifier</code>",
     * at the start of a statement. i.e: "{foo:bar".
     *
     * @return Parsed node
     */
    private STNode parseQualifiedIdentifierRhsInStmtStartBrace(STNode identifier, STNode colon) {
        STNode secondIdentifier = parseIdentifier(ParserRuleContext.VARIABLE_REF);
        STNode secondNameRef = STNodeFactory.createSimpleNameReferenceNode(secondIdentifier);
        if (isWildcardBP(secondIdentifier)) {
            
            STNode wildcardBP = getWildcardBindingPattern(secondIdentifier);
            STNode nameRef = STNodeFactory.createSimpleNameReferenceNode(identifier);
            return STNodeFactory.createFieldBindingPatternFullNode(nameRef, colon, wildcardBP);
        }

        
        STNode qualifiedNameRef = createQualifiedNameReferenceNode(identifier, colon, secondIdentifier);
        switch (peek().kind) {
            case COMMA_TOKEN:
                
                
                
                return STNodeFactory.createSpecificFieldNode(STNodeFactory.createEmptyNode(), identifier, colon,
                        secondNameRef);
            case OPEN_BRACE_TOKEN: 
            case IDENTIFIER_TOKEN: 
                switchContext(ParserRuleContext.BLOCK_STMT);
                startContext(ParserRuleContext.VAR_DECL_STMT);
                List<STNode> varDeclQualifiers = new ArrayList<>();
                STNode typeBindingPattern =
                        parseTypedBindingPatternTypeRhs(qualifiedNameRef, ParserRuleContext.VAR_DECL_STMT);
                STNode annots = STNodeFactory.createEmptyNodeList();
                return parseVarDeclRhs(annots, varDeclQualifiers, typeBindingPattern, false);
            case OPEN_BRACKET_TOKEN:
                
                
                return parseMemberRhsInStmtStartWithBrace(identifier, colon, secondIdentifier, secondNameRef);
            case QUESTION_MARK_TOKEN:
                
                STNode typeDesc = parseComplexTypeDescriptor(qualifiedNameRef,
                        ParserRuleContext.TYPE_DESC_IN_TYPE_BINDING_PATTERN, true);
                varDeclQualifiers = new ArrayList<>();
                typeBindingPattern = parseTypedBindingPatternTypeRhs(typeDesc, ParserRuleContext.VAR_DECL_STMT);
                annots = STNodeFactory.createEmptyNodeList();
                return parseVarDeclRhs(annots, varDeclQualifiers, typeBindingPattern, false);
            case EQUAL_TOKEN:
            case SEMICOLON_TOKEN:
                
                return parseStatementStartWithExprRhs(qualifiedNameRef);
            case PIPE_TOKEN:
            case BITWISE_AND_TOKEN:
            default:
                return parseMemberWithExprInRhs(identifier, colon, secondIdentifier, secondNameRef);
        }
    }

    private SyntaxKind getBracedListType(STNode member) {
        switch (member.kind) {
            case FIELD_BINDING_PATTERN:
            case CAPTURE_BINDING_PATTERN:
            case LIST_BINDING_PATTERN:
            case MAPPING_BINDING_PATTERN:
            case WILDCARD_BINDING_PATTERN:
                return SyntaxKind.MAPPING_BINDING_PATTERN;
            case SPECIFIC_FIELD:
                STNode expr = ((STSpecificFieldNode) member).valueExpr;
                if (expr == null) {
                    return SyntaxKind.MAPPING_BP_OR_MAPPING_CONSTRUCTOR;
                }

                
                switch (expr.kind) {
                    case SIMPLE_NAME_REFERENCE:
                    case LIST_BP_OR_LIST_CONSTRUCTOR:
                    case MAPPING_BP_OR_MAPPING_CONSTRUCTOR:
                        return SyntaxKind.MAPPING_BP_OR_MAPPING_CONSTRUCTOR;
                    case ERROR_BINDING_PATTERN:
                        return SyntaxKind.MAPPING_BINDING_PATTERN;
                    case ERROR_CONSTRUCTOR:
                        if (isPossibleErrorBindingPattern((STErrorConstructorExpressionNode) expr)) {
                            return SyntaxKind.MAPPING_BP_OR_MAPPING_CONSTRUCTOR;
                        }
                        return SyntaxKind.MAPPING_CONSTRUCTOR;
                    default:
                        return SyntaxKind.MAPPING_CONSTRUCTOR;
                }
            case SPREAD_FIELD:
            case COMPUTED_NAME_FIELD:
                return SyntaxKind.MAPPING_CONSTRUCTOR;
            case SIMPLE_NAME_REFERENCE:
            case QUALIFIED_NAME_REFERENCE:
            case LIST_BP_OR_LIST_CONSTRUCTOR:
            case MAPPING_BP_OR_MAPPING_CONSTRUCTOR:
            case REST_BINDING_PATTERN:
                return SyntaxKind.MAPPING_BP_OR_MAPPING_CONSTRUCTOR;
            case LIST:
                return SyntaxKind.BLOCK_STATEMENT;
            default:
                return SyntaxKind.NONE;
        }
    }

    /**
     * Parse mapping binding pattern or mapping constructor.
     *
     * @return Parsed node
     */
    private STNode parseMappingBindingPatterOrMappingConstructor() {
        startContext(ParserRuleContext.MAPPING_BP_OR_MAPPING_CONSTRUCTOR);
        STNode openBrace = parseOpenBrace();
        List<STNode> memberList = new ArrayList<>();
        return parseMappingBindingPatternOrMappingConstructor(openBrace, memberList);
    }

    private boolean isBracedListEnd(SyntaxKind nextTokenKind) {
        switch (nextTokenKind) {
            case EOF_TOKEN:
            case CLOSE_BRACE_TOKEN:
                return true;
            default:
                return false;
        }
    }

    private STNode parseMappingBindingPatternOrMappingConstructor(STNode openBrace, List<STNode> memberList) {
        STToken nextToken = peek();
        while (!isBracedListEnd(nextToken.kind)) {
            
            STNode member = parseMappingBindingPatterOrMappingConstructorMember();
            SyntaxKind currentNodeType = getTypeOfMappingBPOrMappingCons(member);

            switch (currentNodeType) {
                case MAPPING_CONSTRUCTOR:
                    
                    
                    return parseAsMappingConstructor(openBrace, memberList, member);
                case MAPPING_BINDING_PATTERN:
                    
                    
                    return parseAsMappingBindingPattern(openBrace, memberList, member);
                case MAPPING_BP_OR_MAPPING_CONSTRUCTOR:
                default:
                    memberList.add(member);
                    break;
            }

            
            STNode memberEnd = parseMappingFieldEnd();
            if (memberEnd == null) {
                break;
            }
            memberList.add(memberEnd);
            nextToken = peek();
        }

        
        STNode closeBrace = parseCloseBrace();
        return parseMappingBindingPatternOrMappingConstructor(openBrace, memberList, closeBrace);
    }

    private STNode parseMappingBindingPatterOrMappingConstructorMember() {
        switch (peek().kind) {
            case IDENTIFIER_TOKEN:
                STNode key = parseIdentifier(ParserRuleContext.MAPPING_FIELD_NAME);
                return parseMappingFieldRhs(key);
            case STRING_LITERAL_TOKEN:
                STNode readonlyKeyword = STNodeFactory.createEmptyNode();
                key = parseStringLiteral();
                STNode colon = parseColon();
                STNode valueExpr = parseExpression();
                return STNodeFactory.createSpecificFieldNode(readonlyKeyword, key, colon, valueExpr);
            case OPEN_BRACKET_TOKEN:
                return parseComputedField();
            case ELLIPSIS_TOKEN:
                STNode ellipsis = parseEllipsis();
                STNode expr = parseExpression();
                if (expr.kind == SyntaxKind.SIMPLE_NAME_REFERENCE) {
                    return STNodeFactory.createRestBindingPatternNode(ellipsis, expr);
                }
                return STNodeFactory.createSpreadFieldNode(ellipsis, expr);
            default:
                recover(peek(), ParserRuleContext.MAPPING_BP_OR_MAPPING_CONSTRUCTOR_MEMBER);
                return parseMappingBindingPatterOrMappingConstructorMember();
        }
    }

    private STNode parseMappingFieldRhs(STNode key) {
        STNode colon;
        STNode valueExpr;
        switch (peek().kind) {
            case COLON_TOKEN:
                colon = parseColon();
                return parseMappingFieldValue(key, colon);
            case COMMA_TOKEN:
            case CLOSE_BRACE_TOKEN:
                STNode readonlyKeyword = STNodeFactory.createEmptyNode();
                colon = STNodeFactory.createEmptyNode();
                valueExpr = STNodeFactory.createEmptyNode();
                return STNodeFactory.createSpecificFieldNode(readonlyKeyword, key, colon, valueExpr);
            default:
                STToken token = peek();
                recover(token, ParserRuleContext.FIELD_BINDING_PATTERN_END);
                readonlyKeyword = STNodeFactory.createEmptyNode();
                return parseSpecificFieldRhs(readonlyKeyword, key);
        }
    }

    private STNode parseMappingFieldValue(STNode key, STNode colon) {
        
        STNode expr;
        switch (peek().kind) {
            case IDENTIFIER_TOKEN:
                expr = parseExpression();
                break;
            case OPEN_BRACKET_TOKEN: 
                expr = parseListBindingPatternOrListConstructor();
                break;
            case OPEN_BRACE_TOKEN: 
                expr = parseMappingBindingPatterOrMappingConstructor();
                break;
            default:
                expr = parseExpression();
                break;
        }

        if (isBindingPattern(expr.kind)) {
            key = STNodeFactory.createSimpleNameReferenceNode(key);
            return STNodeFactory.createFieldBindingPatternFullNode(key, colon, expr);
        }

        STNode readonlyKeyword = STNodeFactory.createEmptyNode();
        return STNodeFactory.createSpecificFieldNode(readonlyKeyword, key, colon, expr);
    }

    private boolean isBindingPattern(SyntaxKind kind) {
        switch (kind) {
            case FIELD_BINDING_PATTERN:
            case MAPPING_BINDING_PATTERN:
            case CAPTURE_BINDING_PATTERN:
            case LIST_BINDING_PATTERN:
            case WILDCARD_BINDING_PATTERN:
                return true;
            default:
                return false;
        }
    }

    private SyntaxKind getTypeOfMappingBPOrMappingCons(STNode memberNode) {
        switch (memberNode.kind) {
            case FIELD_BINDING_PATTERN:
            case MAPPING_BINDING_PATTERN:
            case CAPTURE_BINDING_PATTERN:
            case LIST_BINDING_PATTERN:
            case WILDCARD_BINDING_PATTERN:
                return SyntaxKind.MAPPING_BINDING_PATTERN;
            case SPECIFIC_FIELD:
                STNode expr = ((STSpecificFieldNode) memberNode).valueExpr;
                
                if (expr == null || expr.kind == SyntaxKind.SIMPLE_NAME_REFERENCE ||
                        expr.kind == SyntaxKind.LIST_BP_OR_LIST_CONSTRUCTOR ||
                        expr.kind == SyntaxKind.MAPPING_BP_OR_MAPPING_CONSTRUCTOR) {
                    return SyntaxKind.MAPPING_BP_OR_MAPPING_CONSTRUCTOR;
                }
                return SyntaxKind.MAPPING_CONSTRUCTOR;
            case SPREAD_FIELD:
            case COMPUTED_NAME_FIELD:
                return SyntaxKind.MAPPING_CONSTRUCTOR;
            case MAPPING_BP_OR_MAPPING_CONSTRUCTOR:
            case SIMPLE_NAME_REFERENCE:
            case QUALIFIED_NAME_REFERENCE:
            case LIST_BP_OR_LIST_CONSTRUCTOR:
            case REST_BINDING_PATTERN: 
            default:
                return SyntaxKind.MAPPING_BP_OR_MAPPING_CONSTRUCTOR;
        }
    }

    private STNode parseMappingBindingPatternOrMappingConstructor(STNode openBrace, List<STNode> members,
                                                                  STNode closeBrace) {
        endContext();
        return new STAmbiguousCollectionNode(SyntaxKind.MAPPING_BP_OR_MAPPING_CONSTRUCTOR, openBrace, members,
                closeBrace);
    }

    private STNode parseAsMappingBindingPattern(STNode openBrace, List<STNode> members, STNode member) {
        members.add(member);
        members = getBindingPatternsList(members, false);
        
        switchContext(ParserRuleContext.MAPPING_BINDING_PATTERN);
        return parseMappingBindingPattern(openBrace, members, member);
    }

    /**
     * Parse list binding pattern or list constructor.
     *
     * @return Parsed node
     */
    private STNode parseListBindingPatternOrListConstructor() {
        startContext(ParserRuleContext.BRACKETED_LIST);
        STNode openBracket = parseOpenBracket();
        List<STNode> memberList = new ArrayList<>();
        return parseListBindingPatternOrListConstructor(openBracket, memberList, false);
    }

    private STNode parseListBindingPatternOrListConstructor(STNode openBracket, List<STNode> memberList,
                                                            boolean isRoot) {
        
        STToken nextToken = peek();
        while (!isBracketedListEnd(nextToken.kind)) {
            
            STNode member = parseListBindingPatternOrListConstructorMember();
            SyntaxKind currentNodeType = getParsingNodeTypeOfListBPOrListCons(member);

            switch (currentNodeType) {
                case LIST_CONSTRUCTOR:
                    
                    
                    return parseAsListConstructor(openBracket, memberList, member, isRoot);
                case LIST_BINDING_PATTERN:
                    
                    
                    return parseAsListBindingPattern(openBracket, memberList, member, isRoot);
                case LIST_BP_OR_LIST_CONSTRUCTOR:
                default:
                    memberList.add(member);
                    break;
            }

            
            STNode memberEnd = parseBracketedListMemberEnd();
            if (memberEnd == null) {
                break;
            }
            memberList.add(memberEnd);
            nextToken = peek();
        }

        
        STNode closeBracket = parseCloseBracket();
        return parseListBindingPatternOrListConstructor(openBracket, memberList, closeBracket, isRoot);
    }

    private STNode parseListBindingPatternOrListConstructorMember() {
        STToken nextToken = peek();
        switch (nextToken.kind) {
            case OPEN_BRACKET_TOKEN:
                
                return parseListBindingPatternOrListConstructor();
            case IDENTIFIER_TOKEN:
                STNode identifier = parseQualifiedIdentifier(ParserRuleContext.VARIABLE_REF);
                if (isWildcardBP(identifier)) {
                    return getWildcardBindingPattern(identifier);
                }
                return parseExpressionRhs(DEFAULT_OP_PRECEDENCE, identifier, false, false);
            case OPEN_BRACE_TOKEN:
                return parseMappingBindingPatterOrMappingConstructor();
            case ELLIPSIS_TOKEN:
                return parseRestBindingOrSpreadMember();
            default:
                if (isValidExpressionStart(nextToken.kind, 1)) {
                    return parseExpression();
                }

                recover(peek(), ParserRuleContext.LIST_BP_OR_LIST_CONSTRUCTOR_MEMBER);
                return parseListBindingPatternOrListConstructorMember();
        }
    }

    private SyntaxKind getParsingNodeTypeOfListBPOrListCons(STNode memberNode) {
        switch (memberNode.kind) {
            case CAPTURE_BINDING_PATTERN:
            case LIST_BINDING_PATTERN:
            case MAPPING_BINDING_PATTERN:
            case WILDCARD_BINDING_PATTERN:
                return SyntaxKind.LIST_BINDING_PATTERN;
            case SIMPLE_NAME_REFERENCE: 
            case LIST_BP_OR_LIST_CONSTRUCTOR: 
            case MAPPING_BP_OR_MAPPING_CONSTRUCTOR:
            case REST_BINDING_PATTERN:
                return SyntaxKind.LIST_BP_OR_LIST_CONSTRUCTOR;
            case SPREAD_MEMBER:
            default:
                return SyntaxKind.LIST_CONSTRUCTOR;
        }
    }

    private STNode parseAsListConstructor(STNode openBracket, List<STNode> memberList, STNode member, boolean isRoot) {
        memberList.add(member);
        memberList = getExpressionList(memberList, false);

        switchContext(ParserRuleContext.LIST_CONSTRUCTOR);
        STNode listMembers = parseListMembers(memberList);
        STNode closeBracket = parseCloseBracket();
        STNode listConstructor =
                STNodeFactory.createListConstructorExpressionNode(openBracket, listMembers, closeBracket);
        endContext();

        STNode expr = parseExpressionRhs(DEFAULT_OP_PRECEDENCE, listConstructor, false, true);
        if (!isRoot) {
            return expr;
        }

        return parseStatementStartWithExprRhs(expr);

    }

    private STNode parseListBindingPatternOrListConstructor(STNode openBracket, List<STNode> members,
                                                            STNode closeBracket, boolean isRoot) {
        STNode lbpOrListCons;
        switch (peek().kind) {
            case COMMA_TOKEN: 
            case CLOSE_BRACE_TOKEN: 
            case CLOSE_BRACKET_TOKEN:
                if (!isRoot) {
                    endContext();
                    return new STAmbiguousCollectionNode(SyntaxKind.LIST_BP_OR_LIST_CONSTRUCTOR, openBracket, members,
                            closeBracket);
                }
                
            default:
                SyntaxKind nextTokenKind = peek().kind;
                if (isValidExprRhsStart(nextTokenKind, closeBracket.kind) || 
                        nextTokenKind == SyntaxKind.SEMICOLON_TOKEN && isRoot) { 
                    members = getExpressionList(members, false);
                    STNode memberExpressions = STNodeFactory.createNodeList(members);
                    lbpOrListCons = STNodeFactory.createListConstructorExpressionNode(openBracket, memberExpressions,
                            closeBracket);
                    lbpOrListCons = parseExpressionRhs(DEFAULT_OP_PRECEDENCE, lbpOrListCons, false, true);
                    break;
                }

                
                members = getBindingPatternsList(members, true);
                STNode bindingPatternsNode = STNodeFactory.createNodeList(members);
                lbpOrListCons = STNodeFactory.createListBindingPatternNode(openBracket, bindingPatternsNode,
                        closeBracket);
                break;
        }

        endContext();

        if (!isRoot) {
            return lbpOrListCons;
        }
        
        if (lbpOrListCons.kind == SyntaxKind.LIST_BINDING_PATTERN) {
            return parseAssignmentStmtRhs(lbpOrListCons);
        } else {
            return parseStatementStartWithExprRhs(lbpOrListCons);
        }
    }

    private STNode parseMemberRhsInStmtStartWithBrace(STNode identifier, STNode colon, STNode secondIdentifier,
                                                      STNode secondNameRef) {
        STNode typedBPOrExpr =
                parseTypedBindingPatternOrMemberAccess(secondNameRef, false, true, ParserRuleContext.AMBIGUOUS_STMT);
        if (isExpression(typedBPOrExpr.kind)) {
            return parseMemberWithExprInRhs(identifier, colon, secondIdentifier, typedBPOrExpr);
        }

        switchContext(ParserRuleContext.BLOCK_STMT);
        startContext(ParserRuleContext.VAR_DECL_STMT);
        List<STNode> varDeclQualifiers = new ArrayList<>();
        STNode annots = STNodeFactory.createEmptyNodeList();

        
        
        
        STTypedBindingPatternNode typedBP = (STTypedBindingPatternNode) typedBPOrExpr;
        STNode qualifiedNameRef = createQualifiedNameReferenceNode(identifier, colon, secondIdentifier);
        STNode newTypeDesc = mergeQualifiedNameWithTypeDesc(qualifiedNameRef, typedBP.typeDescriptor);

        STNode newTypeBP = STNodeFactory.createTypedBindingPatternNode(newTypeDesc, typedBP.bindingPattern);
        STNode publicQualifier = STNodeFactory.createEmptyNode();
        return parseVarDeclRhs(annots, publicQualifier, varDeclQualifiers, newTypeBP, false);
    }

    /**
     * Parse a member that starts with "foo:bar[", in a statement starting with a brace.
     *
     * @param identifier       First identifier of the statement
     * @param colon            Colon that follows the first identifier
     * @param secondIdentifier Identifier that follows the colon
     * @param memberAccessExpr Member access expression
     * @return Parsed node
     */
    private STNode parseMemberWithExprInRhs(STNode identifier, STNode colon, STNode secondIdentifier,
                                            STNode memberAccessExpr) {
        STNode expr = parseExpressionRhs(DEFAULT_OP_PRECEDENCE, memberAccessExpr, false, true);
        switch (peek().kind) {
            case COMMA_TOKEN:
            case CLOSE_BRACE_TOKEN:
                switchContext(ParserRuleContext.EXPRESSION_STATEMENT);
                STNode readonlyKeyword = STNodeFactory.createEmptyNode();
                return STNodeFactory.createSpecificFieldNode(readonlyKeyword, identifier, colon, expr);
            case EQUAL_TOKEN:
            case SEMICOLON_TOKEN:
            default:
                switchContext(ParserRuleContext.BLOCK_STMT);
                startContext(ParserRuleContext.EXPRESSION_STATEMENT);
                
                STNode qualifiedName = createQualifiedNameReferenceNode(identifier, colon, secondIdentifier);
                STNode updatedExpr = mergeQualifiedNameWithExpr(qualifiedName, expr);
                return parseStatementStartWithExprRhs(updatedExpr);
        }
    }

    private STNode parseInferredTypeDescDefaultOrExpression() {
        STToken nextToken = peek();
        SyntaxKind nextTokenKind = nextToken.kind;

        if (nextTokenKind == SyntaxKind.LT_TOKEN) {
            return parseInferredTypeDescDefaultOrExpression(consume());
        }

        if (isValidExprStart(nextTokenKind)) {
            return parseExpression();
        }

         recover(nextToken, ParserRuleContext.EXPR_START_OR_INFERRED_TYPEDESC_DEFAULT_START);
         return parseInferredTypeDescDefaultOrExpression();
    }

    private STNode parseInferredTypeDescDefaultOrExpression(STToken ltToken) {
        STToken nextToken = peek();

        if (nextToken.kind == SyntaxKind.GT_TOKEN) {
            return STNodeFactory.createInferredTypedescDefaultNode(ltToken, consume());
        }

        if (isTypeStartingToken(nextToken.kind) || nextToken.kind == SyntaxKind.AT_TOKEN) {
            startContext(ParserRuleContext.TYPE_CAST);
            STNode expr = parseTypeCastExpr(ltToken, true, false, false);
            return parseExpressionRhs(DEFAULT_OP_PRECEDENCE, expr, true, false);
        }

        recover(nextToken, ParserRuleContext.TYPE_CAST_PARAM_START_OR_INFERRED_TYPEDESC_DEFAULT_END);
        return parseInferredTypeDescDefaultOrExpression(ltToken);
    }

    /**
     * Replace the first identifier of an expression, with a given qualified-identifier.
     * Only expressions that can start with "bar[..]" can reach here.
     *
     * @param qualifiedName Qualified identifier to replace simple identifier
     * @param exprOrAction  Expression or action     * @return Updated expression
     */
    private STNode mergeQualifiedNameWithExpr(STNode qualifiedName, STNode exprOrAction) {
        switch (exprOrAction.kind) {
            case SIMPLE_NAME_REFERENCE:
                return qualifiedName;
            case BINARY_EXPRESSION:
                STBinaryExpressionNode binaryExpr = (STBinaryExpressionNode) exprOrAction;
                STNode newLhsExpr = mergeQualifiedNameWithExpr(qualifiedName, binaryExpr.lhsExpr);
                return STNodeFactory.createBinaryExpressionNode(binaryExpr.kind, newLhsExpr, binaryExpr.operator,
                        binaryExpr.rhsExpr);
            case FIELD_ACCESS:
                STFieldAccessExpressionNode fieldAccess = (STFieldAccessExpressionNode) exprOrAction;
                newLhsExpr = mergeQualifiedNameWithExpr(qualifiedName, fieldAccess.expression);
                return STNodeFactory.createFieldAccessExpressionNode(newLhsExpr, fieldAccess.dotToken,
                        fieldAccess.fieldName);
            case INDEXED_EXPRESSION:
                STIndexedExpressionNode memberAccess = (STIndexedExpressionNode) exprOrAction;
                newLhsExpr = mergeQualifiedNameWithExpr(qualifiedName, memberAccess.containerExpression);
                return STNodeFactory.createIndexedExpressionNode(newLhsExpr, memberAccess.openBracket,
                        memberAccess.keyExpression, memberAccess.closeBracket);
            case TYPE_TEST_EXPRESSION:
                STTypeTestExpressionNode typeTest = (STTypeTestExpressionNode) exprOrAction;
                newLhsExpr = mergeQualifiedNameWithExpr(qualifiedName, typeTest.expression);
                return STNodeFactory.createTypeTestExpressionNode(newLhsExpr, typeTest.isKeyword,
                        typeTest.typeDescriptor);
            case ANNOT_ACCESS:
                STAnnotAccessExpressionNode annotAccess = (STAnnotAccessExpressionNode) exprOrAction;
                newLhsExpr = mergeQualifiedNameWithExpr(qualifiedName, annotAccess.expression);
                return STNodeFactory.createFieldAccessExpressionNode(newLhsExpr, annotAccess.annotChainingToken,
                        annotAccess.annotTagReference);
            case OPTIONAL_FIELD_ACCESS:
                STOptionalFieldAccessExpressionNode optionalFieldAccess =
                        (STOptionalFieldAccessExpressionNode) exprOrAction;
                newLhsExpr = mergeQualifiedNameWithExpr(qualifiedName, optionalFieldAccess.expression);
                return STNodeFactory.createFieldAccessExpressionNode(newLhsExpr,
                        optionalFieldAccess.optionalChainingToken, optionalFieldAccess.fieldName);
            case CONDITIONAL_EXPRESSION:
                STConditionalExpressionNode conditionalExpr = (STConditionalExpressionNode) exprOrAction;
                newLhsExpr = mergeQualifiedNameWithExpr(qualifiedName, conditionalExpr.lhsExpression);
                return STNodeFactory.createConditionalExpressionNode(newLhsExpr, conditionalExpr.questionMarkToken,
                        conditionalExpr.middleExpression, conditionalExpr.colonToken, conditionalExpr.endExpression);
            case REMOTE_METHOD_CALL_ACTION:
                STRemoteMethodCallActionNode remoteCall = (STRemoteMethodCallActionNode) exprOrAction;
                newLhsExpr = mergeQualifiedNameWithExpr(qualifiedName, remoteCall.expression);
                return STNodeFactory.createRemoteMethodCallActionNode(newLhsExpr, remoteCall.rightArrowToken,
                        remoteCall.methodName, remoteCall.openParenToken, remoteCall.arguments,
                        remoteCall.closeParenToken);
            case ASYNC_SEND_ACTION:
                STAsyncSendActionNode asyncSend = (STAsyncSendActionNode) exprOrAction;
                newLhsExpr = mergeQualifiedNameWithExpr(qualifiedName, asyncSend.expression);
                return STNodeFactory.createAsyncSendActionNode(newLhsExpr, asyncSend.rightArrowToken,
                        asyncSend.peerWorker);
            case SYNC_SEND_ACTION:
                STSyncSendActionNode syncSend = (STSyncSendActionNode) exprOrAction;
                newLhsExpr = mergeQualifiedNameWithExpr(qualifiedName, syncSend.expression);
                return STNodeFactory.createAsyncSendActionNode(newLhsExpr, syncSend.syncSendToken, syncSend.peerWorker);
            case FUNCTION_CALL:
                STFunctionCallExpressionNode funcCall = (STFunctionCallExpressionNode) exprOrAction;
                return STNodeFactory.createFunctionCallExpressionNode(qualifiedName, funcCall.openParenToken,
                        funcCall.arguments, funcCall.closeParenToken);
            default:
                return exprOrAction;
        }
    }

    private STNode mergeQualifiedNameWithTypeDesc(STNode qualifiedName, STNode typeDesc) {
        switch (typeDesc.kind) {
            case SIMPLE_NAME_REFERENCE:
                return qualifiedName;
            case ARRAY_TYPE_DESC:
                STArrayTypeDescriptorNode arrayTypeDesc = (STArrayTypeDescriptorNode) typeDesc;
                STNode newMemberType = mergeQualifiedNameWithTypeDesc(qualifiedName, arrayTypeDesc.memberTypeDesc);
                return STNodeFactory.createArrayTypeDescriptorNode(newMemberType, arrayTypeDesc.dimensions);
            case UNION_TYPE_DESC:
                STUnionTypeDescriptorNode unionTypeDesc = (STUnionTypeDescriptorNode) typeDesc;
                STNode newlhsType = mergeQualifiedNameWithTypeDesc(qualifiedName, unionTypeDesc.leftTypeDesc);
                return mergeTypesWithUnion(newlhsType, unionTypeDesc.pipeToken, unionTypeDesc.rightTypeDesc);
            case INTERSECTION_TYPE_DESC:
                STIntersectionTypeDescriptorNode intersectionTypeDesc = (STIntersectionTypeDescriptorNode) typeDesc;
                newlhsType = mergeQualifiedNameWithTypeDesc(qualifiedName, intersectionTypeDesc.leftTypeDesc);
                return mergeTypesWithIntersection(newlhsType, intersectionTypeDesc.bitwiseAndToken,
                        intersectionTypeDesc.rightTypeDesc);
            case OPTIONAL_TYPE_DESC:
                STOptionalTypeDescriptorNode optionalType = (STOptionalTypeDescriptorNode) typeDesc;
                newMemberType = mergeQualifiedNameWithTypeDesc(qualifiedName, optionalType.typeDescriptor);
                return STNodeFactory.createOptionalTypeDescriptorNode(newMemberType, optionalType.questionMarkToken);
            default:
                return typeDesc;
        }
    }

    

    private List<STNode> getTypeDescList(List<STNode> ambiguousList) {
        List<STNode> typeDescList = new ArrayList<>();
        for (STNode item : ambiguousList) {
            typeDescList.add(getTypeDescFromExpr(item));
        }

        return typeDescList;
    }

    /**
     * Create a type-desc out of an expression.
     *
     * @param expression Expression
     * @return Type descriptor
     */
    private STNode getTypeDescFromExpr(STNode expression) {
        if (isDefiniteTypeDesc(expression.kind) || expression.kind == SyntaxKind.COMMA_TOKEN) {
            return expression;
        }
        
        switch (expression.kind) {
            case INDEXED_EXPRESSION:
                return parseArrayTypeDescriptorNode((STIndexedExpressionNode) expression);
            case NUMERIC_LITERAL:
            case BOOLEAN_LITERAL:
            case STRING_LITERAL:
            case NULL_LITERAL:
            case UNARY_EXPRESSION:
                return STNodeFactory.createSingletonTypeDescriptorNode(expression);
            case TYPE_REFERENCE_TYPE_DESC:
                
                return ((STTypeReferenceTypeDescNode) expression).typeRef;
            case BRACED_EXPRESSION:
                STBracedExpressionNode bracedExpr = (STBracedExpressionNode) expression;
                STNode typeDesc = getTypeDescFromExpr(bracedExpr.expression);
                return STNodeFactory.createParenthesisedTypeDescriptorNode(bracedExpr.openParen, typeDesc,
                        bracedExpr.closeParen);
            case NIL_LITERAL:
                STNilLiteralNode nilLiteral = (STNilLiteralNode) expression;
                return STNodeFactory.createNilTypeDescriptorNode(nilLiteral.openParenToken, nilLiteral.closeParenToken);
            case BRACKETED_LIST:
            case LIST_BP_OR_LIST_CONSTRUCTOR:
            case TUPLE_TYPE_DESC_OR_LIST_CONST:    
                STAmbiguousCollectionNode innerList = (STAmbiguousCollectionNode) expression;
                STNode memberTypeDescs = STNodeFactory.createNodeList(getTypeDescList(innerList.members));
                return STNodeFactory.createTupleTypeDescriptorNode(innerList.collectionStartToken, memberTypeDescs,
                        innerList.collectionEndToken);
            case BINARY_EXPRESSION:
                STBinaryExpressionNode binaryExpr = (STBinaryExpressionNode) expression;
                switch (binaryExpr.operator.kind) {
                    case PIPE_TOKEN:
                    case BITWISE_AND_TOKEN:
                        STNode lhsTypeDesc = getTypeDescFromExpr(binaryExpr.lhsExpr);
                        STNode rhsTypeDesc = getTypeDescFromExpr(binaryExpr.rhsExpr);
                        return mergeTypes(lhsTypeDesc, binaryExpr.operator, rhsTypeDesc);
                    default:
                        break;
                }
                return expression;
            case SIMPLE_NAME_REFERENCE:
            case QUALIFIED_NAME_REFERENCE:
                return expression;
            default:
                STNode simpleTypeDescIdentifier = SyntaxErrors.createMissingTokenWithDiagnostics(
                        SyntaxKind.IDENTIFIER_TOKEN, DiagnosticErrorCode.ERROR_MISSING_TYPE_DESC);
                simpleTypeDescIdentifier = SyntaxErrors.cloneWithTrailingInvalidNodeMinutiae(simpleTypeDescIdentifier, 
                        expression);
                return STNodeFactory.createSimpleNameReferenceNode(simpleTypeDescIdentifier);
        }
    }

    private List<STNode> getBindingPatternsList(List<STNode> ambibuousList, boolean isListBP) {
        List<STNode> bindingPatterns = new ArrayList<>();
        for (STNode item : ambibuousList) {
            if (isListBP && item.kind == SyntaxKind.FIELD_BINDING_PATTERN) {
                STNode identifier = SyntaxErrors.createMissingTokenWithDiagnostics(SyntaxKind.IDENTIFIER_TOKEN,
                        ParserRuleContext.BINDING_PATTERN_STARTING_IDENTIFIER);
                identifier = SyntaxErrors.cloneWithLeadingInvalidNodeMinutiae(identifier, item);
                bindingPatterns.add(createCaptureOrWildcardBP(identifier));
            } else {
                bindingPatterns.add(getBindingPattern(item));
            }
        }
        return bindingPatterns;
    }

    private STNode getBindingPattern(STNode ambiguousNode) {
        if (isEmpty(ambiguousNode)) {
            return ambiguousNode;
        }

        switch (ambiguousNode.kind) {
            case WILDCARD_BINDING_PATTERN:
            case CAPTURE_BINDING_PATTERN:
            case LIST_BINDING_PATTERN:
            case MAPPING_BINDING_PATTERN:
            case ERROR_BINDING_PATTERN:
            case REST_BINDING_PATTERN:
            case FIELD_BINDING_PATTERN:
            case NAMED_ARG_BINDING_PATTERN:
            case COMMA_TOKEN: 
                return ambiguousNode;
            case SIMPLE_NAME_REFERENCE:
                STNode varName = ((STSimpleNameReferenceNode) ambiguousNode).name;
                return createCaptureOrWildcardBP(varName);
            case QUALIFIED_NAME_REFERENCE:
                STQualifiedNameReferenceNode qualifiedName = (STQualifiedNameReferenceNode) ambiguousNode;
                STNode fieldName = STNodeFactory.createSimpleNameReferenceNode(qualifiedName.modulePrefix);
                return STNodeFactory.createFieldBindingPatternFullNode(fieldName, qualifiedName.colon,
                        createCaptureOrWildcardBP(qualifiedName.identifier));
            case BRACKETED_LIST:
            case LIST_BP_OR_LIST_CONSTRUCTOR:
                STAmbiguousCollectionNode innerList = (STAmbiguousCollectionNode) ambiguousNode;
                STNode memberBindingPatterns = STNodeFactory.createNodeList(
                        getBindingPatternsList(innerList.members, true));
                return STNodeFactory.createListBindingPatternNode(innerList.collectionStartToken, memberBindingPatterns,
                        innerList.collectionEndToken);
            case MAPPING_BP_OR_MAPPING_CONSTRUCTOR:
                innerList = (STAmbiguousCollectionNode) ambiguousNode;
                List<STNode> bindingPatterns = new ArrayList<>();
                for (int i = 0; i < innerList.members.size(); i++) {
                    STNode bp = getBindingPattern(innerList.members.get(i));
                    bindingPatterns.add(bp);
                    if (bp.kind == SyntaxKind.REST_BINDING_PATTERN) {
                        break;
                    }
                }
                memberBindingPatterns = STNodeFactory.createNodeList(bindingPatterns);
                return STNodeFactory.createMappingBindingPatternNode(innerList.collectionStartToken,
                        memberBindingPatterns, innerList.collectionEndToken);
            case SPECIFIC_FIELD:
                STSpecificFieldNode field = (STSpecificFieldNode) ambiguousNode;
                fieldName = STNodeFactory.createSimpleNameReferenceNode(field.fieldName);
                if (field.valueExpr == null) {
                    return STNodeFactory.createFieldBindingPatternVarnameNode(fieldName);
                }
                return STNodeFactory.createFieldBindingPatternFullNode(fieldName, field.colon,
                        getBindingPattern(field.valueExpr));
            case ERROR_CONSTRUCTOR:
                STErrorConstructorExpressionNode errorCons = (STErrorConstructorExpressionNode) ambiguousNode;
                STNode args = errorCons.arguments;
                int size = args.bucketCount();
                bindingPatterns = new ArrayList<>();
                for (int i = 0; i < size; i++) {
                    STNode arg = args.childInBucket(i);
                    bindingPatterns.add(getBindingPattern(arg));
                }

                STNode argListBindingPatterns = STNodeFactory.createNodeList(bindingPatterns);
                return STNodeFactory.createErrorBindingPatternNode(errorCons.errorKeyword, errorCons.typeReference,
                        errorCons.openParenToken, argListBindingPatterns, errorCons.closeParenToken);
            case POSITIONAL_ARG:
                STPositionalArgumentNode positionalArg = (STPositionalArgumentNode) ambiguousNode;
                return getBindingPattern(positionalArg.expression);
            case NAMED_ARG:
                STNamedArgumentNode namedArg = (STNamedArgumentNode) ambiguousNode;
                STNode bindingPatternArgName = ((STSimpleNameReferenceNode) namedArg.argumentName).name;
                return STNodeFactory.createNamedArgBindingPatternNode(bindingPatternArgName, namedArg.equalsToken,
                        getBindingPattern(namedArg.expression));
            case REST_ARG:
                STRestArgumentNode restArg = (STRestArgumentNode) ambiguousNode;
                return STNodeFactory.createRestBindingPatternNode(restArg.ellipsis, restArg.expression);
            default:
                STNode identifier = SyntaxErrors.createMissingToken(SyntaxKind.IDENTIFIER_TOKEN);
                identifier = SyntaxErrors.cloneWithLeadingInvalidNodeMinutiae(identifier, ambiguousNode, 
                        DiagnosticErrorCode.ERROR_INVALID_BINDING_PATTERN);
                return STNodeFactory.createCaptureBindingPatternNode(identifier);
        }
    }

    private List<STNode> getExpressionList(List<STNode> ambibuousList, boolean isMappingConstructor) {
        List<STNode> exprList = new ArrayList<STNode>();
        for (STNode item : ambibuousList) {
            exprList.add(getExpression(item, isMappingConstructor));
        }
        return exprList;
    }

    private STNode getExpression(STNode ambiguousNode) {
        return getExpression(ambiguousNode, false);
    }

    private STNode getExpression(STNode ambiguousNode, boolean isInMappingConstructor) {
        if (isEmpty(ambiguousNode) || 
                (isDefiniteExpr(ambiguousNode.kind) && ambiguousNode.kind != SyntaxKind.INDEXED_EXPRESSION) || 
                isDefiniteAction(ambiguousNode.kind) || ambiguousNode.kind == SyntaxKind.COMMA_TOKEN) {
            return ambiguousNode;
        }

        switch (ambiguousNode.kind) {
            case BRACKETED_LIST:
            case LIST_BP_OR_LIST_CONSTRUCTOR:
            case TUPLE_TYPE_DESC_OR_LIST_CONST:
                STAmbiguousCollectionNode innerList = (STAmbiguousCollectionNode) ambiguousNode;
                STNode memberExprs = STNodeFactory.createNodeList(getExpressionList(innerList.members, false));
                return STNodeFactory.createListConstructorExpressionNode(innerList.collectionStartToken, memberExprs,
                        innerList.collectionEndToken);
            case MAPPING_BP_OR_MAPPING_CONSTRUCTOR:
                innerList = (STAmbiguousCollectionNode) ambiguousNode;
                List<STNode> fieldList = new ArrayList<>();
                for (int i = 0; i < innerList.members.size(); i++) {
                    STNode field = innerList.members.get(i);
                    STNode fieldNode;
                    if (field.kind == SyntaxKind.QUALIFIED_NAME_REFERENCE) {
                        STQualifiedNameReferenceNode qualifiedNameRefNode = (STQualifiedNameReferenceNode) field;
                        STNode readOnlyKeyword = STNodeFactory.createEmptyNode();
                        STNode fieldName = qualifiedNameRefNode.modulePrefix;
                        STNode colon = qualifiedNameRefNode.colon;
                        STNode valueExpr = getExpression(qualifiedNameRefNode.identifier);
                        fieldNode = STNodeFactory.createSpecificFieldNode(readOnlyKeyword, fieldName, colon, valueExpr);
                    } else {
                        fieldNode = getExpression(field, true);
                    }

                    fieldList.add(fieldNode);
                }
                STNode fields = STNodeFactory.createNodeList(fieldList);
                return STNodeFactory.createMappingConstructorExpressionNode(innerList.collectionStartToken, fields,
                        innerList.collectionEndToken);
            case REST_BINDING_PATTERN:
                STRestBindingPatternNode restBindingPattern = (STRestBindingPatternNode) ambiguousNode;
                if (isInMappingConstructor) {
                    return STNodeFactory.createSpreadFieldNode(restBindingPattern.ellipsisToken,
                            restBindingPattern.variableName);
                }
                return STNodeFactory.createSpreadMemberNode(restBindingPattern.ellipsisToken,
                        restBindingPattern.variableName);
            case SPECIFIC_FIELD:
                
                STSpecificFieldNode field = (STSpecificFieldNode) ambiguousNode;
                return STNodeFactory.createSpecificFieldNode(field.readonlyKeyword, field.fieldName, field.colon,
                        getExpression(field.valueExpr));
            case ERROR_CONSTRUCTOR:
                STErrorConstructorExpressionNode errorCons = (STErrorConstructorExpressionNode) ambiguousNode;
                
                
                STNode errorArgs = getErrorArgList(errorCons.arguments);
                return STNodeFactory.createErrorConstructorExpressionNode(errorCons.errorKeyword,
                        errorCons.typeReference, errorCons.openParenToken, errorArgs, errorCons.closeParenToken);
            case IDENTIFIER_TOKEN:
                return STNodeFactory.createSimpleNameReferenceNode(ambiguousNode);
            case INDEXED_EXPRESSION:
                STIndexedExpressionNode indexedExpressionNode = (STIndexedExpressionNode) ambiguousNode;
                STNodeList keys = (STNodeList) indexedExpressionNode.keyExpression;
                
                if (keys.size() != 0) {
                    return ambiguousNode;
                }
                
                STNode lhsExpr = indexedExpressionNode.containerExpression;
                STNode openBracket = indexedExpressionNode.openBracket;
                STNode closeBracket = indexedExpressionNode.closeBracket;
                STNode missingVarRef = STNodeFactory
                        .createSimpleNameReferenceNode(SyntaxErrors.createMissingToken(SyntaxKind.IDENTIFIER_TOKEN));
                STNode keyExpr = STNodeFactory.createNodeList(missingVarRef);
                closeBracket = SyntaxErrors.addDiagnostic(closeBracket,
                        DiagnosticErrorCode.ERROR_MISSING_KEY_EXPR_IN_MEMBER_ACCESS_EXPR);
                return STNodeFactory.createIndexedExpressionNode(lhsExpr, openBracket, keyExpr, closeBracket);
            case SIMPLE_NAME_REFERENCE:
            case QUALIFIED_NAME_REFERENCE:
            case COMPUTED_NAME_FIELD:
            case SPREAD_FIELD:    
            case SPREAD_MEMBER:
                return ambiguousNode;
            default:
                STNode simpleVarRef = SyntaxErrors.createMissingTokenWithDiagnostics(SyntaxKind.IDENTIFIER_TOKEN,
                        DiagnosticErrorCode.ERROR_MISSING_EXPRESSION);
                simpleVarRef = SyntaxErrors.cloneWithTrailingInvalidNodeMinutiae(simpleVarRef, ambiguousNode);
                return STNodeFactory.createSimpleNameReferenceNode(simpleVarRef);
        }
    }

    private STNode getMappingField(STNode identifier, STNode colon, STNode bindingPatternOrExpr) {
        STNode simpleNameRef = STNodeFactory.createSimpleNameReferenceNode(identifier);
        switch (bindingPatternOrExpr.kind) {
            case LIST_BINDING_PATTERN:
            case MAPPING_BINDING_PATTERN:
                return STNodeFactory.createFieldBindingPatternFullNode(simpleNameRef, colon, bindingPatternOrExpr);
            case LIST_CONSTRUCTOR:
            case MAPPING_CONSTRUCTOR:
                STNode readonlyKeyword = STNodeFactory.createEmptyNode();
                return STNodeFactory
                        .createSpecificFieldNode(readonlyKeyword, identifier, colon, bindingPatternOrExpr);
            case LIST_BP_OR_LIST_CONSTRUCTOR:
            case MAPPING_BP_OR_MAPPING_CONSTRUCTOR:
            default:
                
                
                readonlyKeyword = STNodeFactory.createEmptyNode();
                return STNodeFactory.createSpecificFieldNode(readonlyKeyword, identifier, colon, bindingPatternOrExpr);
        }
    }

    

    private Solution recover(STToken nextToken, ParserRuleContext currentCtx) {
        if (isInsideABlock(nextToken)) {
            return this.recover(nextToken, currentCtx, true);
        } else {
            return this.recover(nextToken, currentCtx, false);
        }
    }

    private boolean isInsideABlock(STToken nextToken) {
        
        
        if (nextToken.kind != SyntaxKind.CLOSE_BRACE_TOKEN) {
            return false;
        }
        
        for (ParserRuleContext ctx : this.errorHandler.getContextStack()) {
            if (isBlockContext(ctx)) {
                
                return true;
            }
        }
        return false;
    }

    private boolean isBlockContext(ParserRuleContext ctx) {
        switch (ctx) {
            case FUNC_BODY_BLOCK:
            case CLASS_MEMBER:
            case OBJECT_CONSTRUCTOR_MEMBER:
            case OBJECT_TYPE_MEMBER:
            case BLOCK_STMT:
            case MATCH_BODY:
            case MAPPING_MATCH_PATTERN:
            case MAPPING_BINDING_PATTERN:
            case MAPPING_CONSTRUCTOR:
            case FORK_STMT:
            case MULTI_RECEIVE_WORKERS:
            case MULTI_WAIT_FIELDS:
            case MODULE_ENUM_DECLARATION:
                return true;
            default:
                return false;
        }
    }

    

    
    
}

Line commented on: if (isListBP && item.kind == SyntaxKind.FIELD_BINDING_PATTERN) {

Revised code:
private STNode parseIdentifierRhsInStmtStartingBrace(STNode readonlyKeyword) {
        STNode identifier = parseIdentifier(ParserRuleContext.VARIABLE_REF);
        switch (peek().kind) {
            case COMMA_TOKEN: 
                
                STNode colon = STNodeFactory.createEmptyNode();
                STNode value = STNodeFactory.createEmptyNode();
                return STNodeFactory.createSpecificFieldNode(readonlyKeyword, identifier, colon, value);
            case COLON_TOKEN:
                
                colon = parseColon();
                if (!isEmpty(readonlyKeyword)) {
                    value = parseExpression();
                    return STNodeFactory.createSpecificFieldNode(readonlyKeyword, identifier, colon, value);
                }

                switch (peek().kind) {
                    case OPEN_BRACKET_TOKEN: 
                        STNode bindingPatternOrExpr = parseListBindingPatternOrListConstructor();
                        return getMappingField(identifier, colon, bindingPatternOrExpr);
                    case OPEN_BRACE_TOKEN: 
                        bindingPatternOrExpr = parseMappingBindingPatterOrMappingConstructor();
                        return getMappingField(identifier, colon, bindingPatternOrExpr);
                    case ERROR_KEYWORD: 
                        bindingPatternOrExpr = parseErrorBindingPatternOrErrorConstructor();
                        return getMappingField(identifier, colon, bindingPatternOrExpr);
                    case IDENTIFIER_TOKEN: 
                        return parseQualifiedIdentifierRhsInStmtStartBrace(identifier, colon);
                    default:
                        STNode expr = parseExpression();
                        return getMappingField(identifier, colon, expr);
                }
            default:
                switchContext(ParserRuleContext.BLOCK_STMT);
                if (!isEmpty(readonlyKeyword)) {
                    startContext(ParserRuleContext.VAR_DECL_STMT);
                    STNode bindingPattern = STNodeFactory.createCaptureBindingPatternNode(identifier);
                    STNode typedBindingPattern =
                            STNodeFactory.createTypedBindingPatternNode(readonlyKeyword, bindingPattern);
                    STNode annots = STNodeFactory.createEmptyNodeList();
                    List<STNode> varDeclQualifiers = new ArrayList<>();
                    return parseVarDeclRhs(annots, varDeclQualifiers, typedBindingPattern, false);
                }

                startContext(ParserRuleContext.AMBIGUOUS_STMT);
                STNode qualifiedIdentifier = parseQualifiedIdentifier(identifier, false);
                STNode expr = parseTypedBindingPatternOrExprRhs(qualifiedIdentifier, true);
                STNode annots = STNodeFactory.createEmptyNodeList();
                return parseStmtStartsWithTypedBPOrExprRhs(annots, expr);
        }
    }

    /**
     * Parse the rhs components of "<code>{ identifier : identifier</code>",
     * at the start of a statement. i.e: "{foo:bar".
     *
     * @return Parsed node
     */
    private STNode parseQualifiedIdentifierRhsInStmtStartBrace(STNode identifier, STNode colon) {
        STNode secondIdentifier = parseIdentifier(ParserRuleContext.VARIABLE_REF);
        STNode secondNameRef = STNodeFactory.createSimpleNameReferenceNode(secondIdentifier);
        if (isWildcardBP(secondIdentifier)) {
            
            STNode wildcardBP = getWildcardBindingPattern(secondIdentifier);
            STNode nameRef = STNodeFactory.createSimpleNameReferenceNode(identifier);
            return STNodeFactory.createFieldBindingPatternFullNode(nameRef, colon, wildcardBP);
        }

        
        STNode qualifiedNameRef = createQualifiedNameReferenceNode(identifier, colon, secondIdentifier);
        switch (peek().kind) {
            case COMMA_TOKEN:
                
                
                
                return STNodeFactory.createSpecificFieldNode(STNodeFactory.createEmptyNode(), identifier, colon,
                        secondNameRef);
            case OPEN_BRACE_TOKEN: 
            case IDENTIFIER_TOKEN: 
                switchContext(ParserRuleContext.BLOCK_STMT);
                startContext(ParserRuleContext.VAR_DECL_STMT);
                List<STNode> varDeclQualifiers = new ArrayList<>();
                STNode typeBindingPattern =
                        parseTypedBindingPatternTypeRhs(qualifiedNameRef, ParserRuleContext.VAR_DECL_STMT);
                STNode annots = STNodeFactory.createEmptyNodeList();
                return parseVarDeclRhs(annots, varDeclQualifiers, typeBindingPattern, false);
            case OPEN_BRACKET_TOKEN:
                
                
                return parseMemberRhsInStmtStartWithBrace(identifier, colon, secondIdentifier, secondNameRef);
            case QUESTION_MARK_TOKEN:
                
                STNode typeDesc = parseComplexTypeDescriptor(qualifiedNameRef,
                        ParserRuleContext.TYPE_DESC_IN_TYPE_BINDING_PATTERN, true);
                varDeclQualifiers = new ArrayList<>();
                typeBindingPattern = parseTypedBindingPatternTypeRhs(typeDesc, ParserRuleContext.VAR_DECL_STMT);
                annots = STNodeFactory.createEmptyNodeList();
                return parseVarDeclRhs(annots, varDeclQualifiers, typeBindingPattern, false);
            case EQUAL_TOKEN:
            case SEMICOLON_TOKEN:
                
                return parseStatementStartWithExprRhs(qualifiedNameRef);
            case PIPE_TOKEN:
            case BITWISE_AND_TOKEN:
            default:
                return parseMemberWithExprInRhs(identifier, colon, secondIdentifier, secondNameRef);
        }
    }

    private SyntaxKind getBracedListType(STNode member) {
        switch (member.kind) {
            case FIELD_BINDING_PATTERN:
            case CAPTURE_BINDING_PATTERN:
            case LIST_BINDING_PATTERN:
            case MAPPING_BINDING_PATTERN:
            case WILDCARD_BINDING_PATTERN:
                return SyntaxKind.MAPPING_BINDING_PATTERN;
            case SPECIFIC_FIELD:
                STNode expr = ((STSpecificFieldNode) member).valueExpr;
                if (expr == null) {
                    return SyntaxKind.MAPPING_BP_OR_MAPPING_CONSTRUCTOR;
                }

                
                switch (expr.kind) {
                    case SIMPLE_NAME_REFERENCE:
                    case LIST_BP_OR_LIST_CONSTRUCTOR:
                    case MAPPING_BP_OR_MAPPING_CONSTRUCTOR:
                        return SyntaxKind.MAPPING_BP_OR_MAPPING_CONSTRUCTOR;
                    case ERROR_BINDING_PATTERN:
                        return SyntaxKind.MAPPING_BINDING_PATTERN;
                    case ERROR_CONSTRUCTOR:
                        if (isPossibleErrorBindingPattern((STErrorConstructorExpressionNode) expr)) {
                            return SyntaxKind.MAPPING_BP_OR_MAPPING_CONSTRUCTOR;
                        }
                        return SyntaxKind.MAPPING_CONSTRUCTOR;
                    default:
                        return SyntaxKind.MAPPING_CONSTRUCTOR;
                }
            case SPREAD_FIELD:
            case COMPUTED_NAME_FIELD:
                return SyntaxKind.MAPPING_CONSTRUCTOR;
            case SIMPLE_NAME_REFERENCE:
            case QUALIFIED_NAME_REFERENCE:
            case LIST_BP_OR_LIST_CONSTRUCTOR:
            case MAPPING_BP_OR_MAPPING_CONSTRUCTOR:
            case REST_BINDING_PATTERN:
                return SyntaxKind.MAPPING_BP_OR_MAPPING_CONSTRUCTOR;
            case LIST:
                return SyntaxKind.BLOCK_STATEMENT;
            default:
                return SyntaxKind.NONE;
        }
    }

    /**
     * Parse mapping binding pattern or mapping constructor.
     *
     * @return Parsed node
     */
    private STNode parseMappingBindingPatterOrMappingConstructor() {
        startContext(ParserRuleContext.MAPPING_BP_OR_MAPPING_CONSTRUCTOR);
        STNode openBrace = parseOpenBrace();
        List<STNode> memberList = new ArrayList<>();
        return parseMappingBindingPatternOrMappingConstructor(openBrace, memberList);
    }

    private boolean isBracedListEnd(SyntaxKind nextTokenKind) {
        switch (nextTokenKind) {
            case EOF_TOKEN:
            case CLOSE_BRACE_TOKEN:
                return true;
            default:
                return false;
        }
    }

    private STNode parseMappingBindingPatternOrMappingConstructor(STNode openBrace, List<STNode> memberList) {
        STToken nextToken = peek();
        while (!isBracedListEnd(nextToken.kind)) {
            
            STNode member = parseMappingBindingPatterOrMappingConstructorMember();
            SyntaxKind currentNodeType = getTypeOfMappingBPOrMappingCons(member);

            switch (currentNodeType) {
                case MAPPING_CONSTRUCTOR:
                    
                    
                    return parseAsMappingConstructor(openBrace, memberList, member);
                case MAPPING_BINDING_PATTERN:
                    
                    
                    return parseAsMappingBindingPattern(openBrace, memberList, member);
                case MAPPING_BP_OR_MAPPING_CONSTRUCTOR:
                default:
                    memberList.add(member);
                    break;
            }

            
            STNode memberEnd = parseMappingFieldEnd();
            if (memberEnd == null) {
                break;
            }
            memberList.add(memberEnd);
            nextToken = peek();
        }

        
        STNode closeBrace = parseCloseBrace();
        return parseMappingBindingPatternOrMappingConstructor(openBrace, memberList, closeBrace);
    }

    private STNode parseMappingBindingPatterOrMappingConstructorMember() {
        switch (peek().kind) {
            case IDENTIFIER_TOKEN:
                STNode key = parseIdentifier(ParserRuleContext.MAPPING_FIELD_NAME);
                return parseMappingFieldRhs(key);
            case STRING_LITERAL_TOKEN:
                STNode readonlyKeyword = STNodeFactory.createEmptyNode();
                key = parseStringLiteral();
                STNode colon = parseColon();
                STNode valueExpr = parseExpression();
                return STNodeFactory.createSpecificFieldNode(readonlyKeyword, key, colon, valueExpr);
            case OPEN_BRACKET_TOKEN:
                return parseComputedField();
            case ELLIPSIS_TOKEN:
                STNode ellipsis = parseEllipsis();
                STNode expr = parseExpression();
                if (expr.kind == SyntaxKind.SIMPLE_NAME_REFERENCE) {
                    return STNodeFactory.createRestBindingPatternNode(ellipsis, expr);
                }
                return STNodeFactory.createSpreadFieldNode(ellipsis, expr);
            default:
                recover(peek(), ParserRuleContext.MAPPING_BP_OR_MAPPING_CONSTRUCTOR_MEMBER);
                return parseMappingBindingPatterOrMappingConstructorMember();
        }
    }

    private STNode parseMappingFieldRhs(STNode key) {
        STNode colon;
        STNode valueExpr;
        switch (peek().kind) {
            case COLON_TOKEN:
                colon = parseColon();
                return parseMappingFieldValue(key, colon);
            case COMMA_TOKEN:
            case CLOSE_BRACE_TOKEN:
                STNode readonlyKeyword = STNodeFactory.createEmptyNode();
                colon = STNodeFactory.createEmptyNode();
                valueExpr = STNodeFactory.createEmptyNode();
                return STNodeFactory.createSpecificFieldNode(readonlyKeyword, key, colon, valueExpr);
            default:
                STToken token = peek();
                recover(token, ParserRuleContext.FIELD_BINDING_PATTERN_END);
                readonlyKeyword = STNodeFactory.createEmptyNode();
                return parseSpecificFieldRhs(readonlyKeyword, key);
        }
    }

    private STNode parseMappingFieldValue(STNode key, STNode colon) {
        
        STNode expr;
        switch (peek().kind) {
            case IDENTIFIER_TOKEN:
                expr = parseExpression();
                break;
            case OPEN_BRACKET_TOKEN: 
                expr = parseListBindingPatternOrListConstructor();
                break;
            case OPEN_BRACE_TOKEN: 
                expr = parseMappingBindingPatterOrMappingConstructor();
                break;
            default:
                expr = parseExpression();
                break;
        }

        if (isBindingPattern(expr.kind)) {
            key = STNodeFactory.createSimpleNameReferenceNode(key);
            return STNodeFactory.createFieldBindingPatternFullNode(key, colon, expr);
        }

        STNode readonlyKeyword = STNodeFactory.createEmptyNode();
        return STNodeFactory.createSpecificFieldNode(readonlyKeyword, key, colon, expr);
    }

    private boolean isBindingPattern(SyntaxKind kind) {
        switch (kind) {
            case FIELD_BINDING_PATTERN:
            case MAPPING_BINDING_PATTERN:
            case CAPTURE_BINDING_PATTERN:
            case LIST_BINDING_PATTERN:
            case WILDCARD_BINDING_PATTERN:
                return true;
            default:
                return false;
        }
    }

    private SyntaxKind getTypeOfMappingBPOrMappingCons(STNode memberNode) {
        switch (memberNode.kind) {
            case FIELD_BINDING_PATTERN:
            case MAPPING_BINDING_PATTERN:
            case CAPTURE_BINDING_PATTERN:
            case LIST_BINDING_PATTERN:
            case WILDCARD_BINDING_PATTERN:
                return SyntaxKind.MAPPING_BINDING_PATTERN;
            case SPECIFIC_FIELD:
                STNode expr = ((STSpecificFieldNode) memberNode).valueExpr;
                
                if (expr == null || expr.kind == SyntaxKind.SIMPLE_NAME_REFERENCE ||
                        expr.kind == SyntaxKind.LIST_BP_OR_LIST_CONSTRUCTOR ||
                        expr.kind == SyntaxKind.MAPPING_BP_OR_MAPPING_CONSTRUCTOR) {
                    return SyntaxKind.MAPPING_BP_OR_MAPPING_CONSTRUCTOR;
                }
                return SyntaxKind.MAPPING_CONSTRUCTOR;
            case SPREAD_FIELD:
            case COMPUTED_NAME_FIELD:
                return SyntaxKind.MAPPING_CONSTRUCTOR;
            case MAPPING_BP_OR_MAPPING_CONSTRUCTOR:
            case SIMPLE_NAME_REFERENCE:
            case QUALIFIED_NAME_REFERENCE:
            case LIST_BP_OR_LIST_CONSTRUCTOR:
            case REST_BINDING_PATTERN: 
            default:
                return SyntaxKind.MAPPING_BP_OR_MAPPING_CONSTRUCTOR;
        }
    }

    private STNode parseMappingBindingPatternOrMappingConstructor(STNode openBrace, List<STNode> members,
                                                                  STNode closeBrace) {
        endContext();
        return new STAmbiguousCollectionNode(SyntaxKind.MAPPING_BP_OR_MAPPING_CONSTRUCTOR, openBrace, members,
                closeBrace);
    }

    private STNode parseAsMappingBindingPattern(STNode openBrace, List<STNode> members, STNode member) {
        members.add(member);
        members = getBindingPatternsList(members, false);
        
        switchContext(ParserRuleContext.MAPPING_BINDING_PATTERN);
        return parseMappingBindingPattern(openBrace, members, member);
    }

    /**
     * Parse list binding pattern or list constructor.
     *
     * @return Parsed node
     */
    private STNode parseListBindingPatternOrListConstructor() {
        startContext(ParserRuleContext.BRACKETED_LIST);
        STNode openBracket = parseOpenBracket();
        List<STNode> memberList = new ArrayList<>();
        return parseListBindingPatternOrListConstructor(openBracket, memberList, false);
    }

    private STNode parseListBindingPatternOrListConstructor(STNode openBracket, List<STNode> memberList,
                                                            boolean isRoot) {
        
        STToken nextToken = peek();
        while (!isBracketedListEnd(nextToken.kind)) {
            
            STNode member = parseListBindingPatternOrListConstructorMember();
            SyntaxKind currentNodeType = getParsingNodeTypeOfListBPOrListCons(member);

            switch (currentNodeType) {
                case LIST_CONSTRUCTOR:
                    
                    
                    return parseAsListConstructor(openBracket, memberList, member, isRoot);
                case LIST_BINDING_PATTERN:
                    
                    
                    return parseAsListBindingPattern(openBracket, memberList, member, isRoot);
                case LIST_BP_OR_LIST_CONSTRUCTOR:
                default:
                    memberList.add(member);
                    break;
            }

            
            STNode memberEnd = parseBracketedListMemberEnd();
            if (memberEnd == null) {
                break;
            }
            memberList.add(memberEnd);
            nextToken = peek();
        }

        
        STNode closeBracket = parseCloseBracket();
        return parseListBindingPatternOrListConstructor(openBracket, memberList, closeBracket, isRoot);
    }

    private STNode parseListBindingPatternOrListConstructorMember() {
        STToken nextToken = peek();
        switch (nextToken.kind) {
            case OPEN_BRACKET_TOKEN:
                
                return parseListBindingPatternOrListConstructor();
            case IDENTIFIER_TOKEN:
                STNode identifier = parseQualifiedIdentifier(ParserRuleContext.VARIABLE_REF);
                if (isWildcardBP(identifier)) {
                    return getWildcardBindingPattern(identifier);
                }
                return parseExpressionRhs(DEFAULT_OP_PRECEDENCE, identifier, false, false);
            case OPEN_BRACE_TOKEN:
                return parseMappingBindingPatterOrMappingConstructor();
            case ELLIPSIS_TOKEN:
                return parseRestBindingOrSpreadMember();
            default:
                if (isValidExpressionStart(nextToken.kind, 1)) {
                    return parseExpression();
                }

                recover(peek(), ParserRuleContext.LIST_BP_OR_LIST_CONSTRUCTOR_MEMBER);
                return parseListBindingPatternOrListConstructorMember();
        }
    }

    private SyntaxKind getParsingNodeTypeOfListBPOrListCons(STNode memberNode) {
        switch (memberNode.kind) {
            case CAPTURE_BINDING_PATTERN:
            case LIST_BINDING_PATTERN:
            case MAPPING_BINDING_PATTERN:
            case WILDCARD_BINDING_PATTERN:
                return SyntaxKind.LIST_BINDING_PATTERN;
            case SIMPLE_NAME_REFERENCE: 
            case LIST_BP_OR_LIST_CONSTRUCTOR: 
            case MAPPING_BP_OR_MAPPING_CONSTRUCTOR:
            case REST_BINDING_PATTERN:
                return SyntaxKind.LIST_BP_OR_LIST_CONSTRUCTOR;
            case SPREAD_MEMBER:
            default:
                return SyntaxKind.LIST_CONSTRUCTOR;
        }
    }

    private STNode parseAsListConstructor(STNode openBracket, List<STNode> memberList, STNode member, boolean isRoot) {
        memberList.add(member);
        memberList = getExpressionList(memberList, false);

        switchContext(ParserRuleContext.LIST_CONSTRUCTOR);
        STNode listMembers = parseListMembers(memberList);
        STNode closeBracket = parseCloseBracket();
        STNode listConstructor =
                STNodeFactory.createListConstructorExpressionNode(openBracket, listMembers, closeBracket);
        endContext();

        STNode expr = parseExpressionRhs(DEFAULT_OP_PRECEDENCE, listConstructor, false, true);
        if (!isRoot) {
            return expr;
        }

        return parseStatementStartWithExprRhs(expr);

    }

    private STNode parseListBindingPatternOrListConstructor(STNode openBracket, List<STNode> members,
                                                            STNode closeBracket, boolean isRoot) {
        STNode lbpOrListCons;
        switch (peek().kind) {
            case COMMA_TOKEN: 
            case CLOSE_BRACE_TOKEN: 
            case CLOSE_BRACKET_TOKEN:
                if (!isRoot) {
                    endContext();
                    return new STAmbiguousCollectionNode(SyntaxKind.LIST_BP_OR_LIST_CONSTRUCTOR, openBracket, members,
                            closeBracket);
                }
                
            default:
                SyntaxKind nextTokenKind = peek().kind;
                if (isValidExprRhsStart(nextTokenKind, closeBracket.kind) || 
                        nextTokenKind == SyntaxKind.SEMICOLON_TOKEN && isRoot) { 
                    members = getExpressionList(members, false);
                    STNode memberExpressions = STNodeFactory.createNodeList(members);
                    lbpOrListCons = STNodeFactory.createListConstructorExpressionNode(openBracket, memberExpressions,
                            closeBracket);
                    lbpOrListCons = parseExpressionRhs(DEFAULT_OP_PRECEDENCE, lbpOrListCons, false, true);
                    break;
                }

                
                members = getBindingPatternsList(members, true);
                STNode bindingPatternsNode = STNodeFactory.createNodeList(members);
                lbpOrListCons = STNodeFactory.createListBindingPatternNode(openBracket, bindingPatternsNode,
                        closeBracket);
                break;
        }

        endContext();

        if (!isRoot) {
            return lbpOrListCons;
        }
        
        if (lbpOrListCons.kind == SyntaxKind.LIST_BINDING_PATTERN) {
            return parseAssignmentStmtRhs(lbpOrListCons);
        } else {
            return parseStatementStartWithExprRhs(lbpOrListCons);
        }
    }

    private STNode parseMemberRhsInStmtStartWithBrace(STNode identifier, STNode colon, STNode secondIdentifier,
                                                      STNode secondNameRef) {
        STNode typedBPOrExpr =
                parseTypedBindingPatternOrMemberAccess(secondNameRef, false, true, ParserRuleContext.AMBIGUOUS_STMT);
        if (isExpression(typedBPOrExpr.kind)) {
            return parseMemberWithExprInRhs(identifier, colon, secondIdentifier, typedBPOrExpr);
        }

        switchContext(ParserRuleContext.BLOCK_STMT);
        startContext(ParserRuleContext.VAR_DECL_STMT);
        List<STNode> varDeclQualifiers = new ArrayList<>();
        STNode annots = STNodeFactory.createEmptyNodeList();

        
        
        
        STTypedBindingPatternNode typedBP = (STTypedBindingPatternNode) typedBPOrExpr;
        STNode qualifiedNameRef = createQualifiedNameReferenceNode(identifier, colon, secondIdentifier);
        STNode newTypeDesc = mergeQualifiedNameWithTypeDesc(qualifiedNameRef, typedBP.typeDescriptor);

        STNode newTypeBP = STNodeFactory.createTypedBindingPatternNode(newTypeDesc, typedBP.bindingPattern);
        STNode publicQualifier = STNodeFactory.createEmptyNode();
        return parseVarDeclRhs(annots, publicQualifier, varDeclQualifiers, newTypeBP, false);
    }

    /**
     * Parse a member that starts with "foo:bar[", in a statement starting with a brace.
     *
     * @param identifier       First identifier of the statement
     * @param colon            Colon that follows the first identifier
     * @param secondIdentifier Identifier that follows the colon
     * @param memberAccessExpr Member access expression
     * @return Parsed node
     */
    private STNode parseMemberWithExprInRhs(STNode identifier, STNode colon, STNode secondIdentifier,
                                            STNode memberAccessExpr) {
        STNode expr = parseExpressionRhs(DEFAULT_OP_PRECEDENCE, memberAccessExpr, false, true);
        switch (peek().kind) {
            case COMMA_TOKEN:
            case CLOSE_BRACE_TOKEN:
                switchContext(ParserRuleContext.EXPRESSION_STATEMENT);
                STNode readonlyKeyword = STNodeFactory.createEmptyNode();
                return STNodeFactory.createSpecificFieldNode(readonlyKeyword, identifier, colon, expr);
            case EQUAL_TOKEN:
            case SEMICOLON_TOKEN:
            default:
                switchContext(ParserRuleContext.BLOCK_STMT);
                startContext(ParserRuleContext.EXPRESSION_STATEMENT);
                
                STNode qualifiedName = createQualifiedNameReferenceNode(identifier, colon, secondIdentifier);
                STNode updatedExpr = mergeQualifiedNameWithExpr(qualifiedName, expr);
                return parseStatementStartWithExprRhs(updatedExpr);
        }
    }

    private STNode parseInferredTypeDescDefaultOrExpression() {
        STToken nextToken = peek();
        SyntaxKind nextTokenKind = nextToken.kind;

        if (nextTokenKind == SyntaxKind.LT_TOKEN) {
            return parseInferredTypeDescDefaultOrExpression(consume());
        }

        if (isValidExprStart(nextTokenKind)) {
            return parseExpression();
        }

         recover(nextToken, ParserRuleContext.EXPR_START_OR_INFERRED_TYPEDESC_DEFAULT_START);
         return parseInferredTypeDescDefaultOrExpression();
    }

    private STNode parseInferredTypeDescDefaultOrExpression(STToken ltToken) {
        STToken nextToken = peek();

        if (nextToken.kind == SyntaxKind.GT_TOKEN) {
            return STNodeFactory.createInferredTypedescDefaultNode(ltToken, consume());
        }

        if (isTypeStartingToken(nextToken.kind) || nextToken.kind == SyntaxKind.AT_TOKEN) {
            startContext(ParserRuleContext.TYPE_CAST);
            STNode expr = parseTypeCastExpr(ltToken, true, false, false);
            return parseExpressionRhs(DEFAULT_OP_PRECEDENCE, expr, true, false);
        }

        recover(nextToken, ParserRuleContext.TYPE_CAST_PARAM_START_OR_INFERRED_TYPEDESC_DEFAULT_END);
        return parseInferredTypeDescDefaultOrExpression(ltToken);
    }

    /**
     * Replace the first identifier of an expression, with a given qualified-identifier.
     * Only expressions that can start with "bar[..]" can reach here.
     *
     * @param qualifiedName Qualified identifier to replace simple identifier
     * @param exprOrAction  Expression or action     * @return Updated expression
     */
    private STNode mergeQualifiedNameWithExpr(STNode qualifiedName, STNode exprOrAction) {
        switch (exprOrAction.kind) {
            case SIMPLE_NAME_REFERENCE:
                return qualifiedName;
            case BINARY_EXPRESSION:
                STBinaryExpressionNode binaryExpr = (STBinaryExpressionNode) exprOrAction;
                STNode newLhsExpr = mergeQualifiedNameWithExpr(qualifiedName, binaryExpr.lhsExpr);
                return STNodeFactory.createBinaryExpressionNode(binaryExpr.kind, newLhsExpr, binaryExpr.operator,
                        binaryExpr.rhsExpr);
            case FIELD_ACCESS:
                STFieldAccessExpressionNode fieldAccess = (STFieldAccessExpressionNode) exprOrAction;
                newLhsExpr = mergeQualifiedNameWithExpr(qualifiedName, fieldAccess.expression);
                return STNodeFactory.createFieldAccessExpressionNode(newLhsExpr, fieldAccess.dotToken,
                        fieldAccess.fieldName);
            case INDEXED_EXPRESSION:
                STIndexedExpressionNode memberAccess = (STIndexedExpressionNode) exprOrAction;
                newLhsExpr = mergeQualifiedNameWithExpr(qualifiedName, memberAccess.containerExpression);
                return STNodeFactory.createIndexedExpressionNode(newLhsExpr, memberAccess.openBracket,
                        memberAccess.keyExpression, memberAccess.closeBracket);
            case TYPE_TEST_EXPRESSION:
                STTypeTestExpressionNode typeTest = (STTypeTestExpressionNode) exprOrAction;
                newLhsExpr = mergeQualifiedNameWithExpr(qualifiedName, typeTest.expression);
                return STNodeFactory.createTypeTestExpressionNode(newLhsExpr, typeTest.isKeyword,
                        typeTest.typeDescriptor);
            case ANNOT_ACCESS:
                STAnnotAccessExpressionNode annotAccess = (STAnnotAccessExpressionNode) exprOrAction;
                newLhsExpr = mergeQualifiedNameWithExpr(qualifiedName, annotAccess.expression);
                return STNodeFactory.createFieldAccessExpressionNode(newLhsExpr, annotAccess.annotChainingToken,
                        annotAccess.annotTagReference);
            case OPTIONAL_FIELD_ACCESS:
                STOptionalFieldAccessExpressionNode optionalFieldAccess =
                        (STOptionalFieldAccessExpressionNode) exprOrAction;
                newLhsExpr = mergeQualifiedNameWithExpr(qualifiedName, optionalFieldAccess.expression);
                return STNodeFactory.createFieldAccessExpressionNode(newLhsExpr,
                        optionalFieldAccess.optionalChainingToken, optionalFieldAccess.fieldName);
            case CONDITIONAL_EXPRESSION:
                STConditionalExpressionNode conditionalExpr = (STConditionalExpressionNode) exprOrAction;
                newLhsExpr = mergeQualifiedNameWithExpr(qualifiedName, conditionalExpr.lhsExpression);
                return STNodeFactory.createConditionalExpressionNode(newLhsExpr, conditionalExpr.questionMarkToken,
                        conditionalExpr.middleExpression, conditionalExpr.colonToken, conditionalExpr.endExpression);
            case REMOTE_METHOD_CALL_ACTION:
                STRemoteMethodCallActionNode remoteCall = (STRemoteMethodCallActionNode) exprOrAction;
                newLhsExpr = mergeQualifiedNameWithExpr(qualifiedName, remoteCall.expression);
                return STNodeFactory.createRemoteMethodCallActionNode(newLhsExpr, remoteCall.rightArrowToken,
                        remoteCall.methodName, remoteCall.openParenToken, remoteCall.arguments,
                        remoteCall.closeParenToken);
            case ASYNC_SEND_ACTION:
                STAsyncSendActionNode asyncSend = (STAsyncSendActionNode) exprOrAction;
                newLhsExpr = mergeQualifiedNameWithExpr(qualifiedName, asyncSend.expression);
                return STNodeFactory.createAsyncSendActionNode(newLhsExpr, asyncSend.rightArrowToken,
                        asyncSend.peerWorker);
            case SYNC_SEND_ACTION:
                STSyncSendActionNode syncSend = (STSyncSendActionNode) exprOrAction;
                newLhsExpr = mergeQualifiedNameWithExpr(qualifiedName, syncSend.expression);
                return STNodeFactory.createAsyncSendActionNode(newLhsExpr, syncSend.syncSendToken, syncSend.peerWorker);
            case FUNCTION_CALL:
                STFunctionCallExpressionNode funcCall = (STFunctionCallExpressionNode) exprOrAction;
                return STNodeFactory.createFunctionCallExpressionNode(qualifiedName, funcCall.openParenToken,
                        funcCall.arguments, funcCall.closeParenToken);
            default:
                return exprOrAction;
        }
    }

    private STNode mergeQualifiedNameWithTypeDesc(STNode qualifiedName, STNode typeDesc) {
        switch (typeDesc.kind) {
            case SIMPLE_NAME_REFERENCE:
                return qualifiedName;
            case ARRAY_TYPE_DESC:
                STArrayTypeDescriptorNode arrayTypeDesc = (STArrayTypeDescriptorNode) typeDesc;
                STNode newMemberType = mergeQualifiedNameWithTypeDesc(qualifiedName, arrayTypeDesc.memberTypeDesc);
                return STNodeFactory.createArrayTypeDescriptorNode(newMemberType, arrayTypeDesc.dimensions);
            case UNION_TYPE_DESC:
                STUnionTypeDescriptorNode unionTypeDesc = (STUnionTypeDescriptorNode) typeDesc;
                STNode newlhsType = mergeQualifiedNameWithTypeDesc(qualifiedName, unionTypeDesc.leftTypeDesc);
                return mergeTypesWithUnion(newlhsType, unionTypeDesc.pipeToken, unionTypeDesc.rightTypeDesc);
            case INTERSECTION_TYPE_DESC:
                STIntersectionTypeDescriptorNode intersectionTypeDesc = (STIntersectionTypeDescriptorNode) typeDesc;
                newlhsType = mergeQualifiedNameWithTypeDesc(qualifiedName, intersectionTypeDesc.leftTypeDesc);
                return mergeTypesWithIntersection(newlhsType, intersectionTypeDesc.bitwiseAndToken,
                        intersectionTypeDesc.rightTypeDesc);
            case OPTIONAL_TYPE_DESC:
                STOptionalTypeDescriptorNode optionalType = (STOptionalTypeDescriptorNode) typeDesc;
                newMemberType = mergeQualifiedNameWithTypeDesc(qualifiedName, optionalType.typeDescriptor);
                return STNodeFactory.createOptionalTypeDescriptorNode(newMemberType, optionalType.questionMarkToken);
            default:
                return typeDesc;
        }
    }

    

    private List<STNode> getTypeDescList(List<STNode> ambiguousList) {
        List<STNode> typeDescList = new ArrayList<>();
        for (STNode item : ambiguousList) {
            typeDescList.add(getTypeDescFromExpr(item));
        }

        return typeDescList;
    }

    /**
     * Create a type-desc out of an expression.
     *
     * @param expression Expression
     * @return Type descriptor
     */
    private STNode getTypeDescFromExpr(STNode expression) {
        if (isDefiniteTypeDesc(expression.kind) || expression.kind == SyntaxKind.COMMA_TOKEN) {
            return expression;
        }
        
        switch (expression.kind) {
            case INDEXED_EXPRESSION:
                return parseArrayTypeDescriptorNode((STIndexedExpressionNode) expression);
            case NUMERIC_LITERAL:
            case BOOLEAN_LITERAL:
            case STRING_LITERAL:
            case NULL_LITERAL:
            case UNARY_EXPRESSION:
                return STNodeFactory.createSingletonTypeDescriptorNode(expression);
            case TYPE_REFERENCE_TYPE_DESC:
                
                return ((STTypeReferenceTypeDescNode) expression).typeRef;
            case BRACED_EXPRESSION:
                STBracedExpressionNode bracedExpr = (STBracedExpressionNode) expression;
                STNode typeDesc = getTypeDescFromExpr(bracedExpr.expression);
                return STNodeFactory.createParenthesisedTypeDescriptorNode(bracedExpr.openParen, typeDesc,
                        bracedExpr.closeParen);
            case NIL_LITERAL:
                STNilLiteralNode nilLiteral = (STNilLiteralNode) expression;
                return STNodeFactory.createNilTypeDescriptorNode(nilLiteral.openParenToken, nilLiteral.closeParenToken);
            case BRACKETED_LIST:
            case LIST_BP_OR_LIST_CONSTRUCTOR:
            case TUPLE_TYPE_DESC_OR_LIST_CONST:    
                STAmbiguousCollectionNode innerList = (STAmbiguousCollectionNode) expression;
                STNode memberTypeDescs = STNodeFactory.createNodeList(getTypeDescList(innerList.members));
                return STNodeFactory.createTupleTypeDescriptorNode(innerList.collectionStartToken, memberTypeDescs,
                        innerList.collectionEndToken);
            case BINARY_EXPRESSION:
                STBinaryExpressionNode binaryExpr = (STBinaryExpressionNode) expression;
                switch (binaryExpr.operator.kind) {
                    case PIPE_TOKEN:
                    case BITWISE_AND_TOKEN:
                        STNode lhsTypeDesc = getTypeDescFromExpr(binaryExpr.lhsExpr);
                        STNode rhsTypeDesc = getTypeDescFromExpr(binaryExpr.rhsExpr);
                        return mergeTypes(lhsTypeDesc, binaryExpr.operator, rhsTypeDesc);
                    default:
                        break;
                }
                return expression;
            case SIMPLE_NAME_REFERENCE:
            case QUALIFIED_NAME_REFERENCE:
                return expression;
            default:
                STNode simpleTypeDescIdentifier = SyntaxErrors.createMissingTokenWithDiagnostics(
                        SyntaxKind.IDENTIFIER_TOKEN, DiagnosticErrorCode.ERROR_MISSING_TYPE_DESC);
                simpleTypeDescIdentifier = SyntaxErrors.cloneWithTrailingInvalidNodeMinutiae(simpleTypeDescIdentifier, 
                        expression);
                return STNodeFactory.createSimpleNameReferenceNode(simpleTypeDescIdentifier);
        }
    }

    private List<STNode> getBindingPatternsList(List<STNode> ambibuousList, boolean isListBP) {
        List<STNode> bindingPatterns = new ArrayList<>();
        for (STNode item : ambibuousList) {
            bindingPatterns.add(getBindingPattern(item, isListBP));
        }
        return bindingPatterns;
    }

    private STNode getBindingPattern(STNode ambiguousNode, boolean isListBP) {
        DiagnosticCode errorCode = DiagnosticErrorCode.ERROR_INVALID_BINDING_PATTERN;

        if (isEmpty(ambiguousNode)) {
            return ambiguousNode;
        }

        switch (ambiguousNode.kind) {
            case WILDCARD_BINDING_PATTERN:
            case CAPTURE_BINDING_PATTERN:
            case LIST_BINDING_PATTERN:
            case MAPPING_BINDING_PATTERN:
            case ERROR_BINDING_PATTERN:
            case REST_BINDING_PATTERN:
            case FIELD_BINDING_PATTERN:
            case NAMED_ARG_BINDING_PATTERN:
            case COMMA_TOKEN: 
                return ambiguousNode;
            case SIMPLE_NAME_REFERENCE:
                STNode varName = ((STSimpleNameReferenceNode) ambiguousNode).name;
                return createCaptureOrWildcardBP(varName);
            case QUALIFIED_NAME_REFERENCE:
                if (isListBP) {
                    errorCode = DiagnosticErrorCode.ERROR_FIELD_BP_INSIDE_LIST_BP;
                    break;
                }
                STQualifiedNameReferenceNode qualifiedName = (STQualifiedNameReferenceNode) ambiguousNode;
                STNode fieldName = STNodeFactory.createSimpleNameReferenceNode(qualifiedName.modulePrefix);
                return STNodeFactory.createFieldBindingPatternFullNode(fieldName, qualifiedName.colon,
                        createCaptureOrWildcardBP(qualifiedName.identifier));
            case BRACKETED_LIST:
            case LIST_BP_OR_LIST_CONSTRUCTOR:
                STAmbiguousCollectionNode innerList = (STAmbiguousCollectionNode) ambiguousNode;
                STNode memberBindingPatterns =
                        STNodeFactory.createNodeList(getBindingPatternsList(innerList.members, true));
                return STNodeFactory.createListBindingPatternNode(innerList.collectionStartToken, memberBindingPatterns,
                        innerList.collectionEndToken);
            case MAPPING_BP_OR_MAPPING_CONSTRUCTOR:
                innerList = (STAmbiguousCollectionNode) ambiguousNode;
                List<STNode> bindingPatterns = new ArrayList<>();
                for (int i = 0; i < innerList.members.size(); i++) {
                    STNode bp = getBindingPattern(innerList.members.get(i), false);
                    bindingPatterns.add(bp);
                    if (bp.kind == SyntaxKind.REST_BINDING_PATTERN) {
                        break;
                    }
                }
                memberBindingPatterns = STNodeFactory.createNodeList(bindingPatterns);
                return STNodeFactory.createMappingBindingPatternNode(innerList.collectionStartToken,
                        memberBindingPatterns, innerList.collectionEndToken);
            case SPECIFIC_FIELD:
                STSpecificFieldNode field = (STSpecificFieldNode) ambiguousNode;
                fieldName = STNodeFactory.createSimpleNameReferenceNode(field.fieldName);
                if (field.valueExpr == null) {
                    return STNodeFactory.createFieldBindingPatternVarnameNode(fieldName);
                }
                return STNodeFactory.createFieldBindingPatternFullNode(fieldName, field.colon,
                        getBindingPattern(field.valueExpr, false));
            case ERROR_CONSTRUCTOR:
                STErrorConstructorExpressionNode errorCons = (STErrorConstructorExpressionNode) ambiguousNode;
                STNode args = errorCons.arguments;
                int size = args.bucketCount();
                bindingPatterns = new ArrayList<>();
                for (int i = 0; i < size; i++) {
                    STNode arg = args.childInBucket(i);
                    bindingPatterns.add(getBindingPattern(arg, false));
                }

                STNode argListBindingPatterns = STNodeFactory.createNodeList(bindingPatterns);
                return STNodeFactory.createErrorBindingPatternNode(errorCons.errorKeyword, errorCons.typeReference,
                        errorCons.openParenToken, argListBindingPatterns, errorCons.closeParenToken);
            case POSITIONAL_ARG:
                STPositionalArgumentNode positionalArg = (STPositionalArgumentNode) ambiguousNode;
                return getBindingPattern(positionalArg.expression, false);
            case NAMED_ARG:
                STNamedArgumentNode namedArg = (STNamedArgumentNode) ambiguousNode;
                STNode bindingPatternArgName = ((STSimpleNameReferenceNode) namedArg.argumentName).name;
                return STNodeFactory.createNamedArgBindingPatternNode(bindingPatternArgName, namedArg.equalsToken,
                        getBindingPattern(namedArg.expression, false));
            case REST_ARG:
                STRestArgumentNode restArg = (STRestArgumentNode) ambiguousNode;
                return STNodeFactory.createRestBindingPatternNode(restArg.ellipsis, restArg.expression);
        }

        STNode identifier = SyntaxErrors.createMissingToken(SyntaxKind.IDENTIFIER_TOKEN);
        identifier = SyntaxErrors.cloneWithLeadingInvalidNodeMinutiae(identifier, ambiguousNode, errorCode);
        return STNodeFactory.createCaptureBindingPatternNode(identifier);
    }

    private List<STNode> getExpressionList(List<STNode> ambibuousList, boolean isMappingConstructor) {
        List<STNode> exprList = new ArrayList<STNode>();
        for (STNode item : ambibuousList) {
            exprList.add(getExpression(item, isMappingConstructor));
        }
        return exprList;
    }

    private STNode getExpression(STNode ambiguousNode) {
        return getExpression(ambiguousNode, false);
    }

    private STNode getExpression(STNode ambiguousNode, boolean isInMappingConstructor) {
        if (isEmpty(ambiguousNode) || 
                (isDefiniteExpr(ambiguousNode.kind) && ambiguousNode.kind != SyntaxKind.INDEXED_EXPRESSION) || 
                isDefiniteAction(ambiguousNode.kind) || ambiguousNode.kind == SyntaxKind.COMMA_TOKEN) {
            return ambiguousNode;
        }

        switch (ambiguousNode.kind) {
            case BRACKETED_LIST:
            case LIST_BP_OR_LIST_CONSTRUCTOR:
            case TUPLE_TYPE_DESC_OR_LIST_CONST:
                STAmbiguousCollectionNode innerList = (STAmbiguousCollectionNode) ambiguousNode;
                STNode memberExprs = STNodeFactory.createNodeList(getExpressionList(innerList.members, false));
                return STNodeFactory.createListConstructorExpressionNode(innerList.collectionStartToken, memberExprs,
                        innerList.collectionEndToken);
            case MAPPING_BP_OR_MAPPING_CONSTRUCTOR:
                innerList = (STAmbiguousCollectionNode) ambiguousNode;
                List<STNode> fieldList = new ArrayList<>();
                for (int i = 0; i < innerList.members.size(); i++) {
                    STNode field = innerList.members.get(i);
                    STNode fieldNode;
                    if (field.kind == SyntaxKind.QUALIFIED_NAME_REFERENCE) {
                        STQualifiedNameReferenceNode qualifiedNameRefNode = (STQualifiedNameReferenceNode) field;
                        STNode readOnlyKeyword = STNodeFactory.createEmptyNode();
                        STNode fieldName = qualifiedNameRefNode.modulePrefix;
                        STNode colon = qualifiedNameRefNode.colon;
                        STNode valueExpr = getExpression(qualifiedNameRefNode.identifier);
                        fieldNode = STNodeFactory.createSpecificFieldNode(readOnlyKeyword, fieldName, colon, valueExpr);
                    } else {
                        fieldNode = getExpression(field, true);
                    }

                    fieldList.add(fieldNode);
                }
                STNode fields = STNodeFactory.createNodeList(fieldList);
                return STNodeFactory.createMappingConstructorExpressionNode(innerList.collectionStartToken, fields,
                        innerList.collectionEndToken);
            case REST_BINDING_PATTERN:
                STRestBindingPatternNode restBindingPattern = (STRestBindingPatternNode) ambiguousNode;
                if (isInMappingConstructor) {
                    return STNodeFactory.createSpreadFieldNode(restBindingPattern.ellipsisToken,
                            restBindingPattern.variableName);
                }
                return STNodeFactory.createSpreadMemberNode(restBindingPattern.ellipsisToken,
                        restBindingPattern.variableName);
            case SPECIFIC_FIELD:
                
                STSpecificFieldNode field = (STSpecificFieldNode) ambiguousNode;
                return STNodeFactory.createSpecificFieldNode(field.readonlyKeyword, field.fieldName, field.colon,
                        getExpression(field.valueExpr));
            case ERROR_CONSTRUCTOR:
                STErrorConstructorExpressionNode errorCons = (STErrorConstructorExpressionNode) ambiguousNode;
                
                
                STNode errorArgs = getErrorArgList(errorCons.arguments);
                return STNodeFactory.createErrorConstructorExpressionNode(errorCons.errorKeyword,
                        errorCons.typeReference, errorCons.openParenToken, errorArgs, errorCons.closeParenToken);
            case IDENTIFIER_TOKEN:
                return STNodeFactory.createSimpleNameReferenceNode(ambiguousNode);
            case INDEXED_EXPRESSION:
                STIndexedExpressionNode indexedExpressionNode = (STIndexedExpressionNode) ambiguousNode;
                STNodeList keys = (STNodeList) indexedExpressionNode.keyExpression;
                
                if (keys.size() != 0) {
                    return ambiguousNode;
                }
                
                STNode lhsExpr = indexedExpressionNode.containerExpression;
                STNode openBracket = indexedExpressionNode.openBracket;
                STNode closeBracket = indexedExpressionNode.closeBracket;
                STNode missingVarRef = STNodeFactory
                        .createSimpleNameReferenceNode(SyntaxErrors.createMissingToken(SyntaxKind.IDENTIFIER_TOKEN));
                STNode keyExpr = STNodeFactory.createNodeList(missingVarRef);
                closeBracket = SyntaxErrors.addDiagnostic(closeBracket,
                        DiagnosticErrorCode.ERROR_MISSING_KEY_EXPR_IN_MEMBER_ACCESS_EXPR);
                return STNodeFactory.createIndexedExpressionNode(lhsExpr, openBracket, keyExpr, closeBracket);
            case SIMPLE_NAME_REFERENCE:
            case QUALIFIED_NAME_REFERENCE:
            case COMPUTED_NAME_FIELD:
            case SPREAD_FIELD:    
            case SPREAD_MEMBER:
                return ambiguousNode;
            default:
                STNode simpleVarRef = SyntaxErrors.createMissingTokenWithDiagnostics(SyntaxKind.IDENTIFIER_TOKEN,
                        DiagnosticErrorCode.ERROR_MISSING_EXPRESSION);
                simpleVarRef = SyntaxErrors.cloneWithTrailingInvalidNodeMinutiae(simpleVarRef, ambiguousNode);
                return STNodeFactory.createSimpleNameReferenceNode(simpleVarRef);
        }
    }

    private STNode getMappingField(STNode identifier, STNode colon, STNode bindingPatternOrExpr) {
        STNode simpleNameRef = STNodeFactory.createSimpleNameReferenceNode(identifier);
        switch (bindingPatternOrExpr.kind) {
            case LIST_BINDING_PATTERN:
            case MAPPING_BINDING_PATTERN:
                return STNodeFactory.createFieldBindingPatternFullNode(simpleNameRef, colon, bindingPatternOrExpr);
            case LIST_CONSTRUCTOR:
            case MAPPING_CONSTRUCTOR:
                STNode readonlyKeyword = STNodeFactory.createEmptyNode();
                return STNodeFactory
                        .createSpecificFieldNode(readonlyKeyword, identifier, colon, bindingPatternOrExpr);
            case LIST_BP_OR_LIST_CONSTRUCTOR:
            case MAPPING_BP_OR_MAPPING_CONSTRUCTOR:
            default:
                
                
                readonlyKeyword = STNodeFactory.createEmptyNode();
                return STNodeFactory.createSpecificFieldNode(readonlyKeyword, identifier, colon, bindingPatternOrExpr);
        }
    }

    

    private Solution recover(STToken nextToken, ParserRuleContext currentCtx) {
        if (isInsideABlock(nextToken)) {
            return this.recover(nextToken, currentCtx, true);
        } else {
            return this.recover(nextToken, currentCtx, false);
        }
    }

    private boolean isInsideABlock(STToken nextToken) {
        
        
        if (nextToken.kind != SyntaxKind.CLOSE_BRACE_TOKEN) {
            return false;
        }
        
        for (ParserRuleContext ctx : this.errorHandler.getContextStack()) {
            if (isBlockContext(ctx)) {
                
                return true;
            }
        }
        return false;
    }

    private boolean isBlockContext(ParserRuleContext ctx) {
        switch (ctx) {
            case FUNC_BODY_BLOCK:
            case CLASS_MEMBER:
            case OBJECT_CONSTRUCTOR_MEMBER:
            case OBJECT_TYPE_MEMBER:
            case BLOCK_STMT:
            case MATCH_BODY:
            case MAPPING_MATCH_PATTERN:
            case MAPPING_BINDING_PATTERN:
            case MAPPING_CONSTRUCTOR:
            case FORK_STMT:
            case MULTI_RECEIVE_WORKERS:
            case MULTI_WAIT_FIELDS:
            case MODULE_ENUM_DECLARATION:
                return true;
            default:
                return false;
        }
    }

    

    
    
}