o
    rZhJX                     @   sp   d dl Z d dlmZmZ d dlmZ d dlmZ G dd deedZG dd	 d	eZ	G d
d deZ
d	dgZdS )    N)ABCMetaabstractmethod)Tree)slice_boundsc                       s   e Zd ZdZd" fdd	Zed#ddZedd	 Z fd
dZ fddZ	 fddZ
 fddZ fddZd$ fdd	Z fddZeedrVdd Zdd Zdd Zd d! Z  ZS )%AbstractParentedTreea  
    An abstract base class for a ``Tree`` that automatically maintains
    pointers to parent nodes.  These parent pointers are updated
    whenever any change is made to a tree's structure.  Two subclasses
    are currently defined:

      - ``ParentedTree`` is used for tree structures where each subtree
        has at most one parent.  This class should be used in cases
        where there is no"sharing" of subtrees.

      - ``MultiParentedTree`` is used for tree structures where a
        subtree may have zero or more parents.  This class should be
        used in cases where subtrees may be shared.

    Subclassing
    ===========
    The ``AbstractParentedTree`` class redefines all operations that
    modify a tree's structure to call two methods, which are used by
    subclasses to update parent information:

      - ``_setparent()`` is called whenever a new child is added.
      - ``_delparent()`` is called whenever a child is removed.
    Nc                    sr   t  || |d ur5t| D ]\}}t|tr | j||dd qt| D ]\}}t|tr4| || q%d S d S )NTdry_run)super__init__	enumerate
isinstancer   
_setparentselfnodechildrenichild	__class__ A/var/www/auris/lib/python3.10/site-packages/nltk/tree/parented.pyr
   .   s   

zAbstractParentedTree.__init__Fc                 C      dS )a  
        Update the parent pointer of ``child`` to point to ``self``.  This
        method is only called if the type of ``child`` is ``Tree``;
        i.e., it is not called when adding a leaf to a tree.  This method
        is always called before the child is actually added to the
        child list of ``self``.

        :type child: Tree
        :type index: int
        :param index: The index of ``child`` in ``self``.
        :raise TypeError: If ``child`` is a tree with an impropriate
            type.  Typically, if ``child`` is a tree, then its type needs
            to match the type of ``self``.  This prevents mixing of
            different tree types (single-parented, multi-parented, and
            non-parented).
        :param dry_run: If true, the don't actually set the child's
            parent pointer; just check for any error conditions, and
            raise an exception if one is found.
        Nr   r   r   indexr   r   r   r   r   @       zAbstractParentedTree._setparentc                 C   r   )a  
        Update the parent pointer of ``child`` to not point to self.  This
        method is only called if the type of ``child`` is ``Tree``; i.e., it
        is not called when removing a leaf from a tree.  This method
        is always called before the child is actually removed from the
        child list of ``self``.

        :type child: Tree
        :type index: int
        :param index: The index of ``child`` in ``self``.
        Nr   r   r   r   r   r   r   
_delparentV   r   zAbstractParentedTree._delparentc                    s,  t |tr/t| |dd\}}}t|||D ]}t | | tr&| | | | qt | d S t |tr]|dk r>|t	| 7 }|dk rFt
dt | | trU| | | | t | d S t |ttfrt	|dkrnt
dt	|dkr{| |d = d S | |d  |dd  = d S tdt| jt|jf )NTZ
allow_stepr   index out of rangez(The tree position () may not be deleted.   #%s indices must be integers, not %s)r   slicer   ranger   r   r	   __delitem__intlen
IndexErrorlisttuple	TypeErrortype__name__)r   r   startstopstepr   r   r   r   r$   j   s4   

z AbstractParentedTree.__delitem__c                    s  t |trmt| |dd\}}}t |ttfst|}t|D ]\}}t |tr3| j||||  dd qt|||D ]}t | | trK| 	| | | q:t|D ]\}}t |trc| ||||   qPt
 || d S t |tr|dk r||t| 7 }|dk rtd|| | u rd S t |tr| || t | | tr| 	| | | t
 || d S t |ttfrt|dkrtdt|dkr|| |d < d S || |d  |dd  < d S tdt| jt|jf )	NTr   r   r   r   z,The tree position () may not be assigned to.r    r!   )r   r"   r   r(   r)   r   r   r   r#   r   r	   __setitem__r%   r&   r'   r*   r+   r,   )r   r   valuer-   r.   r/   r   r   r   r   r   r0      sP   




