def parse_relations(<EOL>belstr: str, char_locs: CharLocs, parsed: Parsed, errors: Errors<EOL>) -> Tuple[Parsed, Errors]:
quotes = char_locs["<STR_LIT>"]<EOL>quoted_range = set([i for start, end in quotes.items() for i in range(start, end)])<EOL>for match in relations_pattern_middle.finditer(belstr):<EOL><INDENT>(start, end) = match.span(<NUM_LIT:1>)<EOL>end = end - <NUM_LIT:1>  <EOL>if start != end:<EOL><INDENT>test_range = set(range(start, end))<EOL><DEDENT>else:<EOL><INDENT>test_range = set(start)<EOL><DEDENT>if test_range.intersection(quoted_range):<EOL><INDENT>continue<EOL><DEDENT>span_key = (start, end)<EOL>parsed[span_key] = {<EOL>"<STR_LIT:type>": "<STR_LIT>",<EOL>"<STR_LIT:name>": match.group(<NUM_LIT:1>),<EOL>"<STR_LIT>": (start, end),<EOL>}<EOL><DEDENT>for match in relations_pattern_end.finditer(belstr):<EOL><INDENT>(start, end) = match.span(<NUM_LIT:1>)<EOL>log.debug(f"<STR_LIT>")<EOL>end = end - <NUM_LIT:1>  <EOL>if start != end:<EOL><INDENT>test_range = set(range(start, end))<EOL><DEDENT>else:<EOL><INDENT>test_range = set(start)<EOL><DEDENT>if test_range.intersection(quoted_range):<EOL><INDENT>continue<EOL><DEDENT>span_key = (start, end)<EOL>parsed[span_key] = {<EOL>"<STR_LIT:type>": "<STR_LIT>",<EOL>"<STR_LIT:name>": match.group(<NUM_LIT:1>),<EOL>"<STR_LIT>": (start, end),<EOL>}<EOL><DEDENT>return parsed, errors<EOL>
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):