
    Xhdz                        d Z ddlmZmZ ddlmZ ddlmZ ddlm	Z	 ddl
mZ ddlmZ dd	lmZ dd
lmZ ddlmZmZ ddlmZ  G d d      Z G d de      Z G d de      Z G d de      Z G d de      Z G d d      Z G d de      Z G d de      Z G d d      Z G d d e      Z d! Z! G d" d#e       Z" G d$ d%e      Z#y&)'a8  "This module implements an SPPF implementation

This is used as the primary output mechanism for the Earley parser
in order to store complex ambiguities.

Full reference and more details is here:
https://web.archive.org/web/20190616123959/http://www.bramvandersanden.com/post/2014/06/shared-packed-parse-forest/
    )TypeAbstractSet)randint)deque)
attrgetter)import_module)partial   )AmbiguousIntermediateExpander)Discard)logger
OrderedSet)Treec                       e Zd Zy)
ForestNodeN__name__
__module____qualname__     N/var/www/html/myenv/lib/python3.12/site-packages/lark/parsers/earley_forest.pyr   r      s    r   r   c                   n    e Zd ZU dZeZee   ed<   dZ	d Z
d Zd Zd Zed        Zed	        Zd
 Zd Zy)
SymbolNodea  
    A Symbol Node represents a symbol (or Intermediate LR0).

    Symbol nodes are keyed by the symbol (s). For intermediate nodes
    s will be an LR0, stored as a tuple of (rule, ptr). For completed symbol
    nodes, s will be a string representing the non-terminal origin (i.e.
    the left hand side of the rule).

    The children of a Symbol or Intermediate Node will always be Packed Nodes;
    with each Packed Node child representing a single derivation of a production.

    Hence a Symbol Node with a single child is unambiguous.

    Parameters:
        s: A Symbol, or a tuple of (rule, ptr) for an intermediate node.
        start: For dynamic lexers, the index of the start of the substring matched by this symbol (inclusive).
        end: For dynamic lexers, the index of the end of the substring matched by this symbol (exclusive).

    Properties:
        is_intermediate: True if this node is an intermediate node.
        priority: The priority of the node's symbol.
    Set)sstartend	_childrenpathspaths_loadedpriorityis_intermediatec                     || _         || _        || _        | j                         | _        | j                         | _        d| _        t        d      | _        t        |t              | _        y )NF-inf)r   r   r   r   r   r    r!   floatr"   
isinstancetupler#   )selfr   r   r   s       r   __init__zSymbolNode.__init__2   sU    
XXZ
! f)!U3r   c           
      V    | j                   j                  t        | |||||             y N)r   add
PackedNode)r)   lr0ruler   leftrights         r   
add_familyzSymbolNode.add_family?   s#    :dCudEJKr   c                 >    | j                   j                  ||f       y r,   )r    r-   )r)   
transitivenodes      r   add_pathzSymbolNode.add_pathB   s    


D)*r   c                    | j                   D ]R  \  }}|j                   t        |       |j                  j                  |j                  j                  | j
                        }|j                  |j                  |       | j                  |j                  j                  j                  |j                  j                  |j                  j                  |j                  j                  |       | j                  |j                  j                  j                  |j                  j                  |j                  j                  |j                  j                  |       U d| _        y )NT)r    
next_titemtyper   r   r   r7   r3   	reductionr0   originr6   r!   )r)   r5   r6   vns       r   
load_pathszSymbolNode.load_pathsE   sI    $

 	ZJ$$0T$Z
 5 5 7 79N9N9T9TVZV^V^_J1148
 4 4 9 9 @ @*BVBVB[B[]g]q]q]w]w  zD  zN  zN  zS  zS  UW  X
 4 4 9 9 @ @*BVBVB[B[]g]q]q]w]w  zD  zN  zN  zS  zS  UY  Z	Z !r   c                 2    t        | j                        dkD  S )z'Returns True if this node is ambiguous.   )lenchildrenr)   s    r   is_ambiguouszSymbolNode.is_ambiguousO   s     4==!A%%r   c                 z    | j                   s| j                          t        | j                  t	        d            S )zVReturns a list of this node's children sorted from greatest to
        least priority.sort_key)key)r!   r>   sortedr   r   rC   s    r   rB   zSymbolNode.childrenT   s-       OOdnn*Z*@AAr   c                 ,    t        | j                        S r,   )iterr   rC   s    r   __iter__zSymbolNode.__iter__\   s    DNN##r   c                    | j                   r| j                  d   }| j                  d   }d |j                  d | D        }d |j                  |d  D        }dj                  |j                  j
                  dj                  |      dj                  |            }n| j                  j
                  }dj                  || j                  | j                  | j                        S )Nr   r@   c              3   4   K   | ]  }|j                     y wr,   name.0	expansions     r   	<genexpr>z&SymbolNode.__repr__.<locals>.<genexpr>c        M)y~~M   c              3   4   K   | ]  }|j                     y wr,   rN   rP   s     r   rS   z&SymbolNode.__repr__.<locals>.<genexpr>d        LinnLrU   {} ::= {}* {} ({}, {}, {}, {}))
