U
    nuf?                     @   s   d dl mZmZ d dlmZmZmZmZ d dlm	Z	 de
ddddZG d	d dZG d
d deZG dd deZG dd deZG dd deZG dd deZG dd deZdS )    )abstractmethodabstractproperty)ListOptionalTupleUnion)split_lines
NodeOrLeafOptional[BaseNode])node
node_typesreturnc                 G   s(   | j }|dk	r$|j|kr|S |j }qdS )an  
    Recursively looks at the parents of a node and returns the first found node
    that matches ``node_types``. Returns ``None`` if no matching node is found.

    This function is deprecated, use :meth:`NodeOrLeaf.search_ancestor` instead.

    :param node: The ancestors of this node will be checked.
    :param node_types: type names that are searched for.
    Nparenttype)r   r   n r   ./tmp/pip-unpacked-wheel-bhkpgl14/parso/tree.pysearch_ancestor   s    

r   c                   @   s   e Zd ZU dZdZeed< ded< dd Zdd	 Zd
d Z	dd Z
dd Zeeeef dddZeeeef dddZedd Zedd Zedd Zed'ddZedddd Zd!d"eeeef  ed#d$d%Zd&S )(r	   z.
    The base class for nodes and leaves.
    r   r   r
   r   c                 C   s   | }|j dk	r|j }q|S )z
        Returns the root node of a parser tree. The returned node doesn't have
        a parent node like all the other nodes/leaves.
        Nr   )selfZscoper   r   r   get_root_node(   s    
zNodeOrLeaf.get_root_nodec              	   C   sb   | j }|dkrdS t|jD ]@\}}|| krz| j j|d  W   S  tk
rZ   Y  dS X qdS )z
        Returns the node immediately following this node in this parent's
        children list. If this node does not have a next sibling, it is None
        N   )r   	enumeratechildren
IndexErrorr   r   ichildr   r   r   get_next_sibling2   s    zNodeOrLeaf.get_next_siblingc                 C   sT   | j }|dkrdS t|jD ]2\}}|| kr|dkr: dS | j j|d    S qdS )z
        Returns the node immediately preceding this node in this parent's
        children list. If this node does not have a previous sibling, it is
        None.
        Nr   r   )r   r   r   r   r   r   r   get_previous_siblingC   s    zNodeOrLeaf.get_previous_siblingc                 C   s   | j dkrdS | }|j j}||}|dkrB|j }|j dkrPdS q||d  }qRqz|jd }W qR tk
rx   | Y S X qRdS )z
        Returns the previous leaf in the parser tree.
        Returns `None` if this is the first element in the parser tree.
        Nr   r   )r   r   indexAttributeErrorr   r   cr   r   r   r   get_previous_leafT   s    


zNodeOrLeaf.get_previous_leafc                 C   s   | j dkrdS | }|j j}||}|t|d krJ|j }|j dkrXdS q||d  }qZqz|jd }W qZ tk
r   | Y S X qZdS )z
        Returns the next leaf in the parser tree.
        Returns None if this is the last element in the parser tree.
        Nr   r   )r   r   r"   lenr#   r$   r   r   r   get_next_leafn   s    


zNodeOrLeaf.get_next_leafr   c                 C   s   dS )z
        Returns the starting position of the prefix as a tuple, e.g. `(3, 4)`.

        :return tuple of int: (line, column)
        Nr   r   r   r   r   	start_pos   s    zNodeOrLeaf.start_posc                 C   s   dS )z
        Returns the end position of the prefix as a tuple, e.g. `(3, 4)`.

        :return tuple of int: (line, column)
        Nr   r*   r   r   r   end_pos   s    zNodeOrLeaf.end_posc                 C   s   dS )a-  
        Returns the start_pos of the prefix. This means basically it returns
        the end_pos of the last prefix. The `get_start_pos_of_prefix()` of the
        prefix `+` in `2 + 1` would be `(1, 1)`, while the start_pos is
        `(1, 2)`.

        :return tuple of int: (line, column)
        Nr   r*   r   r   r   get_start_pos_of_prefix   s    z"NodeOrLeaf.get_start_pos_of_prefixc                 C   s   dS )zO
        Returns the first leaf of a node or itself if this is a leaf.
        Nr   r*   r   r   r   get_first_leaf   s    zNodeOrLeaf.get_first_leafc                 C   s   dS )zN
        Returns the last leaf of a node or itself if this is a leaf.
        Nr   r*   r   r   r   get_last_leaf   s    zNodeOrLeaf.get_last_leafTc                 C   s   dS )z
        Returns the code that was the input for the parser for this node.

        :param include_prefix: Removes the prefix (whitespace and comments) of
            e.g. a statement.
        Nr   r   include_prefixr   r   r   get_code   s    zNodeOrLeaf.get_code)r   r   c                 G   s(   | j }|dk	r$|j|kr|S |j }qdS )a  
        Recursively looks at the parents of this node or leaf and returns the
        first found node that matches ``node_types``. Returns ``None`` if no
        matching node is found.

        :param node_types: type names that are searched for.
        Nr   )r   r   r   r   r   r   r      s    
