U
    td}                     @   sN   d Z ddlmZ ddlmZ ddlZddlZddlZdZdd Z	dd
dZ
dS )z
Implementation of L{igraph.Graph.Formula()}.

You should use this module directly only if you have a very strong reason
to do so. In almost all cases, you are better off with calling
L{igraph.Graph.Formula()}.
    )StringIO)UniqueIdGeneratorN)construct_graph_from_formulac                 #   s  | dkrg dgddgfV  dS t tjtjtjg}d g g ddg  }}}d}tt| j}|D ]}|\}}	}
}
}
|rt	 fdd|	D r|tj
krd}|r|r|||fV  |g  }}ddg}nt fdd|	D rd}|rj||kr|tjkr|t|	 n|t|	 nL|	d	kr6|tj
kr6qbn2|tjkrDn$|tjkrRnd
| ||	f }t|qbd|	krd|	krddg}nd|d< qbd|	krd|d< qbd|	krb|	d dkrd|d< t|	dkrb|	d dkrbd|d< qb|||fV  dS )a[  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
     FNz<>-+Tc                 3   s   | ]}| kV  qd S N .0chZ
edge_charsr   G/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/igraph/formula.py	<genexpr>.   s     z!generate_edges.<locals>.<genexpr>c                 3   s   | ]}| kV  qd S r   r   r   r   r   r   r   7   s     :zDinvalid token found in edge specification: %s; token_type=%r; tok=%r<>r      +)settokenNAMENUMBERSTRINGtokenizegenerate_tokensr   __next__allOPanyappendevalstrNEWLINE	ENDMARKERSyntaxErrorlen)formulaZname_tokensstart_names	end_names
arrowheadsZparsing_verticesZ	token_genZ
token_info
token_typetok_msgr   r   r   generate_edges   s^    

 










r.   nameTc                    s,  |dkr| d|g idS t  g d  }}td|D ]}| }t|D ]\}}}	fdd|D }
fdd|D  |	d s|	d	 s|s| fd
d|
D  qNd}|	d	 r| fdd|
D  |	d rN| fdd|
D  qNq:i }t ||< | t	|||d}|r(|
  |S )a	  Graph.Formula(formula = None, attr = "name", simplify = True)

    Generates a graph from a graph formula

    A graph formula is a simple string representation of a graph.
    It is very handy for creating small graphs quickly. The string
    consists of vertex names separated by edge operators. An edge
    operator is a sequence of dashes (C{-}) that may or may not
    start with an arrowhead (C{<} at the beginning of the sequence
    or C{>} at the end of the sequence). The edge operators can
    be arbitrarily long, i.e., you may use as many dashes to draw
    them as you like. This makes a total of four different edge
    operators:

      - C{-----} makes an undirected edge
      - C{<----} makes a directed edge pointing from the vertex
        on the right hand side of the operator to the vertex on
        the left hand side
      - C{---->} is the opposite of C{<----}
      - C{<--->} creates a mutual directed edge pair between
        the two vertices

    If you only use the undirected edge operator (C{-----}),
    the graph will be undirected. Otherwise it will be directed.
    Vertex names used in the formula will be assigned to the
    C{name} vertex attribute of the graph.

    Some simple examples:

      >>> from igraph import Graph
      >>> print(Graph.Formula())          # empty graph
      IGRAPH UN-- 0 0 --
      + attr: name (v)
      >>> g = Graph.Formula("A-B")        # undirected graph
      >>> g.vs["name"]
      ['A', 'B']
      >>> print(g)
      IGRAPH UN-- 2 1 --
      + attr: name (v)
      + edges (vertex names):
      A--B
      >>> g.get_edgelist()
      [(0, 1)]
      >>> g2 = Graph.Formula("A-----------B")
      >>> g2.isomorphic(g)
      True
      >>> g = Graph.Formula("A  --->  B") # directed graph
      >>> g.vs["name"]
      ['A', 'B']
      >>> print(g)
      IGRAPH DN-- 2 1 --
      + attr: name (v)
      + edges (vertex names):
      A->B

    If you have may disconnected componnets, you can separate them
    with commas. You can also specify isolated vertices:

      >>> g = Graph.Formula("A--B, C--D, E--F, G--H, I, J, K")
      >>> print(", ".join(g.vs["name"]))
      A, B, C, D, E, F, G, H, I, J, K
      >>> g.connected_components().membership
      [0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 6]

    The colon (C{:}) operator can be used to specify vertex sets.
    If an edge operator connects two vertex sets, then every vertex
    from the first vertex set will be connected to every vertex in
    the second set:

      >>> g = Graph.Formula("A:B:C:D --- E:F:G")
      >>> g.isomorphic(Graph.Full_Bipartite(4, 3))
      True

    Note that you have to quote vertex names if they include spaces
    or special characters:

      >>> g = Graph.Formula('"this is" +- "a silly" -+ "graph here"')
      >>> g.vs["name"]
      ['this is', 'a silly', 'graph here']

    @param formula: the formula itself
    @param attr: name of the vertex attribute where the vertex names
                 will be stored
    @param simplify: whether the simplify the constructed graph
    @return: the constructed graph:
    Nr   )vertex_attrsFz[,\n]c                    s   g | ]} | qS r   r   r	   r/   
vertex_idsr   r   
<listcomp>   s     z0construct_graph_from_formula.<locals>.<listcomp>c                    s   g | ]} | qS r   r   r1   r2   r   r   r4      s     r   c                 3   s    | ]} D ]}||fV  q
qd S r   r   r	   Zid1Zid2end_idsr   r   r      s       z/construct_graph_from_formula.<locals>.<genexpr>Tc                 3   s    | ]} D ]}||fV  q
qd S r   r   r5   r6   r   r   r      s       c                 3   s    | ]} D ]}||fV  q
qd S r   r   r5   r6   r   r   r      s       )r   recompilesplitstripr.   extendlistvaluesr%   simplify)clsr&   attrr?   edgesZdirectedpartr'   r(   r)   Z	start_idsr0   resultr   )r7   r3   r   r   d   s,    Yr   )Nr/   T)__doc__ior   Zigraph.datatypesr   r8   r   r   __all__r.   r   r   r   r   r   <module>   s   O