r#   r   rR   formatr<   rO   joinr   r   r"   r)   r0   ptrbeforeaftersymbols         r   __repr__zSymbolNode.__repr___   s    66!9D&&)CMt~~ds7KMFLdnnST6JLE$++DKK,<,<chhv>NPSPXPXY^P_`FVV[[F!((TXXt}}UUr   N)r   r   r   __doc__setr   r   r   __annotations__	__slots__r*   r3   r7   r>   propertyrD   rB   rK   rb   r   r   r   r   r      sg    , !Ck	 jI4L+! & & B B$	Vr   r   c                       e Zd ZdZeZy)StableSymbolNodezAA version of SymbolNode that uses OrderedSet for output stabilityN)r   r   r   rc   r   r   r   r   r   ri   ri   j   s
    G
Cr   ri   c                   b    e Zd ZdZdZd Zed        Zed        Zed        Z	d Z
d Zd	 Zd
 Zy)r.   ay  
    A Packed Node represents a single derivation in a symbol node.

    Parameters:
        rule: The rule associated with this node.
        parent: The parent of this node.
        left: The left child of this node. ``None`` if one does not exist.
        right: The right child of this node. ``None`` if one does not exist.
        priority: The priority of this node.
    )parentr   r0   r   r1   r2   r"   _hashc                     || _         || _        || _        || _        || _        || _        t        d      | _        t        | j                  | j
                  f      | _	        y )Nr%   )
rk   r   r   r0   r1   r2   r&   r"   hashrl   )r)   rk   r   r0   r   r1   r2   s          r   r*   zPackedNode.__init__z   sP    
		
