<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def parse_relations( belstr: str, char_locs: CharLocs, parsed: Parsed, errors: Errors ) -> Tuple[Parsed, Errors]: """Parse relations from BEL string Args: belstr: BEL string as one single string (not list of chars) char_locs: paren, comma and quote char locations parsed: data structure for parsed functions, relations, nested errors: error messages Returns: (parsed, errors):
 """

    quotes = char_locs["quotes"]
    quoted_range = set([i for start, end in quotes.items() for i in range(start, end)])

    for match in relations_pattern_middle.finditer(belstr):
        (start, end) = match.span(1)
        # log.debug(f'Relation-middle {match}')
        end = end - 1  # adjust end to match actual end character index
        if start != end:
            test_range = set(range(start, end))
        else:
            test_range = set(start)

        # Skip if relation overlaps with quoted string
        if test_range.intersection(quoted_range):
            continue

        span_key = (start, end)
        parsed[span_key] = {
            "type": "Relation",
            "name": match.group(1),
            "span": (start, end),
        }

    for match in relations_pattern_end.finditer(belstr):
        (start, end) = match.span(1)
        log.debug(f"Relation-end {match}")
        end = end - 1  # adjust end to match actual end character index
        if start != end:
            test_range = set(range(start, end))
        else:
            test_range = set(start)

        # Skip if relation overlaps with quoted string
        if test_range.intersection(quoted_range):
            continue

        span_key = (start, end)
        parsed[span_key] = {
            "type": "Relation",
            "name": match.group(1),
            "span": (start, end),
        }

    return parsed, errors