
    z                     f   S r SSKJr  SSKJr  SSKJr  SSKJr  SSK	J
r
  SSKJr  SS	KJr  SS
KJr  SSKJr   " S S5      r " S S\5      r " S S\5      r " S S\5      r " S S5      r " S S\5      r " S S\5      r " S S5      r " S S\5      rS r " S S \5      r " S! S"\5      rg#)$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/
    )randint)deque)
attrgetter)import_module)partial   )AmbiguousIntermediateExpander)Discard)logger)Treec                       \ rS rSrSrg)
ForestNode    N__name__
__module____qualname____firstlineno____static_attributes__r       -lib/third_party/lark/parsers/earley_forest.pyr   r      s    r   r   c                   l    \ rS rSrSrSrS rS rS rS r	\
S 5       r\
S	 5       rS
 rS rS rS rSrg)
SymbolNode   ax  
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: The index of the start of the substring matched by this symbol (inclusive).
    end: 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.
)	sstartend	_childrenpathspaths_loadedpriorityis_intermediate_hashc                    Xl         X l        X0l        [        5       U l        [        5       U l        SU l        [        S5      U l        [        U[        5      U l        [        U R                   U R                  U R                  45      U l        g )NF-inf)r   r   r   setr   r    r!   floatr"   
isinstancetupler#   hashr$   )selfr   r   r   s       r   __init__SymbolNode.__init__0   sf    
U
! f)!U34664::txx89
r   c           
      P    U R                   R                  [        XX#XE5      5        g N)r   add
PackedNode)r,   lr0ruler   leftrights         r   
add_familySymbolNode.add_family>   s    :ddJKr   c                 <    U R                   R                  X45        g r0   )r    r1   )r,   
transitivenodes      r   add_pathSymbolNode.add_pathA   s    


)*r   c                    U R                    GHN  u  pUR                  b  [        UR                  R                  UR                  R                  U R
                  5      nUR                  UR                  U5        U R                  UR                  R                  R                  UR                  R                  UR                  R                  UR                  R                  U5        M  U R                  UR                  R                  R                  UR                  R                  UR                  R                  UR                  R                  U5        GMQ     SU l        g )NT)r    
next_titemr   r   r   r   r<   r7   	reductionr4   originr;   r!   )r,   r:   r;   vns       r   
load_pathsSymbolNode.load_pathsD   s:    $

J$$0
 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 !+ !r   c                 2    [        U R                  5      S:  $ )z'Returns True if this node is ambiguous.   )lenchildrenr,   s    r   is_ambiguousSymbolNode.is_ambiguousN   s     4==!A%%r   c                 ~    U R                   (       d  U R                  5         [        U R                  [	        S5      S9$ )zNReturns a list of this node's children sorted from greatest to
least priority.sort_key)key)r!   rC   sortedr   r   rI   s    r   rH   SymbolNode.childrenS   s-       OOdnn*Z*@AAr   c                 ,    [        U R                  5      $ r0   )iterr   rI   s    r   __iter__SymbolNode.__iter__[   s    DNN##r   c                 V   [        U[        5      (       d  gXL =(       d    [        U R                  5      [        UR                  5      :H  =(       aX    U R                  UR                  :H  =(       a8    U R                  UR                  :H  =(       a    U R
                  UR
                  L $ NF)r)   r   typer   r   r   r,   others     r   __eq__SymbolNode.__eq__^   s    %,,}  Ndffegg!>  "M466UWWCT  "MY]YcYcglgrgrYr  "Mw{ww  DI  DM  DM  xM  	Nr   c                     U R                   $ r0   r$   rI   s    r   __hash__SymbolNode.__hash__c       zzr   c                    U R                   (       a  U R                  S   nU R                  S   nS UR                  S U  5       nS UR                  US   5       nSR                  UR                  R
                  SR                  U5      SR                  U5      5      nOU R                  R
                  nSR                  XPR                  U R                  U R                  5      $ )Nr   rF   c              3   8   #    U  H  oR                   v   M     g 7fr0   name.0	expansions     r   	<genexpr>&SymbolNode.__repr__.<locals>.<genexpr>j        M7K)~~7K   c              3   8   #    U  H  oR                   v   M     g 7fr0   rc   re   s     r   rh   ri   k        L6Jnn6Jrk   {} ::= {}* {} ({}, {}, {}, {}))