f499djj12
r   c                 >    | j                   d u xr | j                  d u S r,   r1   r2   rC   s    r   is_emptyzPackedNode.is_empty   s    yyD 7TZZ4%77r   c                 ^    | j                   | j                   | j                  j                  fS )a   
        Used to sort PackedNode children of SymbolNodes.
        A SymbolNode has multiple PackedNodes if it matched
        ambiguously. Hence, we use the sort order to identify
        the order in which ambiguous children should be considered.
        )rq   r"   r0   orderrC   s    r   rF   zPackedNode.sort_key   s#     }}t}}ndiioo==r   c                 ^    | j                   | j                  fD cg c]  }||	 c}S c c}w )z'Returns a list of this node's children.rp   )r)   xs     r   rB   zPackedNode.children   s)     !IItzz2DaamDDDs   **c              #   D   K   | j                    | j                   y wr,   rp   rC   s    r   rK   zPackedNode.__iter__        iijj    c                     t        |t              sy| |u xs4 | j                  |j                  k(  xr | j                  |j                  k(  S NF)r'   r.   r1   r2   r)   others     r   __eq__zPackedNode.__eq__   s=    %,u}Wejj!8!VTZZ5;;=VWr   c                     | j                   S r,   rl   rC   s    r   __hash__zPackedNode.__hash__       zzr   c                    t        | j                  t              r| j                  d   }| j                  d   }d |j                  d | D        }d |j                  |d  D        }dj	                  |j
                  j                  dj                  |      dj                  |            }n| j                  j                  }dj	                  || j                  | j                  | j                  j                        S )Nr   r@   c              3   4   K   | ]  }|j                     y wr,   rN   rP   s     r   rS   z&PackedNode.__repr__.<locals>.<genexpr>   rT   rU   c              3   4   K   | ]  }|j                     y wr,   rN   rP   s     r   rS   z&PackedNode.__repr__.<locals>.<genexpr>   rW   rU   rX   rY   rZ   )r'   r   r(   rR   r[   r<   rO   r\   r   r"   r0   rs   r]   s         r   rb   zPackedNode.__repr__   s    dffe$66!9D&&)CMt~~ds7KMFLdnnST6JLE$++DKK,<,<chhv>NPSPXPXY^P_`FVV[[F!((T]]DIIOO\\r   N)r   r   r   rc   rf   r*   rg   rq   rF   rB   rK   r}   r   rb   r   r   r   r.   r.   n   sh    	 WI3 8 8 > > E EX
	]r   r.   c                   .    e Zd ZdZdZddZd Zd Zd Zy)		TokenNodez
    A Token Node represents a matched terminal and is always a leaf node.

    Parameters:
        token: The Token associated with this node.
        term: The TerminalDef matched by the token.
        priority: The priority of this node.
    )tokentermr"   rl   Nc                 ~    || _         || _        ||| _        n||j                  nd| _        t        |      | _        y Nr   )r   r   r"   rn   rl   )r)   r   r   r"   s       r   r*   zTokenNode.__init__   s:    
	$DM-1-=DMM1DM%[
r   c                 b    t        |t              sy| |u xs | j                  |j                  k(  S rz   )r'   r   r   r{   s     r   r}   zTokenNode.__eq__   s+    %+u};u{{!:;r   c                     | j                   S r,   r   rC   s    r   r   zTokenNode.__hash__   r   r   c                 ,    t        | j                        S r,   )reprr   rC   s    r   rb   zTokenNode.__repr__   s    DJJr   r,   )	r   r   r   rc   rf   r*   r}   r   rb   r   r   r   r   r      s"     7I!<
 r   r   c                   H    e Zd ZdZddZd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zy)ForestVisitora  
    An abstract base class for building forest visitors.

    This class performs a controllable depth-first walk of an SPPF.
    The visitor will not enter cycles and will backtrack if one is encountered.
    Subclasses are notified of cycles through the ``on_cycle`` method.

    Behavior for visit events is defined by overriding the
    ``visit*node*`` functions.

    The walk is controlled by the return values of the ``visit*node_in``
    methods. Returning a node(s) will schedule them to be visited. The visitor
    will begin to backtrack if no nodes are returned.

    Parameters:
        single_visit: If ``True``, non-Token nodes will only be visited once.
    c                     || _         y r,   single_visit)r)   r   s     r   r*   zForestVisitor.__init__   s
    (r   c                      y)zFCalled when a ``Token`` is visited. ``Token`` nodes are always leaves.Nr   r)   r6   s     r   visit_token_nodezForestVisitor.visit_token_node   s    r   c                      y)zCalled when a symbol node is visited. Nodes that are returned
        will be scheduled to be visited. If ``visit_intermediate_node_in``
        is not implemented, this function will be called for intermediate
        nodes as well.Nr   r   s     r   visit_symbol_node_inz"ForestVisitor.visit_symbol_node_in       
 	r   c                      y)zCalled after all nodes returned from a corresponding ``visit_symbol_node_in``
        call have been visited. If ``visit_intermediate_node_out``
        is not implemented, this function will be called for intermediate
        nodes as well.Nr   r   s     r   visit_symbol_node_outz#ForestVisitor.visit_symbol_node_out   r   r   c                      y)zgCalled when a packed node is visited. Nodes that are returned
        will be scheduled to be visited. Nr   r   s     r   visit_packed_node_inz"ForestVisitor.visit_packed_node_in        	r   c                      y)zmCalled after all nodes returned from a corresponding ``visit_packed_node_in``
        call have been visited.Nr   r   s     r   visit_packed_node_outz#ForestVisitor.visit_packed_node_out   r   r   c                      y)a  Called when a cycle is encountered.

        Parameters:
            node: The node that causes a cycle.
            path: The list of nodes being visited: nodes that have been
                entered but not exited. The first element is the root in a forest
                visit, and the last element is the node visited most recently.
                ``path`` should be treated as read-only.
        Nr   r)   r6   paths      r   on_cyclezForestVisitor.on_cycle   s     	r   c                     t        |      dz
  }t        ||         t        |      k7  r |dz  }t        ||         t        |      k7  r ||d S )zA utility function for use in ``on_cycle`` to obtain a slice of
        ``path`` that only contains the nodes that make up the cycle.r@   N)rA   id)r)   r6   r   indexs       r   get_cycle_in_pathzForestVisitor.get_cycle_in_path
  sP     D	AeoD)QJE eoD)EF|r   c                    t               }t               }g }t        |g      }t        | d      }t        | d      }t        | d      }t        | d      }	t        | d|      }
