(formula)
Parses an edge specification from the head of the given
    formula part and yields the following:

      - startpoint(s) of the edge by vertex names
      - endpoint(s) of the edge by names or an empty list if the vertices are
        isolated
      - a pair of bools to denote whether we had arrowheads at the start and end
        vertices
Parses an edge specification from the head of the given
    formula part and yields the following:
Parses an edge specification from the head of the given formula part and yields the following :
def generate_edges(formula):
    """Parses an edge specification from the head of the given
    formula part and yields the following:

      - startpoint(s) of the edge by vertex names
      - endpoint(s) of the edge by names or an empty list if the vertices are
        isolated
      - a pair of bools to denote whether we had arrowheads at the start and end
        vertices
    """
    if formula == "":
        yield [], [""], [False, False]
        return

    name_tokens = set([token.NAME, token.NUMBER, token.STRING])
    edge_chars = "<>-+"
    start_names, end_names, arrowheads = [], [], [False, False]
    parsing_vertices = True

    # Tokenize the formula
    token_gen = tokenize.generate_tokens(StringIO(formula).__next__)
    for token_info in token_gen:
        # Do the state transitions
        token_type, tok, _, _, _ = token_info
        if parsing_vertices:
            if all(ch in edge_chars for ch in tok) and token_type == token.OP:
                parsing_vertices = False
                # Check the edge we currently have
                if start_names and end_names:
                    # We have a whole edge
                    yield start_names, end_names, arrowheads
                start_names, end_names = end_names, []
                arrowheads = [False, False]
        else:
            if any(ch not in edge_chars for ch in tok):
                parsing_vertices = True

        if parsing_vertices:
            # We are parsing vertex names at the moment
            if token_type in name_tokens:
                # We found a vertex name
                if token_type == token.STRING:
                    end_names.append(eval(tok))
                else:
                    end_names.append(str(tok))
            elif tok == ":" and token_type == token.OP:
                # Separating semicolon between vertex names, we just go on
                continue
            elif token_type == token.NEWLINE:
                # Newlines are fine
                pass
            elif token_type == token.ENDMARKER:
                # End markers are fine
                pass
            else:
                msg = (
                    "invalid token found in edge specification: %s; "
                    "token_type=%r; tok=%r"
                    % (formula, token_type, tok)
                )
                raise SyntaxError(msg)
        else:
            # We are parsing an edge operator
            if "<" in tok:
                if ">" in tok:
                    arrowheads = [True, True]
                else:
                    arrowheads[0] = True
            elif ">" in tok:
                arrowheads[1] = True
            elif "+" in tok:
                if tok[0] == "+":
                    arrowheads[0] = True
                if len(tok) > 1 and tok[-1] == "+":
                    arrowheads[1] = True

    # The final edge
    yield start_names, end_names, arrowheads
def generate_edges ( formula ) : if formula == "" : yield [ ] , [ "" ] , [ False , False ] return name_tokens = set ( [ token . NAME , token . NUMBER , token . STRING ] ) edge_chars = "<>-+" start_names , end_names , arrowheads = [ ] , [ ] , [ False , False ] parsing_vertices = True # Tokenize the formula token_gen = tokenize . generate_tokens ( StringIO ( formula ) . __next__ ) for token_info in token_gen : # Do the state transitions token_type , tok , _ , _ , _ = token_info if parsing_vertices : if all ( ch in edge_chars for ch in tok ) and token_type == token . OP : parsing_vertices = False # Check the edge we currently have if start_names and end_names : # We have a whole edge yield start_names , end_names , arrowheads start_names , end_names = end_names , [ ] arrowheads = [ False , False ] else : if any ( ch not in edge_chars for ch in tok ) : parsing_vertices = True if parsing_vertices : # We are parsing vertex names at the moment if token_type in name_tokens : # We found a vertex name if token_type == token . STRING : end_names . append ( eval ( tok ) ) else : end_names . append ( str ( tok ) ) elif tok == ":" and token_type == token . OP : # Separating semicolon between vertex names, we just go on continue elif token_type == token . NEWLINE : # Newlines are fine pass elif token_type == token . ENDMARKER : # End markers are fine pass else : msg = ( "invalid token found in edge specification: %s; " "token_type=%r; tok=%r" % ( formula , token_type , tok ) ) raise SyntaxError ( msg ) else : # We are parsing an edge operator if "<" in tok : if ">" in tok : arrowheads = [ True , True ] else : arrowheads [ 0 ] = True elif ">" in tok : arrowheads [ 1 ] = True elif "+" in tok : if tok [ 0 ] == "+" : arrowheads [ 0 ] = True if len ( tok ) > 1 and tok [ - 1 ] == "+" : arrowheads [ 1 ] = True # The final edge yield start_names , end_names , arrowheads