zNodeOrLeaf.search_ancestor   )indent)r4   r   c                   sr   |dkrddn:t |tr*dd| n"t |tr>d|ntd|d
ttttd fdd	  | S )a  
        Returns a formatted dump of the parser tree rooted at this node or leaf. This is
        mainly useful for debugging purposes.

        The ``indent`` parameter is interpreted in a similar way as :py:func:`ast.dump`.
        If ``indent`` is a non-negative integer or string, then the tree will be
        pretty-printed with that indent level. An indent level of 0, negative, or ``""``
        will only insert newlines. ``None`` selects the single line representation.
        Using a positive integer indent indents that many spaces per level. If
        ``indent`` is a string (such as ``"\t"``), that string is used to indent each
        level.

        :param indent: Indentation style as described above. The default indentation is
            4 spaces, which yields a pretty-printed dump.

        >>> import parso
        >>> print(parso.parse("lambda x, y: x + y").dump())
        Module([
            Lambda([
                Keyword('lambda', (1, 0)),
                Param([
                    Name('x', (1, 7), prefix=' '),
                    Operator(',', (1, 8)),
                ]),
                Param([
                    Name('y', (1, 10), prefix=' '),
                ]),
                Operator(':', (1, 11)),
                PythonNode('arith_expr', [
                    Name('x', (1, 13), prefix=' '),
                    Operator('+', (1, 15), prefix=' '),
                    Name('y', (1, 17), prefix=' '),
                ]),
            ]),
            EndMarker('', (1, 18)),
        ])
        NF T z,expect 'indent' to be int, str or None, got )r   r4   	top_levelr   c                    sD  d}t | j}t| tr|| | d7 }t| trF|| jd7 }nt| tr`|| j d7 }|| jd| j7 }| j	r|d| j	7 }|d7 }nt| t
r|| | d7 }t| tr|| j d7 }|d7 }r|d7 }| jD ]}| || dd	7 }q|| d
7 }ntd| |s@r8|d7 }n|d7 }|S )Nr5   (z, z	, prefix=)[
F)r4   r7   z])zunsupported node encountered: z,
)r   __name__
isinstanceLeaf	ErrorLeaf
token_type	TypedLeafvaluer+   prefixBaseNodeNoder   	TypeError)r   r4   r7   resultZ	node_typer   _format_dumpZindent_stringnewliner   r   rI      s8    







z%NodeOrLeaf.dump.<locals>._format_dump)r5   T)r=   intstrrF   r	   bool)r   r4   r   rH   r   dump   s    &


$zNodeOrLeaf.dumpN)T)r<   
__module____qualname____doc__	__slots__rL   __annotations__r   r   r    r&   r(   r   r   rK   r+   r,   r   r-   r.   r/   r2   r   r   r   rN   r   r   r   r   r	      s.   





c                   @   s   e Zd ZU dZdZeed< deeeef eddddZ	e
eeef d	d
dZejeeef ddddZdd Zdd Zdd ZdddZe
eeef d	ddZdd ZdS )r>   z
    Leafs are basically tokens with a better API. Leafs exactly know where they
    were defined and what text preceeds them.
    )rB   linecolumnrC   rC   r5   N)rB   r+   rC   r   c                 C   s   || _ || _|| _d | _d S N)rB   r+   rC   r   )r   rB   r+   rC   r   r   r   __init__(  s
    zLeaf.__init__r)   c                 C   s   | j | jfS rV   rT   rU   r*   r   r   r   r+   8  s    zLeaf.start_pos)rB   r   c                 C   s   |d | _ |d | _d S )Nr   r   rX   r   rB   r   r   r   r+   <  s    
c                 C   s6   |   }|d kr0t| j}| jt| d dfS |jS )Nr   r   )r&   r   rC   rT   r'   r,   )r   Zprevious_leaflinesr   r   r   r-   A  s
    
zLeaf.get_start_pos_of_prefixc                 C   s   | S rV   r   r*   r   r   r   r.   I  s    zLeaf.get_first_leafc                 C   s   | S rV   r   r*   r   r   r   r/   L  s    zLeaf.get_last_leafTc                 C   s   |r| j | j S | jS d S rV   )rC   rB   r0   r   r   r   r2   O  s    zLeaf.get_codec                 C   sN   t | j}| jt| d }| j|kr:| jt|d  }nt|d }||fS )Nr   r!   )r   rB   rT   r'   rU   )r   rZ   Zend_pos_lineZend_pos_columnr   r   r   r,   U  s    

zLeaf.end_posc                 C   s"   | j }|s| j}dt| j|f S )Nz<%s: %s>)rB   r   r<   rY   r   r   r   __repr__`  s    zLeaf.__repr__)r5   )T)r<   rO   rP   rQ   rR   rL   rS   r   rK   rW   propertyr+   setterr-   r.   r/   r2   r,   r[   r   r   r   r   r>      s   


r>   c                       s"   e Zd ZdZd fdd	Z  ZS )rA   r   r5   c                    s   t  ||| || _d S rV   superrW   r   )r   r   rB   r+   rC   	__class__r   r   rW   j  s    zTypedLeaf.__init__)r5   )r<   rO   rP   rR   rW   __classcell__r   r   ra   r   rA   g  s   rA   c                   @   s   e Zd ZdZdZee ddddZee	e
e
f ddd	Zd
d Zee	e
e
f dddZdd ZdddZdddZdd Zdd Zdd ZdS )rD   zd
    The super class for all nodes.
    A node has children, a type and possibly a parent node.
    )r   N)r   r   c                 C   s    || _ d | _|D ]
}| |_qd S rV   )r   r   )r   r   r   r   r   r   rW   v  s    zBaseNode.__init__r)   c                 C   s   | j d jS Nr   )r   r+   r*   r   r   r   r+     s    zBaseNode.start_posc                 C   s   | j d  S rd   )r   r-   r*   r   r   r   r-     s    z BaseNode.get_start_pos_of_prefixc                 C   s   | j d jS Nr!   )r   r,   r*   r   r   r   r,     s    zBaseNode.end_posc                 C   sL   |rd dd |D S |d jdd}|d dd |dd  D  S d S )	Nr5   c                 s   s   | ]}|  V  qd S rV   r2   .0r%   r   r   r   	<genexpr>  s     z2BaseNode._get_code_for_children.<locals>.<genexpr>r   F)r1   c                 s   s   | ]}|  V  qd S rV   rf   rg   r   r   r   ri     s     r   )joinr2   )r   r   r1   firstr   r   r   _get_code_for_children  s    zBaseNode._get_code_for_childrenTc                 C   s   |  | j|S rV   )rl   r   r0   r   r   r   r2     s    zBaseNode.get_codeFc                    sL    fdd d  kr.j d jks8n td dtj d S )ax  
        Get the :py:class:`parso.tree.Leaf` at ``position``

        :param tuple position: A position tuple, row, column. Rows start from 1
        :param bool include_prefixes: If ``False``, ``None`` will be returned if ``position`` falls
            on whitespace or comments before a leaf
        :return: :py:class:`parso.tree.Leaf` at ``position``, or ``None``
        c                    s   | |krLj |  }s$|jk r$d S z|W S  tk