t        | d|	      }t        | d      }t        | d      }|rMt        t	        |            }	 t        |      }|%t        |      |v r
 |||       <|j                  |       Ny y # t        $ r |j                          Y kt        $ r Y nw xY wt        |t              r# ||j                         |j                          t        |      }||v ryt        |t              r	 ||       n|j                  r	 |
|       n ||       |j                          |j                          |j                  |       |j!                  |       n| j"                  r||v r|j                          n|j!                  |       |j                  |       t        |t              r	 ||      }n|j                  r	 ||      }n |	|      }|t        |t$              st'        |      }nt        |      |v r |||       |j                  |       |r)	Nr   r   r   r   visit_intermediate_node_outvisit_intermediate_node_inr   r   )rd   r   getattrnextreversedr   appendStopIterationpop	TypeErrorr'   r   r   r.   r#   remover-   r   r   rJ   )r)   rootvisitingvisitedr   input_stackvpnovpnivsnovsnivinovinivtnoccurrent	next_node
current_ids                    r   visitzForestVisitor.visit  sL    5 %  TFm t45t34t45t34t:DAt94@d./T:&8K01G M	 $i=H,y$'""9-'  ! !  '9-GMM"!GJX%gz2M,,MM!

+J'""zW'<!Z(G$gz2 $WI,, $WI $WI$!)Z8 $YI	]h.y$'""9-u s   C C;0C;:C;N)F)r   r   r   rc   r*   r   r   r   r   r   r   r   r   r   r   r   r   r      s5    $)


X.r   r   c                   j     e Zd ZdZ fdZd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zd Zd Z xZS )ForestTransformera  The base class for a bottom-up forest transformation. Most users will
    want to use ``TreeForestTransformer`` instead as it has a friendlier
    interface and covers most use cases.

    Transformations are applied via inheritance and overriding of the
    ``transform*node`` methods.

    ``transform_token_node`` receives a ``Token`` as an argument.
    All other methods receive the node that is being transformed and
    a list of the results of the transformations of that node's children.
    The return value of these methods are the resulting transformations.

    If ``Discard`` is raised in a node's transformation, no data from that node
    will be passed to its parent's transformation.
    c                 f    t         t        |           t               | _        t               | _        y r,   )superr   r*   dictdatar   
node_stackr)   	__class__s    r   r*   zForestTransformer.__init__}  s#    /1F	'r   c                     | j                   j                  d       g | j                  d<   | j                  |       t	        | j                  d         dk  sJ | j                  d   r| j                  d   d   S y)z$Perform a transformation on an SPPF.resultr@   r   N)r   r   r   r   rA   )r)   r   s     r   	transformzForestTransformer.transform  so    x( 		(

4499X&'1,,,99X99X&q)) r   c                     |S )zTransform a symbol node.r   r)   r6   r   s      r   transform_symbol_nodez'ForestTransformer.transform_symbol_node      r   c                     |S )zTransform an intermediate node.r   r   s      r   transform_intermediate_nodez-ForestTransformer.transform_intermediate_node  r   r   c                     |S )zTransform a packed node.r   r   s      r   transform_packed_nodez'ForestTransformer.transform_packed_node  r   r   c                     |S )zTransform a ``Token``.r   r   s     r   transform_token_nodez&ForestTransformer.transform_token_node  r   r   c                     | j                   j                  t        |             g | j                  t        |      <   |j                  S r,   r   r   r   r   rB   r   s     r   r   z&ForestTransformer.visit_symbol_node_in  4    r$x( 		"T(}}r   c                     | j                   j                  t        |             g | j                  t        |      <   |j                  S r,   r   r   s     r   r   z&ForestTransformer.visit_packed_node_in  r   r   c                     | j                  |      }|t        ur,| j                  | j                  d      j	                  |       y y N)r   r   r   r   r   )r)   r6   transformeds      r   r   z"ForestTransformer.visit_token_node  s?    //5g%IIdoob)*11+> &r   c                    | j                   j                           ||| j                  t        |               }|t        ur+| j                  | j                   d      j                  |       | j                  t        |      = y r   )r   r   r   r   r   r   )r)   r6   methodr   s       r   _visit_node_out_helperz(ForestTransformer._visit_node_out_helper  sc    T499RX#67g%IIdoob)*11+>IIbhr   c                 <    | j                  || j                         y r,   )r   r   r   s     r   r   z'ForestTransformer.visit_symbol_node_out      ##D$*D*DEr   c                 <    | j                  || j                         y r,   )r   r   r   s     r   r   z-ForestTransformer.visit_intermediate_node_out  s    ##D$*J*JKr   c                 <    | j                  || j                         y r,   )r   r   r   s     r   r   z'ForestTransformer.visit_packed_node_out  r   r   )r   r   r   rc   r*   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__r   s   @r   r   r   l  sL     "*