z AbstractParentedTree.__setitem__c                    s*   t |tr| |t|  t | d S Nr   r   r   r&   r	   append)r   r   r   r   r   r4      s   
zAbstractParentedTree.appendc                    s4   |D ]}t |tr| |t|  t | qd S r2   r3   )r   r   r   r   r   r   extend   s
   
zAbstractParentedTree.extendc                    sH   |dk r
|t | 7 }|dk rd}t|tr| || t || d S Nr   )r&   r   r   r   r	   insert)r   r   r   r   r   r   r7      s   
zAbstractParentedTree.insertc                    sN   |dk r
|t | 7 }|dk rtdt| | tr!| | | | t |S )Nr   r   )r&   r'   r   r   r   r	   pop)r   r   r   r   r   r9      s   zAbstractParentedTree.popc                    s8   |  |}t| | tr| | | | t | d S r2   )r   r   r   r   r	   remover   r   r   r   r:      s   
zAbstractParentedTree.remove__getslice__c                 C      |  ttd|td|S r6   )__getitem__r"   maxr   r-   r.   r   r   r   r;         z!AbstractParentedTree.__getslice__c                 C   r<   r6   )r$   r"   r>   r?   r   r   r   __delslice__  r@   z!AbstractParentedTree.__delslice__c                 C   s   |  ttd|td||S r6   )r0   r"   r>   )r   r-   r.   r1   r   r   r   __setslice__  s   z!AbstractParentedTree.__setslice__c                 C   s   | j t| fS )a  Method used by the pickle module when un-pickling.
        This method provides the arguments passed to ``__new__``
        upon un-pickling. Without this method, ParentedTree instances
        cannot be pickled and unpickled in Python 3.7+ onwards.

        :return: Tuple of arguments for ``__new__``, i.e. the label
            and the children of this node.
        :rtype: Tuple[Any, List[AbstractParentedTree]]
        )Z_labelr(   r   r   r   r   __getnewargs__  s   
z#AbstractParentedTree.__getnewargs__r2   F)r8   )r,   
__module____qualname____doc__r
   r   r   r   r$   r0   r4   r5   r7   r9   r:   hasattrr(   r;   rA   rB   rD   __classcell__r   r   r   r   r      s&    
(<
r   )	metaclassc                       sz   e Zd ZdZd fdd	Zdd Zd fdd		Zd
d Zdd Zdd Z	dd Z
dd Zdd Zdd ZdddZ  ZS )ParentedTreea  
    A ``Tree`` that automatically maintains parent pointers for
    single-parented trees.  The following are methods for querying
    the structure of a parented tree: ``parent``, ``parent_index``,
    ``left_sibling``, ``right_sibling``, ``root``, ``treeposition``.

    Each ``ParentedTree`` may have at most one parent.  In
    particular, subtrees may not be shared.  Any attempt to reuse a
    single ``ParentedTree`` as a child of more than one parent (or
    as multiple children of the same parent) will cause a
    ``ValueError`` exception to be raised.

    ``ParentedTrees`` should never be used in the same tree as ``Trees``
    or ``MultiParentedTrees``.  Mixing tree implementations may result
    in incorrect parent pointers and in ``TypeError`` exceptions.
    Nc                    sT   d | _ 	 t || |d u r&t| D ]\}}t|tr%d |_ | || qd S d S r2   )_parentr	   r
   r   r   r   r   r   r   r   r   r
   '  s   