rJ   | Y S X t| | d }j | }|jkrz | |S  |d |S d S )N   r   )r   r+   get_leaf_for_positionr#   rK   r,   )lowerupperelementr"   binary_searchinclude_prefixespositionr   r   r   rs     s    




z5BaseNode.get_leaf_for_position.<locals>.binary_search)r   r   r!   z7Please provide a position that exists within this node.r   r   )r   r,   
ValueErrorr'   )r   ru   rt   r   rr   r   rn     s    	zBaseNode.get_leaf_for_positionc                 C   s   | j d  S rd   )r   r.   r*   r   r   r   r.     s    zBaseNode.get_first_leafc                 C   s   | j d  S re   )r   r/   r*   r   r   r   r/     s    zBaseNode.get_last_leafc                 C   s>   |   dddd }dt| j|| jd | jd f S )Nr;   r6   z<%s: %s@%s,%s>r   r   )r2   replacestripr   r<   r+   )r   coder   r   r   r[     s    zBaseNode.__repr__)T)F)r<   rO   rP   rQ   rR   r   r	   rW   r\   r   rK   r+   r-   r,   rl   r2   rn   r.   r/   r[   r   r   r   r   rD   o  s   

 rD   c                       s,   e Zd ZdZdZ fddZdd Z  ZS )rE   z+Concrete implementation for interior nodes.r^   c                    s   t  | || _d S rV   r_   )r   r   r   ra   r   r   rW     s    zNode.__init__c                 C   s   d| j j| j| jf S )Nz
%s(%s, %r))rb   r<   r   r   r*   r   r   r   r[     s    zNode.__repr__)r<   rO   rP   rQ   rR   rW   r[   rc   r   r   ra   r   rE     s   rE   c                   @   s   e Zd ZdZdZdZdS )	ErrorNodez
    A node that contains valid nodes/leaves that we're follow by a token that
    was invalid. This basically means that the leaf after this node is where
    Python would mark a syntax error.
    r   Z
error_nodeN)r<   rO   rP   rQ   rR   r   r   r   r   r   r{     s   r{   c                       s2   e Zd ZdZdZdZd	 fdd	Zdd Z  ZS )
r?   z
    A leaf that is either completely invalid in a language (like `$` in Python)
    or is invalid at that position. Like the star in `1 +* 1`.
    )r@   Z
error_leafr5   c                    s   t  ||| || _d S rV   )r`   rW   r@   )r   r@   rB   r+   rC   ra   r   r   rW     s    zErrorLeaf.__init__c                 C   s    dt | j| jt| j| jf S )Nz<%s: %s:%s, %s>)r   r<   r@   reprrB   r+   r*   r   r   r   r[     s    zErrorLeaf.__repr__)r5   )	r<   rO   rP   rQ   rR   r   rW   r[   rc   r   r   ra   r   r?     s
   r?   N)abcr   r   typingr   r   r   r   Zparso.utilsr   rL   r   r	   r>   rA   rD   rE   r{   r?   r   r   r   r   <module>   s     	GU