?
 FLFr   r   c                   :     e Zd ZdZ fdZd Zd Zd Zd Z xZ	S )ForestSumVisitoraq  
    A visitor for prioritizing ambiguous parts of the Forest.

    This visitor is used when support for explicit priorities on
    rules is requested (whether normal, or invert). It walks the
    forest (or subsets thereof) and cascades properties upwards
    from the leaves.

    It would be ideal to do this during parsing, however this would
    require processing each Earley item multiple times. That's
    a big performance drawback; so running a forest walk is the
    lesser of two evils: there can be significantly more Earley
    items created during parsing than there are SPPF nodes in the
    final tree.
    c                 .    t         t        |   d       y )NTr   )r   r   r*   r   s    r   r*   zForestSumVisitor.__init__  s    .D.Ar   c              #   D   K   |j                    |j                   y wr,   rp   r   s     r   r   z%ForestSumVisitor.visit_packed_node_in  rw   rx   c                 ,    t        |j                        S r,   )rJ   rB   r   s     r   r   z%ForestSumVisitor.visit_symbol_node_in  s    DMM""r   c                 *   |j                   j                  s@|j                  j                  j                  r |j                  j                  j                  nd}|t        |j                  dd      z  }|t        |j                  dd      z  }||_        y )Nr   r"   )rk   r#   r0   optionsr"   r   r2   r1   )r)   r6   r"   s      r   r   z&ForestSumVisitor.visit_packed_node_out  sp    59[[5P5PUYU^U^UfUfUoUo499$$--uvGDJJ
A66GDIIz155 r   c                 F    t        d |j                  D              |_        y )Nc              3   4   K   | ]  }|j                     y wr,   )r"   )rQ   childs     r   rS   z9ForestSumVisitor.visit_symbol_node_out.<locals>.<genexpr>  s     FuENNFrU   )maxrB   r"   r   s     r   r   z&ForestSumVisitor.visit_symbol_node_out  s    FFFr   )
r   r   r   rc   r*   r   r   r   r   r   r   s   @r   r   r     s#    B#!Gr   r   c                   8    e Zd ZdZ G d d      Z e       Zd Zy)
PackedDataz}Used in transformationss of packed nodes to distinguish the data
    that comes from the left child and the right child.
    c                       e Zd Zy)PackedData._NoDataNr   r   r   r   _NoDatar     s    r   r   c                     | j                   | _        | j                   | _        |r;|j                  $|d   | _        t        |      dkD  r|d   | _        y y |d   | _        y y )Nr   r@   )NO_DATAr1   r2   rA   r   s      r   r*   zPackedData.__init__  s]    LL	\\
yy$ G	t9q=!%aDJ ! "!W
 r   N)r   r   r   rc   r   r   r*   r   r   r   r   r     s      iG	%r   r   c                        e Zd ZdZe e        e       ddf fd	Z fdZd Z	d Z
d Zd Zd	 Zd
 Zd Zd Z fdZ fdZ fdZ xZS )ForestToParseTreeao  Used by the earley parser when ambiguity equals 'resolve' or
    'explicit'. Transforms an SPPF into an (ambiguous) parse tree.

    Parameters:
        tree_class: The tree class to use for construction
        callbacks: A dictionary of rules to functions that output a tree
        prioritizer: A ``ForestVisitor`` that manipulates the priorities of ForestNodes
        resolve_ambiguity: If True, ambiguities will be resolved based on
                        priorities. Otherwise, `_ambig` nodes will be in the resulting tree.
        use_cache: If True, the results of packed node transformations will be cached.
    Tc                     t         t        |           || _        || _        || _        || _        || _        i | _        d| _	        d | _
        t               | _        y rz   )r   r   r*   
