o
    biJ!                  	   @   s
  d dl Z d dlmZ d dlmZmZmZmZmZm	Z	m
Z
mZ er>ddlmZmZ zd dlZW n	 ey7   Y nw d dlmZ G dd dZe
d	Zeed
f ZG dd de	e Zed ZG dd deZddededdddfddZddefddZddefddZdS )    N)deepcopy)ListCallableIteratorUnionOptionalGenericTypeVarTYPE_CHECKING   )TerminalDefToken)Literalc                   @   s^   e Zd ZU eed< eed< eed< eed< eed< eed< eed< ded	< eed
< dd ZdS )Metaemptylinecolumn	start_posend_line
end_columnend_poszList[TerminalDef]orig_expansion
match_treec                 C   s
   d| _ d S )NT)r   self r   =/home/ubuntu/.local/lib/python3.10/site-packages/lark/tree.py__init__      
zMeta.__init__N)__name__
__module____qualname__bool__annotations__intr   r   r   r   r   r      s   
 r   _Leaf_TTree[_Leaf_T]c                	   @   s2  e Zd ZU dZeed< ded< d9dedddee ddfdd	Ze	defd
dZ
dd Zdd Zdd Zd:dedefddZd9ded ddfddZdd Zdd Zdd Zdefd d!Zd;d#d$Zd%d& Zd<d)d*Zdedd"fd+d,Zd-d. Zd'd/dee fd0d1Zd2d3 Zd=d5d6Zdeddddfd7d8ZdS )>Treea  The main tree class.

    Creates a new tree, and stores "data" and "children" in attributes of the same name.
    Trees can be hashed and compared.

    Parameters:
        data: The name of the rule or alias
        children: List of matched sub-rules and terminals
        meta: Line & Column numbers (if ``propagate_positions`` is enabled).
            meta attributes: (line, column, end_line, end_column, start_pos, end_pos,
                              container_line, container_column, container_end_line, container_end_column)
            container_* attributes consider all symbols, including those that have been inlined in the tree.
            For example, in the rule 'a: _A B _C', the regular attributes will mark the start and end of B,
            but the container_* attributes will also include _A and _C in the range. However, rules that
            contain 'a' will consider it in full, including _A and _C for all attributes.
    datazList[Branch[_Leaf_T]]childrenNmetareturnc                 C   s   || _ || _|| _d S N)r(   r)   _meta)r   r(   r)   r*   r   r   r   r   9   s   
zTree.__init__c                 C   s   | j d u r	t | _ | j S r,   )r-   r   r   r   r   r   r*   >   s   
z	Tree.metac                 C   s   d| j | jf S )NzTree(%r, %r)r(   r)   r   r   r   r   __repr__D   s   zTree.__repr__c                 C   s   | j S r,   r(   r   r   r   r   _pretty_labelG   s   zTree._pretty_labelc                 c   s    ||  |    V  t| jdkr't| jd ts'd| jd  dV  d S dV  | jD ]}t|tr@||d |E d H  q-||d   | dV  q-d S )Nr   r   	
)r1   lenr)   
isinstancer'   _pretty)r   level
indent_strnr   r   r   r6   J   s   

zTree._pretty  r8   c                 C   s   d | d|S )z]Returns an indented string representation of the tree.

        Great for debugging.
         r   )joinr6   )r   r8   r   r   r   prettyV   s   zTree.prettyparentzrich.tree.Treec                 C   s
   |  |S )zReturns a tree widget for the 'rich' library.

        Example:
            ::
                from rich import print
                from lark import Tree

                tree = Tree('root', ['node1', 'node2'])
                print(tree)
        )_rich)r   r>   r   r   r   __rich__]   s   
zTree.__rich__c                 C   sh   |r| d| j d}ndd l}|j| j}| jD ]}t|tr(|| q| d| d q|S )Nz[bold]z[/bold]r   z[green]z[/green])addr(   	rich.treetreer'   r)   r5   r?   )r   r>   rC   richcr   r   r   r?   j   s   

z
Tree._richc                 C   s0   z| j |j ko| j|jkW S  ty   Y dS w )NF)r(   r)   AttributeErrorr   otherr   r   r   __eq__y   s
   zTree.__eq__c                 C   s
   | |k S r,   r   rG   r   r   r   __ne__   r   zTree.__ne__c                 C   s   t | jt| jfS r,   )hashr(   tupler)   r   r   r   r   __hash__   s   zTree.__hash__Iterator[Tree[_Leaf_T]]c                    sP   | g}t   |D ]}| t|< | fddt|jD 7 }q~tt  S )zDepth-first iteration.

        Iterates over all the subtrees, never returning to the same node twice (Lark's parse-tree is actually a DAG).
        c                    s&   g | ]}t |trt| vr|qS r   )r5   r'   id).0rE   subtreesr   r   