zParentedTree.__init__c                 C      ddl m} |S )Nr   )ImmutableParentedTree)nltk.tree.immutablerO   )r   rO   r   r   r   _frozen_class5     zParentedTree._frozen_classFc                    s&   |st | jj d t jddS )NzB objects do not support shallow copies. Defaulting to a deep copy.T)deep)warningswarnr   r,   r	   copy)r   rS   r   r   r   rV   :  s
   zParentedTree.copyc                 C   s   | j S )z5The parent of this tree, or None if it has no parent.)rM   rC   r   r   r   parentE  s   zParentedTree.parentc                 C   s:   | j du rdS t| j D ]\}}|| u r|  S qJ d)aD  
        The index of this tree in its parent.  I.e.,
        ``ptree.parent()[ptree.parent_index()] is ptree``.  Note that
        ``ptree.parent_index()`` is not necessarily equal to
        ``ptree.parent.index(ptree)``, since the ``index()`` method
        returns the first child that is equal to its argument.
        NFz&expected to find self in self._parent!)rM   r   )r   r   r   r   r   r   parent_indexI  s   
zParentedTree.parent_indexc                 C   s(   |   }| jr|dkr| j|d  S dS )z6The left sibling of this tree, or None if it has none.r   r    N)rX   rM   r   rX   r   r   r   left_siblingX  s   zParentedTree.left_siblingc                 C   s2   |   }| jr|t| jd k r| j|d  S dS )z7The right sibling of this tree, or None if it has none.r    N)rX   rM   r&   rY   r   r   r   right_sibling_  s   zParentedTree.right_siblingc                 C   s(   | }|  dur|  }|  dus|S )z
        The root of this tree.  I.e., the unique ancestor of this tree
        whose parent is None.  If ``ptree.parent()`` is None, then
        ``ptree`` is its own root.
        N)rW   r   rootr   r   r   r]   f  s
   zParentedTree.rootc                 C   s&   |   du rdS |    |  f S )z
        The tree position of this tree, relative to the root of the
        tree.  I.e., ``ptree.root[ptree.treeposition] is ptree``.
        Nr   )rW   treepositionrX   rC   r   r   r   r^   q  s   zParentedTree.treepositionc                 C   s6   t |tsJ | | |u sJ |j| u sJ d |_d S r2   )r   rL   rM   r   r   r   r   r     s   
zParentedTree._delparentc                 C   s@   t |ts	tdt|dr|jd urtd|s| |_d S d S )Nz5Can not insert a non-ParentedTree into a ParentedTreerM   z3Can not insert a subtree that already has a parent.)r   rL   r*   rI   rM   
ValueErrorr   r   r   r   r     s   

zParentedTree._setparentr2   rE   )r,   rF   rG   rH   r
   rQ   rV   rW   rX   rZ   r[   r]   r^   r   r   rJ   r   r   r   r   rL     s    	rL   c                       s|   e Zd ZdZd fdd	Zdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd ZdddZ  ZS )MultiParentedTreea  
    A ``Tree`` that automatically maintains parent pointers for
    multi-parented trees.  The following are methods for querying the
    structure of a multi-parented tree: ``parents()``, ``parent_indices()``,
    ``left_siblings()``, ``right_siblings()``, ``roots``, ``treepositions``.

    Each ``MultiParentedTree`` may have zero or more parents.  In
    particular, subtrees may be shared.  If a single
    ``MultiParentedTree`` is used as multiple children of the same
    parent, then that parent will appear multiple times in its
    ``parents()`` method.

    ``MultiParentedTrees`` should never be used in the same tree as
    ``Trees`` or ``ParentedTrees``.  Mixing tree implementations may
    result in incorrect parent pointers and in ``TypeError`` exceptions.
    Nc                    sT   g | _ 	 t || |d u r&t| D ]\}}t|tr%g |_ | || qd S d S r2   )_parentsr	   r
   r   r   r   r   r   r   r   r   r
     s   
zMultiParentedTree.__init__c                 C   rN   )Nr   )ImmutableMultiParentedTree)rP   rb   )r   rb   r   r   r   rQ     rR   zMultiParentedTree._frozen_classc                 C   s
   t | jS )a  
        The set of parents of this tree.  If this tree has no parents,
        then ``parents`` is the empty set.  To check if a tree is used
        as multiple children of the same parent, use the
        ``parent_indices()`` method.

        :type: list(MultiParentedTree)
        )r(   ra   rC   r   r   r   parents  s   
	zMultiParentedTree.parentsc                 C      dd |   D S )a}  
        A list of all left siblings of this tree, in any of its parent
        trees.  A tree may be its own left sibling if it is used as
        multiple contiguous children of the same parent.  A tree may
        appear multiple times in this list if it is the left sibling
        of this tree with respect to multiple parents.

        :type: list(MultiParentedTree)
        c                 S   s$   g | ]\}}|d kr||d  qS )r   r    r   .0rW   r   r   r   r   