tree_class	callbacksprioritizerresolve_ambiguity
_use_cache_cache_on_cycle_retreat_cycle_noderd   _successful_visits)r)   r   r  r  r  	use_cacher   s         r   r*   zForestToParseTree.__init__  sW    /1$"&!2#!&"%%r   c                     | j                   r| j                   j                  |       t        t        |   |       i | _        y r,   )r  r   r   r   r  )r)   r   r   s     r   r   zForestToParseTree.visit  s7    ""4(,T2r   c                 L    t        j                  d|       || _        d| _        y )NzCycle encountered in the SPPF at node: %s. As infinite ambiguities cannot be represented in a tree, this family of derivations will be discarded.T)r   debugr  r  r   s      r   r   zForestToParseTree.on_cycle  s*     @AE	G  !%r   c                     | j                   rMt        |      t        | j                        k(  st        |      | j                  v rd | _        d| _         y t        S y rz   )r  r   r  r  r   r   s     r   _check_cyclezForestToParseTree._check_cycle  sM    !!$x2d..//2d8t?V?V3V#' ).& "r   c                     g }|D ]>  }t        |d      r|j                  dk(  r||j                  z  }.|j                  |       @ |S )Nr   _ambig)hasattrr   rB   r   )r)   rB   new_childrenr   s       r   _collapse_ambigz!ForestToParseTree._collapse_ambig#  sO     	+Euf%%***@.##E*		+
 r   c                 @     | j                   |j                     |      S r,   )r  r0   r   s      r   _call_rule_funcz!ForestToParseTree._call_rule_func,  s     )t~~dii(..r   c                 \    t        |      dkD  r| j                  d|      S |r|d   S t        S )Nr@   r  r   rA   r   r   r   s      r   _call_ambig_funcz"ForestToParseTree._call_ambig_func2  s1     t9q=??8T227Nr   c                     t        |      | j                  vrt        S | j                  |      }|t        u r|S | j                  j	                  t        |             | j                  |      }| j                  ||      S r,   )r   r  r   r  r   r  r  )r)   r6   r   rs       r   r   z'ForestToParseTree.transform_symbol_node<  sp    d84222Nd#<H&&r$x0##D)$$T400r   c                 L   t        |      | j                  vrt        S | j                  |      }|t        u r|S | j                  j	                  t        |             t        |      dkD  r1|D cg c]  }| j                  d|       }}| j                  d|      S |d   S c c}w )Nr@   _inter_iambigr   )r   r  r   r  r   rA   r   )r)   r6   r   r  crB   s         r   r   z-ForestToParseTree.transform_intermediate_nodeF  s    d84222Nd#<H&&r$x0t9q=>BC!4CHC??9h77Aw Ds   /B!c                 L   | j                  |      }|t        u r|S | j                  r't        |j                        | j
                  v rt        S | j                  r/t        |      | j                  v r| j                  t        |         S g }t        |      dk  sJ t        ||      }|j                  t        j                  ur[|j                  j                  r*t        |j                  t              r||j                  z  }n|j                  |j                         |j                   t        j                  ur|j                  |j                          |j                  j                  r|n| j#                  ||      }| j                  r|| j                  t        |      <   |S )Nr
   )r  r   r  r   rk   r  r  r  rA   r   r1   r   r#   r'   listr   r2   r  )r)   r6   r   r  rB   r   s         r   r   z'ForestToParseTree.transform_packed_nodeR  s8   d#<H!!bo9P9P&PN??r$x4;;6;;r$x((4yA~~$%99J...yy((Z		4-HDII%		*::Z///OODJJ'"&++"="=h4CWCWX\^fCg??$/DKK4!r   c                 \    t         t        |   |       | j                  ry |j                  S r,   )r   r   r   r  rB   r)   r6   r   s     r   r   z&ForestToParseTree.visit_symbol_node_ini  s)    ;DA!!}}r   c                     d| _         t        t        |   |      }| j                  r!t        |j                        | j                  vr&| j                  rt        |      | j                  vr|S y y rz   )
r  r   r   r   r  r   rk   r  r  r  )r)   r6   to_visitr   s      r   r   z&ForestToParseTree.visit_packed_node_ino  sb    !&*DFtL%%DKK@W@W)W??bhdkk&A 'B *Xr   c                     t         t        |   |       | j                  s/| j                  j                  t        |j                               y y r,   )r   r   r   r  r  r-   r   rk   r"  s     r   r   z'ForestToParseTree.visit_packed_node_outv  s=    <TB%%##''4;;8 &r   )r   r   r   rc   r   r   r   r*   r   r   r  r  r  r  r   r   r   r   r   r   r   r   s   @r   r   r     sg    
 #'$&FVFXlp  }A 