<listcomp>   s    z&Tree.iter_subtrees.<locals>.<listcomp>)dictrO   reversedr)   listvalues)r   queuesubtreer   rQ   r   iter_subtrees   s   zTree.iter_subtreesc                 c   sT    | g}|j }|j}|r(| }t|tsq
|V  t|jD ]}|| q|sdS dS )ztBreadth-first iteration.

        Iterates over all the subtrees, return nodes in order like pretty() does.
        N)appendpopr5   r'   rU   r)   )r   stackstack_append	stack_popnodechildr   r   r   iter_subtrees_topdown   s   

zTree.iter_subtrees_topdownpredCallable[[Tree[_Leaf_T]], bool]c                 C   s   t ||  S )z?Returns all nodes of the tree that evaluate pred(node) as true.)filterrZ   )r   rc   r   r   r   	find_pred   s   zTree.find_predc                    s   |   fddS )z?Returns all nodes of the tree whose data equals the given data.c                    s
   | j  kS r,   r0   )tr0   r   r   <lambda>   s   
 z Tree.find_data.<locals>.<lambda>)rf   )r   r(   r   r0   r   	find_data   s   zTree.find_datac                 G   sZ   d}t t| jd ddD ]}| j| }t|tr*|j|v r*|j| j||d < d}q|S )z\Expand (inline) children with any of the given data values. Returns True if anything changedFr   T)ranger4   r)   r5   r'   r(   )r   data_valueschangedira   r   r   r   expand_kids_by_data   s   
zTree.expand_kids_by_dataz!Callable[[Branch[_Leaf_T]], bool]c                 c   sB    | j D ]}t|tr||D ]}|V  qq||r|V  qdS )zReturn all values in the tree that evaluate pred(value) as true.

        This can be used to find all the tokens in the tree.

        Example:
            >>> all_tokens = tree.scan_values(lambda v: isinstance(v, Token))
        N)r)   r5   r'   scan_values)r   rc   rE   rg   r   r   r   rp      s   

zTree.scan_valuesc                 C   s   t | | jt| j|| jdS )N)r*   )typer(   r   r)   r-   )r   memor   r   r   __deepcopy__   s   zTree.__deepcopy__r&   c                 C   s   t | | j| jS r,   )rq   r(   r)   r   r   r   r   copy   s   z	Tree.copyc                 C   s   || _ || _d S r,   r.   )r   r(   r)   r   r   r   set   s   
zTree.setr,   )r:   )r+   rN   )rc   rd   r+   rN   )r+   r&   ) r   r    r!   __doc__strr#   r   r   r   propertyr*   r/   r1   r6   r=   r@   r?   rI   rJ   r$   rM   rZ   rb   rf   ri   ro   r   r%   rp   rs   rt   ru   r   r   r   r   r'   $   s2   
  


r'   r   c                   @   s   e Zd ZdZdS )SlottedTree)r(   r)   ruler-   N)r   r    r!   	__slots__r   r   r   r   ry      s    ry   LRrC   filenamerankdirzLiteral["TB", "LR", "BT", "RL"]r+   c                 K       t | |fi |}|| d S r,   )pydot__tree_to_graph	write_pngrC   r}   r~   kwargsgraphr   r   r   pydot__tree_to_png      r   c                 K   r   r,   )r   writer   r   r   r   pydot__tree_to_dot   r   r   c                    sT   ddl jd	d|d|dgfdd fdd  |  S )
a  Creates a colorful image that represents the tree (data+children, without meta)

    Possible values for `rankdir` are "TB", "LR", "BT", "RL", corresponding to
    directed graphs drawn from top to bottom, from left to right, from bottom to
    top, and from right to left, respectively.

    `kwargs` can be any graph attribute (e. g. `dpi=200`). For a list of
    possible attributes, see https://www.graphviz.org/doc/info/attrs.html.
    r   Ndigraph)
graph_typer~   c                    s4   j d t| d}d  d7  <  | |S )Nr   )labelr   )Noderepradd_node)leafr`   )r   rn   pydotr   r   new_leaf   s   
z&pydot__tree_to_graph.<locals>.new_leafc                    s   t | jd@ }|dO } fdd| jD }jd dd| | jd}d  d	7  < | |D ]}|| q3|S )
Ni i c                    s&   g | ]}t |tr |n|qS r   )r5   r'   )rP   ra   )	_to_pydotr   r   r   rS      s    z;pydot__tree_to_graph.<locals>._to_pydot.<locals>.<listcomp>r   filledz#%x)style	fillcolorr   r   )rK   r(   r)   r   r   add_edgeEdge)rY   colorsubnodesr`   subnoder   r   rn   r   r   r   r   r      s   
z'pydot__tree_to_graph.<locals>._to_pydotr   )r   Dot)rC   r~   r   r   r   r   r      s   r   )r|   )sysrt   r   typingr   r   r   r   r   r   r	   r
   lexerr   r   rD   ImportErrorr   r   r%   Branchr'   	ParseTreery   rw   r   r   r   r   r   r   r   <module>   s*    ( 1