<listcomp>  s
    
z3MultiParentedTree.left_siblings.<locals>.<listcomp>_get_parent_indicesrC   r   r   r   left_siblings     
zMultiParentedTree.left_siblingsc                 C   rd   )a  
        A list of all right siblings of this tree, in any of its parent
        trees.  A tree may be its own right sibling if it is used as
        multiple contiguous children of the same parent.  A tree may
        appear multiple times in this list if it is the right sibling
        of this tree with respect to multiple parents.

        :type: list(MultiParentedTree)
        c                 S   s,   g | ]\}}|t |d  k r||d   qS )r    )r&   re   r   r   r   rg     s
    
z4MultiParentedTree.right_siblings.<locals>.<listcomp>rh   rC   r   r   r   right_siblings  rk   z MultiParentedTree.right_siblingsc                    s    fdd j D S )Nc                    s.   g | ]}t |D ]\}}| u r||fqqS r   )r   )rf   rW   r   r   rC   r   r   rg     s    z9MultiParentedTree._get_parent_indices.<locals>.<listcomp>ra   rC   r   rC   r   ri     s   
z%MultiParentedTree._get_parent_indicesc                 C   s   t | i  S )z
        The set of all roots of this tree.  This set is formed by
        tracing all possible parent paths until trees with no parents
        are found.

        :type: list(MultiParentedTree)
        )r(   _get_roots_helpervaluesrC   r   r   r   roots  s   zMultiParentedTree.rootsc                 C   s0   | j r| j D ]}|| q|S | |t| < |S r2   )ra   rn   id)r   resultrW   r   r   r   rn     s   
z#MultiParentedTree._get_roots_helperc                    s$   | j vrg S  fddt|D S )aY  
        Return a list of the indices where this tree occurs as a child
        of ``parent``.  If this child does not occur as a child of
        ``parent``, then the empty list is returned.  The following is
        always true::

          for parent_index in ptree.parent_indices(parent):
              parent[parent_index] is ptree
        c                    s   g | ]
\}}| u r|qS r   r   )rf   r   r   rC   r   r   rg     s    z4MultiParentedTree.parent_indices.<locals>.<listcomp>)ra   r   )r   rW   r   rC   r   parent_indices  s   

z MultiParentedTree.parent_indicesc                    s$    u rdgS  fddj D S )a  
        Return a list of all tree positions that can be used to reach
        this multi-parented tree starting from ``root``.  I.e., the
        following is always true::

          for treepos in ptree.treepositions(root):
              root[treepos] is ptree
        r   c                    s@   g | ]}|  D ]}t|D ]\}}|u r||f qq	qS r   )treepositionsr   )rf   rW   Ztreeposr   r   r]   r   r   r   rg   !  s    
z3MultiParentedTree.treepositions.<locals>.<listcomp>rm   r\   r   ru   r   rt     s
   	zMultiParentedTree.treepositionsc                    sv   t |tsJ  | |u sJ t fdd|jD dksJ t D ]\}}||u r2||kr2 d S q#|j  d S )Nc                    s   g | ]}| u r|qS r   r   )rf   prC   r   r   rg   1  s    z0MultiParentedTree._delparent.<locals>.<listcomp>r    )r   r`   r&   ra   r   r:   )r   r   r   r   cr   rC   r   r   -  s    zMultiParentedTree._delparentFc                 C   sD   t |ts	td|s |jD ]	}|| u r d S q|j|  d S d S )Nz?Can not insert a non-MultiParentedTree into a MultiParentedTree)r   r`   r*   ra   r4   )r   r   r   r   rW   r   r   r   r   ;  s   

zMultiParentedTree._setparentr2   rE   )r,   rF   rG   rH   r
   rQ   rc   rj   rl   ri   rp   rn   rs   rt   r   r   rJ   r   r   r   r   r`     s    	
r`   )rT   abcr   r   Znltk.tree.treer   Z	nltk.utilr   r   rL   r`   __all__r   r   r   r   <module>   s   
    7