(&/1
. 9 9r   r   c                     d| _         | S )zDecorator for methods of subclasses of ``TreeForestTransformer``.
    Denotes that the method should receive a list of transformed derivations.T)handles_ambiguity)funcs    r   r'  r'  {  s     "DKr   c                   Z     e Zd ZdZe e       ddf fd	Zd Zd Zd Z	d Z
d	 Zd
 Z xZS )TreeForestTransformerac  A ``ForestTransformer`` with a tree ``Transformer``-like interface.
    By default, it will construct a tree.

    Methods provided via inheritance are called based on the rule/symbol
    names of nodes in the forest.

    Methods that act on rules will receive a list of the results of the
    transformations of the rule's children. By default, trees and tokens.

    Methods that act on tokens will receive a token.

    Alternatively, methods that act on rules may be annotated with
    ``handles_ambiguity``. In this case, the function will receive a list
    of all the transformations of all the derivations of the rule.
    By default, a list of trees where each tree.data is equal to the
    rule name or one of its aliases.

    Non-tree transformations are made possible by override of
    ``__default__``, ``__default_token__``, and ``__default_ambig__``.

    Note:
        Tree shaping features such as inlined rules and token filtering are
        not built into the transformation. Positions are also not propagated.

    Parameters:
        tree_class: The tree class to use for construction
        prioritizer: A ``ForestVisitor`` that manipulates the priorities of nodes in the SPPF.
        resolve_ambiguity: If True, ambiguities will be resolved based on priorities.
        use_cache (bool): If True, caches the results of some transformations,
                          potentially improving performance when ``resolve_ambiguity==False``.
                          Only use if you know what you are doing: i.e. All transformation
                          functions are pure and referentially transparent.
    TFc                 D    t         t        |   |t               |||       y r,   )r   r*  r*   r   )r)   r   r  r  r	  r   s        r   r*   zTreeForestTransformer.__init__  s    #T3JUfhqrr   c                 &    | j                  ||      S )zkDefault operation on tree (for override).

        Returns a tree with name with data as children.
        )r   r)   rO   r   s      r   __default__z!TreeForestTransformer.__default__  s    
 tT**r   c                 \    t        |      dkD  r| j                  d|      S |r|d   S t        S )zDefault operation on ambiguous rule (for override).

        Wraps data in an '_ambig_' node if it contains more than
        one element.
        r@   r  r   r  r-  s      r   __default_ambig__z'TreeForestTransformer.__default_ambig__  s1     t9q=??8T227Nr   c                     |S )zRDefault operation on ``Token`` (for override).

        Returns ``node``.
        r   r   s     r   __default_token__z'TreeForestTransformer.__default_token__  s	    
 r   c                 P     t        | |j                  | j                        |      S r,   )r   r:   r2  r   s     r   r   z*TreeForestTransformer.transform_token_node  s"    ?wtTYY(>(>?EEr   c                    |j                   j                  xsB |j                   j                  j                  xs  |j                   j                  j
                  }t        | || j                        }|| j                  k(  st        |d      rt        | j                  |      }| j                  s"t        t        | j                        } ||      } ||      S Nr'  )r0   aliasr   template_sourcer<   rO   r   r.  r  r	   r  r   r   )r)   r6   r   rO   	user_funcwrappers         r   r  z%TreeForestTransformer._call_rule_func  s    yy\$))"3"3"C"C\tyyGWGWG\G\D$(8(89	(((GI?R,S 0 0$7I%%;T__MG	*Ir   c                     |j                   j                  }t        | || j                        }|| j                  k(  st	        |d      st        | j                  |      } ||      S r5  )r   rO   r   r0  r  r	   )r)   r6   r   rO   r8  s        r   r  z&TreeForestTransformer._call_ambig_func  sW    vv{{D$(>(>?	...giI\6] 6 6=Ir   )r   r   r   rc   r   r   r*   r.  r0  r2  r   r  r  r   r   s   @r   r*  r*    s?     D #'4D4FZ^jo s+
Fr   r*  c                   L     e Zd ZdZd	 fd	Z fdZd Zd Zd Zd Z	d Z
 xZS )
ForestToPyDotVisitora  
    A Forest visitor which writes the SPPF to a PNG.

    The SPPF can get really large, really quickly because
    of the amount of meta-data it stores, so this is probably
    only useful for trivial trees and learning how the SPPF
    is structured.
    c                     t         t        |   d       t        d      | _        | j                  j                  d|      | _        y )NTr   pydotdigraph)