r#   r   rg   formatrA   rd   joinr   r   r"   r,   r4   ptrbeforeaftersymbols         r   __repr__SymbolNode.__repr__f   s    66!9D&&)CMt~~ds7KMFLdnnST6JLE$++DKK,<,<chhv>NPSPXPXY^P_`FVV[[F!((TXXt}}UUr   )	r   r$   r   r#   r    r!   r"   r   r   N)r   r   r   r   __doc__	__slots__r-   r7   r<   rC   propertyrJ   rH   rS   rZ   r^   rx   r   r   r   r   r   r      sd    , tI:L+! & & B B$N
	Vr   r   c                   j    \ rS rSrSrSrS r\S 5       r\S 5       r	\S 5       r
S rS	 rS
 rS rSrg)r2   q   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   r4   r   r5   r6   r"   r$   c                     Xl         X l        X@l        X0l        XPl        X`l        [        S5      U l        [        U R                  U R
                  45      U l	        g )Nr&   )
r   r   r   r4   r5   r6   r(   r"   r+   r$   )r,   r   r   r4   r   r5   r6   s          r   r-   PackedNode.__init__}   sD    
		
f499djj12
r   c                 H    U R                   S L =(       a    U R                  S L $ r0   r5   r6   rI   s    r   is_emptyPackedNode.is_empty   s    yyD 7TZZ4%77r   c                 ^    U R                   U R                  * U R                  R                  4$ )z
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.
)r   r"   r4   orderrI   s    r   rM   PackedNode.sort_key   s#     }}t}}ndiioo==r   c                 f    U R                   U R                  4 Vs/ s H	  oc  M  UPM     sn$ s  snf )z'Returns a list of this node's children.r   )r,   xs     r   rH   PackedNode.children   s+     !IItzz2D2a2DDDs   ..c              #   D   #    U R                   v   U R                  v   g 7fr0   r   rI   s    r   rS   PackedNode.__iter__        iijj    c                     [        U[        5      (       d  gXL =(       d9    U R                  UR                  :H  =(       a    U R                  UR                  :H  $ rV   )r)   r2   r5   r6   rX   s     r   rZ   PackedNode.__eq__   s>    %,,}Wejj!8!VTZZ5;;=VWr   c                     U R                   $ r0   r]   rI   s    r   r^   PackedNode.__hash__   r`   r   c                    [        U R                  [        5      (       a  U R                  S   nU R                  S   nS UR                  S U  5       nS UR                  US   5       nSR	                  UR
                  R                  SR                  U5      SR                  U5      5      nOU R                  R                  nSR	                  XPR                  U R                  U R                  R                  5      $ )Nr   rF   c              3   8   #    U  H  oR                   v   M     g 7fr0   rc   re   s     r   rh   &PackedNode.__repr__.<locals>.<genexpr>   rj   rk   c              3   8   #    U  H  oR                   v   M     g 7fr0   rc   re   s     r   rh   r      rm   rk   rn   ro   rp   )r)   r   r*   rg   rq   rA   rd   rr   r   r"   r4   r   rs   s         r   rx   PackedNode.__repr__   s    dffe$$66!9D&&)CMt~~ds7KMFLdnnST6JLE$++DKK,<,<chhv>NPSPXPXY^P_`FVV[[F!((T]]DIIOO\\r   )r$   r5   r   r"   r6   r4   r   r   N)r   r   r   r   rz   r{   r-   r|   r   rM   rH   rS   rZ   r^   rx   r   r   r   r   r2   r2   q   sh    	 WI3 8 8 > > E EX
	]r   r2   c                   8    \ rS rSrSrSrS
