u"""

    :type pattern: text_type
    :param pattern:
    :param start:
    :return:

def _parse_bracket_expression(pattern, start=0, no_escape=False):
    u"""

    :type pattern: text_type
    :param pattern:
    :param start:
    :return:
    """
    i = start

    if pattern[i:i+len(_BE_OPEN)] != _BE_OPEN:
        raise ValueError(u'Expected {}'.format(repr(_BE_OPEN)))
    i += len(_BE_OPEN)

    # fnmatch builds on top of POSIX, but uses `!` while POSIX uses `^`
    if pattern[i:i+len(_BE_NON_MATCHING)] == _BE_NON_MATCHING:
        matching = False
        i += len(_BE_NON_MATCHING)
    elif pattern[i:i+len(_BE_NON_MATCHING2)] == _BE_NON_MATCHING2:
        matching = False
        i += len(_BE_NON_MATCHING2)
    else:
        matching = True

    # We iterate other the items twice, first we get the tokens and parse most of it except for
    # ranges. Then, we resolve ranges by joining collating elements separated by an empty range
    # marker

    # Items in this bracket expression
    items = []

    # First pass: tokenize
    while len(items) == 0 or pattern[i:i + len(_BE_CLOSE)] != _BE_CLOSE:
        if not no_escape and pattern[i:i+len(_ESCAPE)] == _ESCAPE:  # Literal escape \a
            i += len(_ESCAPE)
            if i >= len(pattern):
                raise ValueError(u'Invalid pattern, incomplete escape sequence')
            items.append(_create_be_collating_element(pattern[i:i + 1]))
            i += 1
        elif pattern[i:i+len(_BE_CS_OPEN)] == _BE_CS_OPEN:  # Collating symbol [.abc.]
            cs, cs_len = _parse_be_collating_symbol(pattern, i)
            items.append(_create_be_collating_element(cs))
            i += cs_len
        elif pattern[i:i+len(_BE_ECE_OPEN)] == _BE_ECE_OPEN:  # Equivalence class expression [=abc=]
            # Currently, equivalence classes are a synonym for collating symbols because we do not
            # support equivalence classes. The difference is that we have to prevent them from
            # ending ranges to eventually add support for equivalence classes in the future
            ec_repr, ece_len = _parse_be_equivalence_class_expression(pattern, i)
            items.append(_create_be_equivalence_class(ec_repr))
            i += ece_len
        elif pattern[i:i+len(_BE_CCE_OPEN)] == _BE_CCE_OPEN:  # Character class expression [:alpha:]
            cc_name, cce_len = _parse_be_character_class_expression(pattern, i)
            items.append(_create_be_character_class(cc_name))
            i += cce_len
        elif pattern[i:i + len(_BE_RANGE)] == _BE_RANGE:  # Range a-c
            items.append(_create_be_unmatched_range())
            i += len(_BE_RANGE)
        else:  # Single-character collating element
            items.append(_create_be_collating_element(pattern[i:i+1]))
            i += 1

        if i >= len(pattern):
            raise ValueError(u'InvalidPattern, end of bracket expression not found')
    i += len(_BE_CLOSE)

    # Second pass: resolve ranges
    items_with_ranges = []
    j = 0
    while j < len(items):
        item = items[j]
        if not _is_be_unmatched_range(item):
            items_with_ranges.append(item)
        else:
            # From here, the current item is an unmatched range, we try to get the previous and next
            # item if they are collating elements
            if j == 0:
                prev_elem = None
            else:
                prev_elem = items_with_ranges[-1]
                if not _is_be_collating_element(prev_elem):
                    prev_elem = None
            if j == len(items) - 1:
                next_elem = None
            else:
                next_elem = items[j + 1]
                # case [a--], [---] or [[.a.]--]
                if prev_elem is not None and _is_be_unmatched_range(next_elem):
                    next_elem = _create_be_collating_element(_BE_RANGE)
                elif not _is_be_collating_element(next_elem):
                    next_elem = None

            # Unmatched dash between two collating elements
            if prev_elem is not None and next_elem is not None:
                # Note that we allow ranges between multi-character collating elements
                range_start = _read_be_collating_element(prev_elem)
                range_end = _read_be_collating_element(next_elem)
                # Equivalent to .pop then .append
                items_with_ranges[-1] = _create_be_range(range_start, range_end)
                j += 1  # Skip the next item (corresponds to the end of the range)
            # Add the dash as a collating element
            else:
                items_with_ranges.append(_create_be_collating_element(_BE_RANGE))
                _create_be_collating_element(_BE_RANGE)
        j += 1

    return _create_bracket_expression(matching, items_with_ranges), i - start