graph_typerankdir)r   r<  r*   r   r>  Dotgraph)r)   rA  r   s     r   r*   zForestToPyDotVisitor.__init__  s:    "D22E"7+
ZZ^^y'^J
r   c                     t         t        |   |       	 | j                  j	                  |       y # t
        $ r }t        j                  d|       Y d }~y d }~ww xY w)NzCould not write png: )r   r<  r   rC  	write_pngFileNotFoundErrorr   error)r)   r   filenameer   s       r   r   zForestToPyDotVisitor.visit  sL    "D/5	5JJ  *  	5LL0!44	5s   2 	AAAc                 "   t        t        |            }dj                  |j                  j	                  dd            }d}d}d}| j
                  j                  ||dj                  |      ||      }| j                  j                  |       y )	Nz"{}""z\"退 z"filled,rounded"diamond#{:06x}style	fillcolorshapelabel)	strr   r[   valuereplacer>  NoderC  add_noder)   r6   graph_node_idgraph_node_labelgraph_node_colorgraph_node_stylegraph_node_shape
graph_nodes           r   r   z%ForestToPyDotVisitor.visit_token_node  s    BtH#??4::+=+=c5+IJ#/$ZZ__]:JV_VfVfgwVx  AQ  Yi_  j


J'r   c              #   "  K   t        t        |            }t        |      }d}d}d}| j                  j	                  ||dj                  |      ||      }| j                  j                  |       |j                   |j                   y w)NrL  filledrM  rN  rO  )
rT  r   r   r>  rW  r[   rC  rX  r1   r2   rY  s           r   r   z)ForestToPyDotVisitor.visit_packed_node_in  s     BtH:##$ZZ__]:JV_VfVfgwVx  AQ  Yi_  j


J'iijjs   BBc           	         t        t        |            }| j                  j                  |      d   }|j                  |j
                  fD ]  }|t        t        t        |t              r|j                  n|            }| j                  j                  |      d   }| j                  j                  | j                  j                  ||             t        t        dd            }d}| j                  j                  ||d      }d}| j                  j                  |       | j                  j                  | j                  j                  |||              y )Nr   l      @*_kzcP l   
~l!]c invisNone)rP  rS  )rP  )rT  r   rC  get_noder1   r2   r'   r   r   add_edger>  Edger   rW  rX  )	r)   r6   rZ  r_  r   child_graph_node_idchild_graph_nodechild_graph_node_stylechild_edge_styles	            r   r   z*ForestToPyDotVisitor.visit_packed_node_out  s!   BtHZZ((7:
ii, 	kE &)"Jui<XU[[^c*d&e##'::#6#67J#KA#N 

##DJJOOJ@P$QR '*'2PQo*p&q#)0&#'::??3FNdlr?#s #* 

##$45

##DJJOOJ@PXhO$ij	kr   c                 (   t        t        |            }t        |      }d}d}|j                  rd}nd}| j                  j                  ||dj                  |      ||      }| j                  j                  |       t        |j                        S )NrL  z"filled"ellipse	rectanglerN  rO  )rT  r   r   r#   r>  rW  r[   rC  rX  rJ   rB   rY  s           r   r   z)ForestToPyDotVisitor.visit_symbol_node_in  s    BtH:#'(*ZZ__]:JV_VfVfgwVx  AQ  Yi_  j


J'DMM""r   c                 X   t        t        |            }| j                  j                  |      d   }|j                  D ]i  }t        t        |            }| j                  j                  |      d   }| j                  j                  | j                  j                  ||             k y r   )rT  r   rC  re  rB   rf  r>  rg  )r)   r6   rZ  r_  r   rh  ri  s          r   r   z*ForestToPyDotVisitor.visit_symbol_node_out  s    BtHZZ((7:
]] 	OE"%bi.#zz223FGJJJ


<L MN	Or   )TB)r   r   r   rc   r*   r   r   r   r   r   r   r   r   s   @r   r<  r<    s.    K
5(	k"#Or   r<  N)$rc   typingr   r   randomr   collectionsr   operatorr   	importlibr   	functoolsr	   parse_tree_builderr   visitorsr   utilsr   r   treer   r   r   ri   r.   r   r   r   r   r   r   r'  r*  r<  r   r   r   <module>r{     s    %    #  >  & 	 	OV OVbz >] >]@ 
  <^. ^.@NF NFb!G} !GF% %*D9) D9LR- RhMO= MOr   