S jrS rS rS r	S	r
g)	TokenNode   z
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"   r$   Nc                 |    Xl         X l        Ub  X0l        OUb  UR                  OSU l        [        U5      U l        g Nr   )r   r   r"   r+   r$   )r,   r   r   r"   s       r   r-   TokenNode.__init__   s4    
	$M-1-=DMM1DM%[
r   c                 t    [        U[        5      (       d  gXL =(       d    U R                  UR                  :H  $ rV   )r)   r   r   rX   s     r   rZ   TokenNode.__eq__   s,    %++};u{{!:;r   c                     U R                   $ r0   r]   rI   s    r   r^   TokenNode.__hash__   r`   r   c                 ,    [        U R                  5      $ r0   )reprr   rI   s    r   rx   TokenNode.__repr__   s    DJJr   )r$   r"   r   r   r0   )r   r   r   r   rz   r{   r-   rZ   r^   rx   r   r   r   r   r   r      s"     7I!<
 r   r   c                   R    \ rS rSrSrSS jrS rS rS rS r	S r
S	 rS
 rS rSrg)ForestVisitor   as  
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                     Xl         g r0   single_visit)r,   r   s     r   r-   ForestVisitor.__init__   s    (r   c                     g)zFCalled when a ``Token`` is visited. ``Token`` nodes are always leaves.Nr   r,   r;   s     r   visit_token_nodeForestVisitor.visit_token_node   s    r   c                     g)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_in"ForestVisitor.visit_symbol_node_in       
 	r   c                     g)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_out#ForestVisitor.visit_symbol_node_out   r   r   c                     g)z_Called when a packed node is visited. Nodes that are returned
will be scheduled to be visited. Nr   r   s     r   visit_packed_node_in"ForestVisitor.visit_packed_node_in        	r   c                     g)zeCalled after all nodes returned from a corresponding ``visit_packed_node_in``
call have been visited.Nr   r   s     r   visit_packed_node_out#ForestVisitor.visit_packed_node_out   r   r   c                     g)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,   r;   paths      r   on_cycleForestVisitor.on_cycle  s     	r   c                     [        U5      S-
  n[        X#   5      [        U5      :w  a!  US-  n[        X#   5      [        U5      :w  a  M!  X#S $ )z}A utility function for use in ``on_cycle`` to obtain a slice of
``path`` that only contains the nodes that make up the cycle.rF   N)rG   id)r,   r;   r   indexs       r   get_cycle_in_pathForestVisitor.get_cycle_in_path  sJ     D	AoD)QJE oD)F|r   c                 |   [        5       n[        5       n/ n[        U/5      n[        U S5      n[        U S5      n[        U S5      n[        U S5      n	[        U SU5      n
[        U SU	5      n[        U S5      n[        U S5      nU(       aQ  [        [	        U5      5      n [        U5      nUc  M,  [        U5      U;   a
  U" X5        ME  UR                  U5        MX  g ! [         a    UR                  5          Mv  [         a     Of = f[        U[        5      (       a$  U" UR                  5        UR                  5         M  [        U5      nUU;   a  [        U[        5      (       a	  U" U5        O"UR                  (       a	  U
" U5        OU" U5        UR                  5         UR                  5         UR                  U5        UR!                  U5        OU R"                  (       a  UU;   a  UR                  5         OUR!                  U5        UR                  U5        [        U[        5      (       a	  U" U5      nO"UR                  (       a	  U" U5      nOU	" U5      nUc  GM  [        U[$        5      (       d  ['        U5      nO[        U5      U;   a  U" X5        GM  UR                  U5        U(       a  GM1  g )	Nr   r   r   r   visit_intermediate_node_outvisit_intermediate_node_inr   r   )r'   r   getattrnextreversedr   appendStopIterationpop	TypeErrorr)   r   r   r2   r#   remover1   r   r   rR   )r,   rootvisitingvisitedr   input_stackvpnovpnivsnovsnivinovinivtnoccurrent	next_node
current_ids                    r   visitForestVisitor.visit  sT    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2M,,MM!

+J'""zW'<!Z(G$gz22 $WI,, $WI $WI$!)Z88 $YI	]h.y'""9-u ks   !C D;	DDr   N)F)r   r   r   r   rz   r-   r   r   r   r   r   r   r   r   r   r   r   r   r   r      s5    $)


X.r   r   c                   t   ^  \ rS rSrSrU 4S jrS rS rS rS r	S r
S	 rS
 rS rS rS rS rS rSrU =r$ )ForestTransformerio  a  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   > [         [        U ]  5         [        5       U l        [        5       U l        g r0   )superr   r-   dictdatar   
node_stackr,   	__class__s    r   r-   ForestTransformer.__init__  s#    /1F	'r   c                    U R                   R                  S5        / U R                  S'   U R                  U5        [	        U R                  S   5      S::  d   eU R                  S   (       a  U R                  S   S   $ g)z$Perform a transformation on an SPPF.resultrF   r   N)r   r   r   r   rG   )r,   r   s     r   	transformForestTransformer.transform  so    x( 		(

4499X&'1,,,99X99X&q)) r   c                     U$ )zTransform a symbol node.r   r,   r;   r   s      r   transform_symbol_node'ForestTransformer.transform_symbol_node      r   c                     U$ )zTransform an intermediate node.r   r   s      r   transform_intermediate_node-ForestTransformer.transform_intermediate_node  r   r   c                     U$ )zTransform a packed node.r   r   s      r   transform_packed_node'ForestTransformer.transform_packed_node  r   r   c                     U$ )zTransform a ``Token``.r   r   s     r   transform_token_node&ForestTransformer.transform_token_node  r   r   c                     U R                   R                  [        U5      5        / U R                  [        U5      '   UR                  $ r0   r   r   r   r   rH   r   s     r   r   &ForestTransformer.visit_symbol_node_in  4    r$x( 		"T(}}r   c                     U R                   R                  [        U5      5        / U R                  [        U5      '   UR                  $ r0   r  r   s     r   r   &ForestTransformer.visit_packed_node_in  r  r   c                     U R                  U5      nU[        La,  U R                  U R                  S      R	                  U5        g g N)r  r
   r   r   r   )r,   r;   transformeds      r   r   "ForestTransformer.visit_token_node  s?    //5g%IIdoob)*11+> &r   c                    U R                   R                  5         U" XR                  [        U5         5      nU[        La+  U R                  U R                   S      R                  U5        U R                  [        U5      	 g r
  )r   r   r   r   r
   r   )r,   r;   methodr  s       r   _visit_node_out_helper(ForestTransformer._visit_node_out_helper  sa    T99RX#67g%IIdoob)*11+>IIbhr   c                 :    U R                  XR                  5        g r0   )r  r   r   s     r   r   'ForestTransformer.visit_symbol_node_out      ##D*D*DEr   c                 :    U R                  XR                  5        g r0   )r  r   r   s     r   r   -ForestTransformer.visit_intermediate_node_out  s    ##D*J*JKr   c                 :    U R                  XR                  5        g r0   )r  r   r   s     r   r   'ForestTransformer.visit_packed_node_out  r  r   )r   r   )r   r   r   r   rz   r-   r   r   r   r   r  r   r   r   r  r   r   r   r   __classcell__r   s   @r   r   r   o  sR     "*

?
 FLF Fr   r   c                   D   ^  \ rS rSrSrU 4S jrS rS rS rS r	Sr
U =r$ )	ForestSumVisitori  aA  
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                 (   > [         [        U ]  SS9  g )NTr   )r   r  r-   r   s    r   r-   ForestSumVisitor.__init__  s    .D.Ar   c              #   D   #    UR                   v   UR                  v   g 7fr0   r   r   s     r   r   %ForestSumVisitor.visit_packed_node_in  r   r   c                 ,    [        UR                  5      $ r0   )rR   rH   r   s     r   r   %ForestSumVisitor.visit_symbol_node_in  s    DMM""r   c                 <   UR                   R                  (       dE  UR                  R                  R                  (       a   UR                  R                  R                  OSnU[        UR                  SS5      -  nU[        UR                  SS5      -  nX!l        g )Nr   r"   )r   r#   r4   optionsr"   r   r6   r5   )r,   r;   r"   s      r   r   &ForestSumVisitor.visit_packed_node_out  sn    59[[5P5PUYU^U^UfUfUoUo499$$--uvGDJJ
A66GDIIz155 r   c                 F    [        S UR                   5       5      Ul        g )Nc              3   8   #    U  H  oR                   v   M     g 7fr0   )r"   )rf   childs     r   rh   9ForestSumVisitor.visit_symbol_node_out.<locals>.<genexpr>  s     FuNNrk   )maxrH   r"   r   s     r   r   &ForestSumVisitor.visit_symbol_node_out  s    FFFr   r   )r   r   r   r   rz   r-   r   r   r   r   r   r  r  s   @r   r  r    s)    B#!G Gr   r  c                   @    \ rS rSrSr " S S5      r\" 5       rS rSrg)
PackedDatai  zuUsed in transformationss of packed nodes to distinguish the data
that comes from the left child and the right child.
c                       \ rS rSrSrg)PackedData._NoDatai  r   Nr   r   r   r   _NoDatar/    s    r   r0  c                     U R                   U l        U R                   U l        U(       a=  UR                  b%  US   U l        [        U5      S:  a  US   U l        g g US   U l        g g )Nr   rF   )NO_DATAr5   r6   rG   r   s      r   r-   PackedData.__init__  s]    LL	\\
yy$ G	t9q=!%aDJ ! "!W
 r   r   N)	r   r   r   r   rz   r0  r2  r-   r   r   r   r   r-  r-    s      iG	%r   r-  c                      ^  \ rS rSrSr\\" 5       \" 5       SS4U 4S jjrU 4S jr	S r
S rS rS	 rS
 rS rS rS rU 4S jrU 4S jrU 4S jrSrU =r$ )ForestToParseTreei  aK  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                    > [         [        U ]  5         Xl        X l        X0l        X@l        XPl        0 U l        SU l	        S U l
        [        5       U l        g rV   )r   r5  r-   
tree_class	callbacksprioritizerresolve_ambiguity
_use_cache_cache_on_cycle_retreat_cycle_noder'   _successful_visits)r,   r7  r8  r9  r:  	use_cacher   s         r   r-   ForestToParseTree.__init__  sM    /1$"&!2#!&"%%r   c                    > U R                   (       a  U R                   R                  U5        [        [        U ]  U5        0 U l        g r0   )r9  r   r   r5  r<  )r,   r   r   s     r   r   ForestToParseTree.visit  s7    ""4(,T2r   c                 L    [         R                  " SU5        Xl        SU l        g )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   ForestToParseTree.on_cycle  s(     @AE	G  !%r   c                     U R                   (       aP  [        U5      [        U R                  5      :X  d  [        U5      U R                  ;   a  S U l        SU l         g [        $ g rV   )r=  r   r>  r?  r
   r   s     r   _check_cycleForestToParseTree._check_cycle  sM    !!$x2d..//2d8t?V?V3V#' ).& "r   c                     / nU HE  n[        US5      (       a   UR                  S:X  a  X#R                  -  nM4  UR                  U5        MG     U$ )Nr   _ambig)hasattrr   rH   r   )r,   rH   new_childrenr(  s       r   _collapse_ambig!ForestToParseTree._collapse_ambig&  sK    Euf%%%***@.##E*	 
 r   c                 @    U R                   UR                     " U5      $ r0   )r8  r4   r   s      r   _call_rule_func!ForestToParseTree._call_rule_func/  s     ~~dii(..r   c                 h    [        U5      S:  a  U R                  SU5      $ U(       a  US   $ [        $ )NrF   rK  r   rG   r7  r
   r   s      r   _call_ambig_func"ForestToParseTree._call_ambig_func5  s1     t9q=??8T227Nr   c                    [        U5      U R                  ;  a  [        $ U R                  U5      nU[        L a  U$ U R                  R	                  [        U5      5        U R                  U5      nU R                  X5      $ r0   )r   r?  r
   rH  r   rN  rU  )r,   r;   r   rs       r   r   'ForestToParseTree.transform_symbol_node?  sn    d84222Nd#<H&&r$x0##D)$$T00r   c                 X   [        U5      U R                  ;  a  [        $ U R                  U5      nU[        L a  U$ U R                  R	                  [        U5      5        [        U5      S:  a3  U Vs/ s H  o@R                  SU5      PM     nnU R                  SU5      $ US   $ s  snf )NrF   _inter_iambigr   )r   r?  r
   rH  r   rG   r7  )r,   r;   r   rX  crH   s         r   r   -ForestToParseTree.transform_intermediate_nodeI  s    d84222Nd#<H&&r$x0t9q=>BCd!4dHC??9h77Aw Ds   3B'c                    U R                  U5      nU[        L a  U$ U R                  (       a)  [        UR                  5      U R
                  ;   a  [        $ U R                  (       a1  [        U5      U R                  ;   a  U R                  [        U5         $ / n[        U5      S::  d   e[        X5      nUR                  [        R                  Lad  UR                  R                  (       a.  [        UR                  [        5      (       a  XBR                  -  nOUR                  UR                  5        UR                   [        R                  La  UR                  UR                   5        UR                  R                  (       a%  U R                  R#                  [        U5      U5      $ U R                  R#                  [        U5      U R%                  X5      5      $ )Nr   )rH  r
   r:  r   r   r?  r;  r<  rG   r-  r5   r2  r#   r)   listr   r6   
setdefaultrQ  )r,   r;   r   rX  rH   s        r   r   'ForestToParseTree.transform_packed_nodeU  sD   d#<H!!bo9P9P&PN??r$x4;;6;;r$x((4yA~~$%99J...yy((Z		4-H-HII%		*::Z///OODJJ';;&&;;))"T(H=={{%%bh0D0DT0TUUr   c                 f   > [         [        U ]  U5        U R                  (       a  g UR                  $ r0   )r   r5  r   r=  rH   r,   r;   r   s     r   r   &ForestToParseTree.visit_symbol_node_ink  s)    ;DA!!}}r   c                    > SU l         [        [        U ]  U5      nU R                  (       a#  [        UR                  5      U R                  ;  a-  U R                  (       a  [        U5      U R                  ;  a  U$ g g rV   )
r=  r   r5  r   r:  r   r   r?  r;  r<  )r,   r;   to_visitr   s      r   r   &ForestToParseTree.visit_packed_node_inq  sb    !&*DFtL%%DKK@W@W)W??bhdkk&A 'B *Xr   c                    > [         [        U ]  U5        U R                  (       d/  U R                  R                  [        UR                  5      5        g g r0   )r   r5  r   r=  r?  r1   r   r   rd  s     r   r   'ForestToParseTree.visit_packed_node_outx  s=    <TB%%##''4;;8 &r   )	r<  r>  r=  r?  r;  r8  r9  r:  r7  )r   r   r   r   rz   r   r   r  r-   r   r   rH  rN  rQ  rU  r   r   r   r   r   r   r   r  r  s   @r   r5  r5    sh    
 #'$&FVFXlp  }A 
(&/1
V, 9 9r   r5  c                     SU l         U $ )zDecorator for methods of subclasses of ``TreeForestTransformer``.
Denotes that the method should receive a list of transformed derivations.T)handles_ambiguity)funcs    r   rl  rl  }  s     "DKr   c                   f   ^  \ rS rSrSr\\" 5       SS4U 4S jjrS rS r	S r
S	 rS
 rS rSrU =r$ )TreeForestTransformeri  a  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                 B   > [         [        U ]  U[        5       X#U5        g r0   )r   ro  r-   r   )r,   r7  r9  r:  r@  r   s        r   r-   TreeForestTransformer.__init__  s    #T3Jhqrr   c                 $    U R                  X5      $ )z[Default operation on tree (for override).

Returns a tree with name with data as children.
)r7  r,   rd   r   s      r   __default__!TreeForestTransformer.__default__  s    
 t**r   c                 h    [        U5      S:  a  U R                  SU5      $ U(       a  US   $ [        $ )z{Default operation on ambiguous rule (for override).

Wraps data in an '_ambig_' node if it contains more than
one element.
rF   rK  r   rT  rs  s      r   __default_ambig__'TreeForestTransformer.__default_ambig__  s1     t9q=??8T227Nr   c                     U$ )zBDefault operation on ``Token`` (for override).

Returns ``node``.
r   r   s     r   __default_token__'TreeForestTransformer.__default_token__  s	    
 r   c                 N    [        XR                  U R                  5      " U5      $ r0   )r   rW   rz  r   s     r   r  *TreeForestTransformer.transform_token_node  s    tYY(>(>?EEr   c                    UR                   R                  =(       dG    UR                   R                  R                  =(       d     UR                   R                  R
                  n[        XU R                  5      nX@R                  :X  d  [        US5      (       a  [        U R                  U5      nU R                  (       d"  [        [        U R                  5      nU" U5      nU" U5      $ Nrl  )r4   aliasr$  template_sourcerA   rd   r   rt  rL  r   r:  r	   r7  )r,   r;   r   rd   	user_funcwrappers         r   rQ  %TreeForestTransformer._call_rule_func  s    yy\$))"3"3"C"C\tyyGWGWG\G\D(8(89	(((GI?R,S,S 0 0$7I%%;T__MG	*Ir   c                     UR                   R                  n[        XU R                  5      nX@R                  :X  d  [	        US5      (       d  [        U R                  U5      nU" U5      $ r  )r   rd   r   rw  rL  r   )r,   r;   r   rd   r  s        r   rU  &TreeForestTransformer._call_ambig_func  sV    vv{{D(>(>?	...giI\6]6] 6 6=Ir   r   )r   r   r   r   rz   r   r  r-   rt  rw  rz  r  rQ  rU  r   r  r  s   @r   ro  ro    sD     D #'4D4FZ^jo s+
F r   ro  c                   Z   ^  \ rS rSrSrSU 4S jjrU 4S jrS rS rS r	S r
S	 rS
rU =r$ )ForestToPyDotVisitori  z
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                    > [         [        U ]  SS9  [        S5      U l        U R                  R                  SUS9U l        g )NTr   pydotdigraph)
graph_typerankdir)r   r  r-   r   r  Dotgraph)r,   r  r   s     r   r-   ForestToPyDotVisitor.__init__  s:    "D22E"7+
ZZ^^y'^J
r   c                    > [         [        U ]  U5         U R                  R	                  U5        g ! [
         a!  n[        R                  " SU5         S nAg S nAff = f)NzCould not write png: )r   r  r   r  	write_pngFileNotFoundErrorr   error)r,   r   filenameer   s       r   r   ForestToPyDotVisitor.visit  sL    "D/5	5JJ  *  	5LL0!44	5s   2 
AAAc                    [        [        U5      5      nSR                  UR                  R	                  SS5      5      nSnSnSnU R
                  R                  X%SR                  U5      XcS9nU R                  R                  U5        g )	Nz"{}""z\"退 z"filled,rounded"diamond#{:06x}style	fillcolorshapelabel)	strr   rq   valuereplacer  Noder  add_noder,   r;   graph_node_idgraph_node_labelgraph_node_colorgraph_node_stylegraph_node_shape
graph_nodes           r   r   %ForestToPyDotVisitor.visit_token_node  s    BtH#??4::+=+=c5+IJ#/$ZZ__]V_VfVfgwVx  AQ_  j


J'r   c              #     #    [        [        U5      5      n[        U5      nSnSnSnU R                  R	                  X%SR                  U5      XcS9nU R                  R                  U5        UR                  v   UR                  v   g 7f)Nr  filledr  r  r  )
r  r   r   r  r  rq   r  r  r5   r6   r  s           r   r   )ForestToPyDotVisitor.visit_packed_node_in  s     BtH:##$ZZ__]V_VfVfgwVx  AQ_  j


J'iijjs   BB
c           	         [        [        U5      5      nU R                  R                  U5      S   nUR                  UR
                  4 GH  nUb  [        [        [        U[        5      (       a  UR                  OU5      5      nU R                  R                  U5      S   nU R                  R                  U R                  R                  X65      5        M  [        [        SS5      5      nSnU R                  R                  XWSS9nSnU R                  R                  U5        U R                  R                  U R                  R                  X6US95        GM     g )Nr   l      @*_kzcP l   
~l!]c invisNone)r  r  )r  )r  r   r  get_noder5   r6   r)   r   r   add_edger  Edger   r  r  )	r,   r;   r  r  r(  child_graph_node_idchild_graph_nodechild_graph_node_stylechild_edge_styles	            r   r   *ForestToPyDotVisitor.visit_packed_node_out   s   BtHZZ((7:
ii,E &)"Jui<X<XU[[^c*d&e##'::#6#67J#KA#N 

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

##$45

##DJJOOJXhO$ij -r   c                 (   [        [        U5      5      n[        U5      nSnSnUR                  (       a  SnOSnU R                  R                  X%SR                  U5      XcS9nU R                  R                  U5        [        UR                  5      $ )Nr  z"filled"ellipse	rectangler  r  )r  r   r   r#   r  r  rq   r  r  rR   rH   r  s           r   r   )ForestToPyDotVisitor.visit_symbol_node_in  s    BtH:#'(*ZZ__]V_VfVfgwVx  AQ_  j


J'DMM""r   c                 Z   [        [        U5      5      nU R                  R                  U5      S   nUR                   Hi  n[        [        U5      5      nU R                  R                  U5      S   nU R                  R                  U R                  R                  X65      5        Mk     g r   )r  r   r  r  rH   r  r  r  )r,   r;   r  r  r(  r  r  s          r   r   *ForestToPyDotVisitor.visit_symbol_node_out  s~    BtHZZ((7:
]]E"%bi.#zz223FGJJJ


 MN #r   )r  r  )TB)r   r   r   r   rz   r-   r   r   r   r   r   r   r   r  r  s   @r   r  r    s4    K
5(	k"#O Or   r  N)rz   randomr   collectionsr   operatorr   	importlibr   	functoolsr   parse_tree_builderr	   visitorsr
   utilsr   treer   r   r   r2   r   r   r   r  r-  r5  rl  ro  r  r   r   r   <module>r     s       #  >   	 	WV WVr>] >]@ 
  <^. ^.@NF NFb!G} !GF% %*C9) C9JR- RhMO= MOr   