
    /h                     v   S r SSKrSSKrSSKrSSKJr  SSKJrJr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      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 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+ jr#\" 5       \" 5       \" 5       \" 5       /r$\" 5       \ " 5       \" 5       \" 5       /r%\" 5       \ " 5       \" 5       \" 5       /r&\" 5       \"" 5       \!" 5       /r' " S, S-\5      r( " S. S/\(5      r) " S0 S1\(5      r* " S2 S3\(5      r+ " S4 S5\(5      r, " S6 S7\(5      r-S8 r.       S<S9 jr/\0S::X  a  \/" 5         gg)=a  
Data classes and parser implementations for "chart parsers", which
use dynamic programming to efficiently parse a text.  A chart
parser derives parse trees for a text by iteratively adding "edges"
to a "chart."  Each edge represents a hypothesis about the tree
structure for a subsequence of the text.  The chart is a
"blackboard" for composing and combining these hypotheses.

When a chart parser begins parsing a text, it creates a new (empty)
chart, spanning the text.  It then incrementally adds new edges to the
chart.  A set of "chart rules" specifies the conditions under which
new edges should be added to the chart.  Once the chart reaches a
stage where none of the chart rules adds any new edges, parsing is
complete.

Charts are encoded with the ``Chart`` class, and edges are encoded with
the ``TreeEdge`` and ``LeafEdge`` classes.  The chart parser module
defines three chart parsers:

  - ``ChartParser`` is a simple and flexible chart parser.  Given a
    set of chart rules, it will apply those rules to the chart until
    no more edges are added.

  - ``SteppingChartParser`` is a subclass of ``ChartParser`` that can
    be used to step through the parsing process.
    N)total_ordering)PCFGis_nonterminalis_terminal)raise_unorderable_types)ParserI)Tree)OrderedDictc                   r    \ 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S rS rS rS rS rSrg)EdgeI6   ay  
A hypothesis about the structure of part of a sentence.
Each edge records the fact that a structure is (partially)
consistent with the sentence.  An edge contains:

- A span, indicating what part of the sentence is
  consistent with the hypothesized structure.
- A left-hand side, specifying what kind of structure is
  hypothesized.
- A right-hand side, specifying the contents of the
  hypothesized structure.
- A dot position, indicating how much of the hypothesized
  structure is consistent with the sentence.

Every edge is either complete or incomplete:

- An edge is complete if its structure is fully consistent
  with the sentence.
- An edge is incomplete if its structure is partially
  consistent with the sentence.  For every incomplete edge, the
  span specifies a possible prefix for the edge's structure.

There are two kinds of edge:

- A ``TreeEdge`` records which trees have been found to
  be (partially) consistent with the text.
- A ``LeafEdge`` records the tokens occurring in the text.

The ``EdgeI`` interface provides a common interface to both types
of edge, allowing chart parsers to treat them in a uniform manner.
c                 B    U R                   [        :X  a  [        S5      eg )NzEdge is an abstract interface)	__class__r   	TypeErrorselfs    H/var/www/auris/envauris/lib/python3.13/site-packages/nltk/parse/chart.py__init__EdgeI.__init__X   s    >>U";<< #    c                     [        5       e)z
Return a tuple ``(s, e)``, where ``tokens[s:e]`` is the
portion of the sentence that is consistent with this
edge's structure.

:rtype: tuple(int, int)
NotImplementedErrorr   s    r   span
EdgeI.span`        "##r   c                     [        5       e)z:
Return the start index of this edge's span.

:rtype: int
r   r   s    r   startEdgeI.startj        "##r   c                     [        5       e)z8
Return the end index of this edge's span.

:rtype: int
r   r   s    r   end	EdgeI.endr   r    r   c                     [        5       e)z5
Return the length of this edge's span.

:rtype: int
r   r   s    r   lengthEdgeI.lengthz   r    r   c                     [        5       e)z
Return this edge's left-hand side, which specifies what kind
of structure is hypothesized by this edge.

:see: ``TreeEdge`` and ``LeafEdge`` for a description of
    the left-hand side values for each edge type.
r   r   s    r   lhs	EdgeI.lhs   r   r   c                     [        5       e)z
Return this edge's right-hand side, which specifies
the content of the structure hypothesized by this edge.

:see: ``TreeEdge`` and ``LeafEdge`` for a description of
    the right-hand side values for each edge type.
r   r   s    r   rhs	EdgeI.rhs   r   r   c                     [        5       e)z
Return this edge's dot position, which indicates how much of
the hypothesized structure is consistent with the
sentence.  In particular, ``self.rhs[:dot]`` is consistent
with ``tokens[self.start():self.end()]``.

:rtype: int
r   r   s    r   dot	EdgeI.dot        "##r   c                     [        5       e)z~
Return the element of this edge's right-hand side that
immediately follows its dot.

:rtype: Nonterminal or terminal or None
r   r   s    r   nextsymEdgeI.nextsym        "##r   c                     [        5       e)zW
Return True if this edge's structure is fully consistent
with the text.

:rtype: bool
r   r   s    r   is_completeEdgeI.is_complete   r4   r   c                     [        5       e)z[
Return True if this edge's structure is partially consistent
with the text.

:rtype: bool
r   r   s    r   is_incompleteEdgeI.is_incomplete   r4   r   c                 r    U R                   UR                   L =(       a    U R                  UR                  :H  $ N)r   _comparison_keyr   others     r   __eq__EdgeI.__eq__   s0    NNeoo- >$$(=(==	
r   c                     X:X  + $ r<    r>   s     r   __ne__EdgeI.__ne__   s      r   c                    [        U[        5      (       d  [        SX5        U R                  UR                  L a  U R                  UR                  :  $ U R                  R
                  UR                  R
                  :  $ )N<)
isinstancer   r   r   r=   __name__r>   s     r   __lt__EdgeI.__lt__   s_    %''#C5>>U__,''%*?*???>>**U__-E-EEEr   c                      U R                   $ ! [         a)    [        U R                  5      U l         U R                   s $ f = fr<   )_hashAttributeErrorhashr=   r   s    r   __hash__EdgeI.__hash__   s<    	:: 	d223DJ::	s    0A A)rM   N)rI   
__module____qualname____firstlineno____doc__r   r   r   r"   r%   r(   r+   r.   r2   r6   r9   r@   rD   rJ   rP   __static_attributes__rC   r   r   r   r   6   sT    @=$$$$$$	$$$$
!Fr   r   c                       \ rS rSrSrSS jr\S 5       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Srg)TreeEdge   a  
An edge that records the fact that a tree is (partially)
consistent with the sentence.  A tree edge consists of:

- A span, indicating what part of the sentence is
  consistent with the hypothesized tree.
- A left-hand side, specifying the hypothesized tree's node
  value.
- A right-hand side, specifying the hypothesized tree's
  children.  Each element of the right-hand side is either a
  terminal, specifying a token with that terminal as its leaf
  value; or a nonterminal, specifying a subtree with that
  nonterminal's symbol as its node value.
- A dot position, indicating which children are consistent
  with part of the sentence.  In particular, if ``dot`` is the
  dot position, ``rhs`` is the right-hand size, ``(start,end)``
  is the span, and ``sentence`` is the list of tokens in the
  sentence, then ``tokens[start:end]`` can be spanned by the
  children specified by ``rhs[:dot]``.

For more information about edges, see the ``EdgeI`` interface.
c                 \    Xl         X l        [        U5      nX0l        X@l        XX44U l        g)a  
Construct a new ``TreeEdge``.

:type span: tuple(int, int)
:param span: A tuple ``(s, e)``, where ``tokens[s:e]`` is the
    portion of the sentence that is consistent with the new
    edge's structure.
:type lhs: Nonterminal
:param lhs: The new edge's left-hand side, specifying the
    hypothesized tree's node value.
:type rhs: list(Nonterminal and str)
:param rhs: The new edge's right-hand side, specifying the
    hypothesized tree's children.
:type dot: int
:param dot: The position of the new edge's dot.  This position
    specifies what prefix of the production's right hand side
    is consistent with the text.  In particular, if
    ``sentence`` is the list of tokens in the sentence, then
    ``okens[span[0]:span[1]]`` can be spanned by the
    children specified by ``rhs[:dot]``.
N)_span_lhstuple_rhs_dotr=   )r   r   r(   r+   r.   s        r   r   TreeEdge.__init__   s.    , 
	Cj		 $34r   c                 T    [        X4U R                  5       U R                  5       SS9$ )z
Return a new ``TreeEdge`` formed from the given production.
The new edge's left-hand side and right-hand side will
be taken from ``production``; its span will be
``(index,index)``; and its dot position will be ``0``.

:rtype: TreeEdge
r   r   r(   r+   r.   )rX   r(   r+   )
productionindexs     r   from_productionTreeEdge.from_production  s+     Z^^%5:>>;KQR
 	
r   c                 z    [        U R                  S   U4U R                  U R                  U R                  S-   S9$ )z
Return a new ``TreeEdge`` formed from this edge.
The new edge's dot position is increased by ``1``,
and its end index will be replaced by ``new_end``.

:param new_end: The new end index.
:type new_end: int
:rtype: TreeEdge
r      rb   )rX   r[   r\   r^   r_   )r   new_ends     r   move_dot_forwardTreeEdge.move_dot_forward$  s:     **Q-)						A	
 	
r   c                     U R                   $ r<   )r\   r   s    r   r(   TreeEdge.lhs6      yyr   c                     U R                   $ r<   r[   r   s    r   r   TreeEdge.span9      zzr   c                      U R                   S   $ Nr   rp   r   s    r   r   TreeEdge.start<      zz!}r   c                      U R                   S   $ Nrh   rp   r   s    r   r"   TreeEdge.end?  rv   r   c                 @    U R                   S   U R                   S   -
  $ )Nrh   r   rp   r   s    r   r%   TreeEdge.lengthB  s    zz!}tzz!},,r   c                     U R                   $ r<   )r^   r   s    r   r+   TreeEdge.rhsE  rn   r   c                     U R                   $ r<   )r_   r   s    r   r.   TreeEdge.dotH  rn   r   c                 F    U R                   [        U R                  5      :H  $ r<   r_   lenr^   r   s    r   r6   TreeEdge.is_completeK      yyC		N**r   c                 F    U R                   [        U R                  5      :g  $ r<   r   r   s    r   r9   TreeEdge.is_incompleteN  r   r   c                 |    U R                   [        U R                  5      :  a  g U R                  U R                      $ r<   r   r   s    r   r2   TreeEdge.nextsymQ  s,    99DII&99TYY''r   c                 p   SU R                   S    SU R                   S    S3nXR                  <S S3-  n[        [        U R                  5      5       H5  nX R
                  :X  a  US-  nUS	[        U R                  U   5      -  -  nM7     [        U R                  5      U R
                  :X  a  US-  nU$ )
N[r   :rh   ] 2z ->z *z %s)r[   r\   ranger   r^   r_   repr)r   stris      r   __str__TreeEdge.__str__X  s    $**Q-$**Q-3II''s499~&AII~t54		!---C ' tyy>TYY&4KC
r   c                     SU -  $ Nz
[Edge: %s]rC   r   s    r   __repr__TreeEdge.__repr__d  s    d""r   )r=   r_   r\   r^   r[   Nr   )rI   rR   rS   rT   rU   r   staticmethodre   rj   r(   r   r   r"   r%   r+   r.   r6   r9   r2   r   r   rV   rC   r   r   rX   rX      sa    .5: 
 

$-++(
#r   rX   c                   f    \ 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S rS rS rSrg)LeafEdgeih  ag  
An edge that records the fact that a leaf value is consistent with
a word in the sentence.  A leaf edge consists of:

- An index, indicating the position of the word.
- A leaf, specifying the word's content.

A leaf edge's left-hand side is its leaf value, and its right hand
side is ``()``.  Its span is ``[index, index+1]``, and its dot
position is ``0``.
c                 ,    Xl         X l        X4U l        g)z
Construct a new ``LeafEdge``.

:param leaf: The new edge's leaf value, specifying the word
    that is recorded by this edge.
:param index: The new edge's index, specifying the position of
    the word that is recorded by this edge.
N)_leaf_indexr=   )r   leafrd   s      r   r   LeafEdge.__init__u  s     
 $}r   c                     U R                   $ r<   )r   r   s    r   r(   LeafEdge.lhs  rr   r   c                 8    U R                   U R                   S-   4$ rx   r   r   s    r   r   LeafEdge.span  s    T[[1_--r   c                     U R                   $ r<   r   r   s    r   r   LeafEdge.start  s    {{r   c                      U R                   S-   $ rx   r   r   s    r   r"   LeafEdge.end  s    {{Qr   c                     grx   rC   r   s    r   r%   LeafEdge.length      r   c                     gNrC   rC   r   s    r   r+   LeafEdge.rhs  s    r   c                     grt   rC   r   s    r   r.   LeafEdge.dot  r   r   c                     g)NTrC   r   s    r   r6   LeafEdge.is_complete      r   c                     gNFrC   r   s    r   r9   LeafEdge.is_incomplete  s    r   c                     g r<   rC   r   s    r   r2   LeafEdge.nextsym  r   r   c                 l    SU R                    SU R                   S-    S[        U R                  5       3$ )Nr   r   rh   r   )r   r   r   r   s    r   r   LeafEdge.__str__  s2    4;;-qq 1D4D3EFFr   c                     SU -  $ r   rC   r   s    r   r   LeafEdge.__repr__  s    t$$r   )r=   r   r   N)rI   rR   rS   rT   rU   r   r(   r   r   r"   r%   r+   r.   r6   r9   r2   r   r   rV   rC   r   r   r   r   h  sI    
-.G%r   r   c                       \ rS rSrSrS rS rS rS rS r	S r
S	 r\rS
 rS rS rS rS rS rS r\4S jr\S4S jrS rS rSS jrSS jrSS jrS rSrg)Charti  a  
A blackboard for hypotheses about the syntactic constituents of a
sentence.  A chart contains a set of edges, and each edge encodes
a single hypothesis about the structure of some portion of the
sentence.

The ``select`` method can be used to select a specific collection
of edges.  For example ``chart.select(is_complete=True, start=0)``
yields all complete edges whose start indices are 0.  To ensure
the efficiency of these selection operations, ``Chart`` dynamically
creates and maintains an index for each set of attributes that
have been selected on.

In order to reconstruct the trees that are represented by an edge,
the chart associates each edge with a set of child pointer lists.
A child pointer list is a list of the edges that license an
edge's right-hand side.

:ivar _tokens: The sentence that the chart covers.
:ivar _num_leaves: The number of tokens.
:ivar _edges: A list of the edges in the chart
:ivar _edge_to_cpls: A dictionary mapping each edge to a set
    of child pointer lists that are associated with that edge.
:ivar _indexes: A dictionary mapping tuples of edge attributes
    to indices, where each index maps the corresponding edge
    attribute values to lists of edges.
c                 x    [        U5      U l        [        U R                  5      U l        U R	                  5         g)z
Construct a new chart. The chart is initialized with the
leaf edges corresponding to the terminal leaves.

:type tokens: list
:param tokens: The sentence that this chart will be used to parse.
N)r]   _tokensr   _num_leaves
initializer   tokenss     r   r   Chart.__init__  s,     V}t||, 	r   c                 .    / U l         0 U l        0 U l        g)z
Clear the chart.
N)_edges_edge_to_cpls_indexesr   s    r   r   Chart.initialize  s    
    r   c                     U R                   $ )zC
Return the number of words in this chart's sentence.

:rtype: int
)r   r   s    r   
num_leavesChart.num_leaves  s     r   c                      U R                   U   $ )zD
Return the leaf value of the word at the given index.

:rtype: str
r   )r   rd   s     r   r   
Chart.leaf  s     ||E""r   c                     U R                   $ )z[
Return a list of the leaf values of each word in the
chart's sentence.

:rtype: list(str)
r   r   s    r   leavesChart.leaves  s     ||r   c                      U R                   SS $ )z
Return a list of all edges in this chart.  New edges
that are added to the chart after the call to edges()
will *not* be contained in this list.

:rtype: list(EdgeI)
:see: ``iteredges``, ``select``
N)r   r   s    r   edgesChart.edges	  s     {{1~r   c                 ,    [        U R                  5      $ )z
Return an iterator over the edges in this chart.  It is
not guaranteed that new edges which are added to the
chart before the iterator is exhausted will also be generated.

:rtype: iter(EdgeI)
:see: ``edges``, ``select``
)iterr   r   s    r   	iteredgesChart.iteredges  s     DKK  r   c                 ,    [        U R                  5      $ )zB
Return the number of edges contained in this chart.

:rtype: int
)r   r   r   s    r   	num_edgesChart.num_edges"  s     4%%&&r   c                 <  ^ T0 :X  a  [        U R                  5      $ [        TR                  5       5      n[	        U5      nX R
                  ;  a  U R                  U5        [	        U4S jU 5       5      n[        U R
                  U   R                  U/ 5      5      $ )a  
Return an iterator over the edges in this chart.  Any
new edges that are added to the chart before the iterator
is exahusted will also be generated.  ``restrictions``
can be used to restrict the set of edges that will be
generated.

:param span: Only generate edges ``e`` where ``e.span()==span``
:param start: Only generate edges ``e`` where ``e.start()==start``
:param end: Only generate edges ``e`` where ``e.end()==end``
:param length: Only generate edges ``e`` where ``e.length()==length``
:param lhs: Only generate edges ``e`` where ``e.lhs()==lhs``
:param rhs: Only generate edges ``e`` where ``e.rhs()==rhs``
:param nextsym: Only generate edges ``e`` where
    ``e.nextsym()==nextsym``
:param dot: Only generate edges ``e`` where ``e.dot()==dot``
:param is_complete: Only generate edges ``e`` where
    ``e.is_complete()==is_complete``
:param is_incomplete: Only generate edges ``e`` where
    ``e.is_incomplete()==is_incomplete``
:rtype: iter(EdgeI)
c              3   .   >#    U  H
  nTU   v   M     g 7fr<   rC   ).0keyrestrictionss     r   	<genexpr>Chart.select.<locals>.<genexpr>M  s     =*3\#&*s   )r   r   sortedkeysr]   r   
_add_indexget)r   r   
restr_keysvalss    `  r   selectChart.select*  s    0 2$$ L--/0
:&
 ]]*OOJ'=*==DMM*-11$;<<r   c                   ^ U H&  n[        [        U5      (       a  M  [        SU-  5      e   0 =o0R                  U'   U R                   H9  m[        U4S jU 5       5      nUR                  U/ 5      R                  T5        M;     g)zs
A helper function for ``select``, which creates a new index for
a given set of attributes (aka restriction keys).
zBad restriction: %sc              3   F   >#    U  H  n[        TU5      " 5       v   M     g 7fr<   getattrr   r   edges     r   r   #Chart._add_index.<locals>.<genexpr>_       D#s+--   !N)hasattrr   
ValueErrorr   r   r]   
setdefaultappend)r   r   r   rd   r   r   s        @r   r   Chart._add_indexP  s{     C5#&& !6!<== 
 -/.j) KKDDDDDT2&--d3  r   c                    ^ U R                   R                  5        H;  u  p#[        U4S jU 5       5      nUR                  U/ 5      R	                  T5        M=     g)z[
A helper function for ``insert``, which registers the new
edge with all existing indexes.
c              3   F   >#    U  H  n[        TU5      " 5       v   M     g 7fr<   r   r   s     r   r   /Chart._register_with_indexes.<locals>.<genexpr>h  r   r   N)r   itemsr]   r   r   )r   r   r   rd   r   s    `   r   _register_with_indexesChart._register_with_indexesb  sJ    
 "&!4!4!6JDDDDT2&--d3 "7r   c                 ~    U R                  U5      nU Vs/ s H  oUU4-   PM
     nnU R                  " U/UQ76 $ s  snf )zD
Add a new edge to the chart, using a pointer to the previous edge.
)child_pointer_listsinsert)r   new_edgeprevious_edge
child_edgecplscplnew_cplss          r   insert_with_backpointerChart.insert_with_backpointero  sF     ''63784C:-'48{{8/h// 9s   :c                     XR                   ;  a"  U R                  U5        U R                  U5        U R                   R                  U[	        5       5      nSnU H  n[        U5      nXS;  d  M  SX5'   SnM     U$ )a!  
Add a new edge to the chart, and return True if this operation
modified the chart.  In particular, return true iff the chart
did not already contain ``edge``, or if it did not already associate
``child_pointer_lists`` with ``edge``.

:type edge: EdgeI
:param edge: The new edge
:type child_pointer_lists: sequence of tuple(EdgeI)
:param child_pointer_lists: A sequence of lists of the edges that
    were used to form this edge.  This list is used to reconstruct
    the trees (or partial trees) that are associated with ``edge``.
:rtype: bool
FT)r   _append_edger   r   r
   r]   )r   r   r  r  chart_was_modifiedchild_pointer_lists         r   r  Chart.insertw  s      )))d#''- !!,,T;=A""5!&'9!:!-+/(%)" #6 "!r   c                 :    U R                   R                  U5        g r<   )r   r   r   r   s     r   r  Chart._append_edge  s    4 r   c              #      #    U R                  SU R                  US9 H  nU R                  X2SS9 Sh  vN   M     g N	7f)zq
Return an iterator of the complete tree structures that span
the entire chart, and whose root node is ``root``.
r   )r   r"   r(   T)
tree_classcompleteN)r   r   trees)r   rootr  r   s       r   parsesChart.parses  s@     
 KKaT-=-=4KHDzz$zMMM IMs   2A >
A Fc           	      6    [        U R                  X0 US95      $ )a  
Return an iterator of the tree structures that are associated
with ``edge``.

If ``edge`` is incomplete, then the unexpanded children will be
encoded as childless subtrees, whose node value is the
corresponding terminal or nonterminal.

:rtype: list(Tree)
:note: If two trees share a common subtree, then the same
    Tree may be used to encode that subtree in
    both trees.  If you need to eliminate this subtree
    sharing, then create a deep copy of each tree.
)memor  )r   _trees)r   r   r  r  s       r   r  Chart.trees  s     DKKRJKOPPr   c           
         X;   a  X1   $ U(       a  UR                  5       (       a  / $ [        U[        5      (       a%  U R                  UR	                  5          nU/X1'   U/$ / X1'   / nUR                  5       R                  5       nU R                  U5       HU  nU V	s/ s H  oR                  XX45      PM     n
n	[        R                  " U
6  H  nUR                  U" X{5      5        M     MW     UR                  5       (       aQ  UR                  5       UR                  5       S  Vs/ s H  o" U/ 5      PM     nnU H  nUR                  U5        M     XcU'   U$ s  sn	f s  snf )z
A helper function for ``trees``.

:param memo: A dictionary used to record the trees that we've
    generated for each edge, so that when we see an edge more
    than once, we can reuse the same trees.
N)r9   rH   r   r   r   r(   symbolr  r  	itertoolsproductr   r+   r.   extend)r   r   r  r  r  r   r  r(   r	  cpchild_choiceschildrenelt
unexpandedtrees                  r   r  Chart._trees  sS    <: **,,I dH%%<<

-DDJ6M 
hhj! ++D1C TWWSVR[[tHSVMW &--}=Z67 > 2 9=DHHJL9QR9Q#*S"-9QJRJ'  T
 ! X Ss   E(E!c                 V    U R                   R                  U0 5      R                  5       $ )z
Return the set of child pointer lists for the given edge.
Each child pointer list is a list of edges that have
been used to form this edge.

:rtype: list(list(EdgeI))
)r   r   r   r  s     r   r  Chart.child_pointer_lists  s&     !!%%dB/4466r   Nc                 ~   Uc  SU R                  5       S-   -  nUR                  5       UR                  5       pCSSSUS-
  -  -   U-  -   nX4:X  a!  UR                  5       (       a  US-  nOUS-  nOUR                  5       (       a@  UR	                  5       SU R
                  4:X  a   US	S
U-  XC-
  S-
  -  -   S
US-
  -  -   S-   -  nOTUR                  5       (       a   US	SU-  XC-
  S-
  -  -   SUS-
  -  -   S-   -  nOUS	SU-  XC-
  S-
  -  -   SUS-
  -  -   S-   -  nUSUS-
  -  S-   U R
                  U-
  -  -  nUSU-  -   $ )z
Return a pretty-printed string representation of a given edge
in this chart.

:rtype: str
:param width: The number of characters allotted to each
    index in the sentence.
2   rh   |. #>r   r   =]-z| %s)r   r   r"   r6   r   r   )r   r   widthr   r"   r   s         r   pretty_format_edgeChart.pretty_format_edge  s|    =4??,q01E

dhhjS3%!),,55 <!!s
s
 DIIKAt7G7G3H$H3#+#+/::SEAI=NNQTTTC3#+#+/::SEAI=NNQTTTC3#+#+/::SEAI=NNQTTTCuqy!C'D,<,<s,BCCVd]""r   c                     Uc  SU R                  5       S-   -  nU R                  bA  US:  a;  SnU R                   H"  nX#SUS-
   R                  US-
  5      S-   -  nM$     US-  nU$ SnU$ )z
Return a pretty-printed string representation of this
chart's leaves.  This string can be used as a header
for calls to ``pretty_format_edge``.
Nr/  rh   z|.r1  r0   )r   r   center)r   r8  headertoks       r   pretty_format_leavesChart.pretty_format_leaves  s     =4??,q01E<<#	F||k	*11%!)<sBB $cMF  Fr   c                    ^ ^ Tc  ST R                  5       S-   -  m[        S T  5       5      nU VVs/ s H  u    p4UPM
     nnnT R                  T5      S-   SR                  U U4S jU 5       5      -   $ s  snnf )z
Return a pretty-printed string representation of this chart.

:param width: The number of characters allotted to each
    index in the sentence.
:rtype: str
r/  rh   c              3   b   #    U  H%  oR                  5       UR                  5       U4v   M'     g 7fr<   )r%   r   )r   es     r   r   &Chart.pretty_format.<locals>.<genexpr>=  s!     @4a
AGGIq14s   -/
c              3   H   >#    U  H  nTR                  UT5      v   M     g 7fr<   )r9  )r   r   r   r8  s     r   r   rE  C  s!     O//e<<s   ")r   r   r@  join)r   r8  r   _rD  s   ``   r   pretty_formatChart.pretty_format1  s     =4??,q01E @4@@$)*Ey1E* %%e,iiOOOP	
 +s   A6c           	         SnUS-  nUS-  nUS-  n[        U R                  5       SS5       H  nUS:X  a  US-  n[        U R                  5       S-   5       HZ  nUS:X  dH  X0R                  US-
     R	                  5       ::  d%  X0R                  US-
     R                  5       :  d  MQ  US	X24-  -  nM\     M     US
-  n[        U R                  5       S-   5       H  nUS-  n[        U R                  5       S-   5       HZ  nUS:X  dH  X0R                  US-
     R	                  5       ::  d%  X0R                  US-
     R                  5       :  d  MQ  USX24-  -  nM\     US-  nM     US-  nUS-  nUS-  n[        U R                  5       5       H  nUSU R                  U5      US-   4-  -  nM!     US-  nUS-  n[        U 5       H  u  p$[        UR	                  5       5       H  nUSUUS-   US-   US-   4-  -  nM     USUR	                  5       US-   UR                  5       US-   U4-  -  n[        UR                  5       U R                  5       5       H  nUSUUS-   US-   US-   4-  -  nM     M     US-  nU$ )Nzdigraph nltk_chart {
z  rankdir=LR;
z  node [height=0.1,width=0.1];
z*  node [style=filled, color="lightgray"];
r   z&  node [style=filled, color="black"];
rh   z  %04d.%04d [label=""];
z/  x [style=invis]; x->0000.0000 [style=invis];
z  {rank=same;z
 %04d.%04dz}
z"  edge [style=invis, weight=100];
z  node [shape=plaintext]
z  0000.0000z->%s->%04d.0000z;

z   edge [style=solid, weight=1];
z*  %04d.%04d -> %04d.%04d [style="invis"];
z'  %04d.%04d -> %04d.%04d [label="%s"];
)r   r   r   r   r   r"   r   	enumerate)r   syxr   s        r   dot_digraphChart.dot_digraphJ  s   $		//	:: t~~'R0AAv>>4??,q016QU+1133qKKA<N<R<R<T7T4v==A	 2 1 	
?? t(1,-A A4>>+a/06QU+1133qKKA<N<R<R<T7T..A	 1
 JA . 	
22	))	]t()A"diilAE%:::A *	W 	
00 GA4::<(BEEE	F   ) ;

A
A?  A 488:t'89BEEE	F   : ', 	
U
r   )r   r   r   r   r   r<   )rI   rR   rS   rT   rU   r   r   r   r   r   r   r   __iter__r   r   r   r   r  r  r  r	   r  r  r  r  r9  r@  rJ  rR  rV   rC   r   r   r   r     s    8$ #		! H'$=L4$40"B! '+ N &*E Q"4l	7 #D&
2@r   r   c                   $    \ rS rSrSrS rS rSrg)
ChartRuleIi  a  
A rule that specifies what new edges are licensed by any given set
of existing edges.  Each chart rule expects a fixed number of
edges, as indicated by the class variable ``NUM_EDGES``.  In
particular:

- A chart rule with ``NUM_EDGES=0`` specifies what new edges are
  licensed, regardless of existing edges.
- A chart rule with ``NUM_EDGES=1`` specifies what new edges are
  licensed by a single existing edge.
- A chart rule with ``NUM_EDGES=2`` specifies what new edges are
  licensed by a pair of existing edges.

:type NUM_EDGES: int
:cvar NUM_EDGES: The number of existing edges that this rule uses
    to license new edges.  Typically, this number ranges from zero
    to two.
c                     [        5       e)a  
Return a generator that will add edges licensed by this rule
and the given edges to the chart, one at a time.  Each
time the generator is resumed, it will either add a new
edge and yield that edge; or return.

:type edges: list(EdgeI)
:param edges: A set of existing edges.  The number of edges
    that should be passed to ``apply()`` is specified by the
    ``NUM_EDGES`` class variable.
:rtype: iter(EdgeI)
r   r   chartgrammarr   s       r   applyChartRuleI.apply  s     "##r   c                     [        5       e)z
Return a generator that will add all edges licensed by
this rule, given the edges that are currently in the
chart, one at a time.  Each time the generator is resumed,
it will either add a new edge and yield that edge; or return.

:rtype: iter(EdgeI)
r   )r   rY  rZ  s      r   apply_everywhereChartRuleI.apply_everywhere  r0   r   rC   N)rI   rR   rS   rT   rU   r[  r^  rV   rC   r   r   rV  rV    s    &$	$r   rV  c                   *    \ rS rSrSrS rS rS rSrg)AbstractChartRulei  aQ  
An abstract base class for chart rules.  ``AbstractChartRule``
provides:

- A default implementation for ``apply``.
- A default implementation for ``apply_everywhere``,
  (Currently, this implementation assumes that ``NUM_EDGES <= 3``.)
- A default implementation for ``__str__``, which returns a
  name based on the rule's class name.
c                     [        5       er<   r   rX  s       r   r[  AbstractChartRule.apply  s    !##r   c           
   #     #    U R                   S:X  a  U R                  X5       S h  vN   g U R                   S:X  a$  U H  nU R                  XU5       S h  vN   M     g U R                   S:X  a-  U H&  nU H  nU R                  XX45       S h  vN   M     M(     g U R                   S:X  a7  U H0  nU H'  nU H  nU R                  XX4U5       S h  vN   M      M)     M2     g [        S5      e N N Nc N"7f)Nr   rh         z&NUM_EDGES>3 is not currently supported)	NUM_EDGESr[  AssertionError)r   rY  rZ  e1e2e3s         r   r^  "AbstractChartRule.apply_everywhere  s     >>Qzz%111^^q ::eb999  ^^q B#zz%"AAA    ^^q B##'::ebb#III $    !!IJJ% 2 :
 B JsF   %C8C0/C8C28C8C4AC8C6
C82C84C86C8c                 Z    [         R                  " SSU R                  R                  5      $ )Nz([a-z])([A-Z])z\1 \2)resubr   rI   r   s    r   r   AbstractChartRule.__str__  s     vv&$..2I2IJJr   rC   N)	rI   rR   rS   rT   rU   r[  r^  r   rV   rC   r   r   ra  ra    s    	$
K.Kr   ra  c                   "    \ rS rSrSrSrS rSrg)FundamentalRulei  z
A rule that joins two adjacent edges to form a single combined
edge.  In particular, this rule specifies that any pair of edges

- ``[A -> alpha \* B beta][i:j]``
- ``[B -> gamma \*][j:k]``

licenses the edge:

- ``[A -> alpha B * beta][i:j]``
re  c              #   `  #    UR                  5       (       aY  UR                  5       (       aD  UR                  5       UR                  5       :X  a"  UR	                  5       UR                  5       :X  d  g UR                  UR                  5       5      nUR                  XSU5      (       a  Uv   g g 7fr<   )r9   r6   r"   r   r2   r(   rj   r  r   rY  rZ  	left_edge
right_edger  s         r   r[  FundamentalRule.apply  s      ##%%&&((:#3#3#55!!#z~~'77 --jnn.>? ((jIIN Js   B,B.rC   NrI   rR   rS   rT   rU   rg  r[  rV   rC   r   r   rr  rr    s    
 Ir   rr  c                   .    \ rS rSrSrSrS rS rS rSr	g)	SingleEdgeFundamentalRulei  a  
A rule that joins a given edge with adjacent edges in the chart,
to form combined edges.  In particular, this rule specifies that
either of the edges:

- ``[A -> alpha \* B beta][i:j]``
- ``[B -> gamma \*][j:k]``

licenses the edge:

- ``[A -> alpha B * beta][i:j]``

if the other edge is already in the chart.

:note: This is basically ``FundamentalRule``, with one edge left
    unspecified.
rh   c              #      #    UR                  5       (       a  U R                  XU5       S h  vN   g U R                  XU5       S h  vN   g  N  N7fr<   )r9   _apply_incomplete_apply_complete)r   rY  rZ  r   s       r   r[  SingleEdgeFundamentalRule.apply*  sI     --edCCC++EDAAA DAs!   +AAAA	AAc              #      #    UR                  UR                  5       SUR                  5       S9 H?  nUR                  UR	                  5       5      nUR                  XTU5      (       d  M;  Uv   MA     g 7fNF)r"   r6   r2   )r   r   r(   rj   r"   r  )r   rY  rZ  rv  ru  r  s         r   r}  )SingleEdgeFundamentalRule._apply_complete0  se       "z~~?O & 
I !11*..2BCH,,X*MM
   A%A4+	A4c              #      #    UR                  UR                  5       SUR                  5       S9 H?  nUR                  UR                  5       5      nUR	                  XSU5      (       d  M;  Uv   MA     g 7fNT)r   r6   r(   )r   r"   r2   rj   r  rt  s         r   r|  +SingleEdgeFundamentalRule._apply_incomplete8  sd     ,,--/t9J9J9L ' 
J !11*..2BCH,,X*MM
r  rC   N)
rI   rR   rS   rT   rU   rg  r[  r}  r|  rV   rC   r   r   rz  rz    s    $ IBr   rz  c                       \ rS rSrSrS rSrg)LeafInitRuleiF  r   c              #      #    [        UR                  5       5       H;  n[        UR                  U5      U5      nUR	                  US5      (       d  M7  Uv   M=     g 7fr   )r   r   r   r   r  )r   rY  rZ  rd   r  s        r   r[  LeafInitRule.applyI  sH     5++-.E

5 159H||Hb)) /s   AA	ArC   N)rI   rR   rS   rT   rg  r[  rV   rC   r   r   r  r  F  s    Ir   r  c                   "    \ rS rSrSrSrS rSrg)TopDownInitRuleiU  a  
A rule licensing edges corresponding to the grammar productions for
the grammar's start symbol.  In particular, this rule specifies that
``[S -> \* alpha][0:i]`` is licensed for each grammar production
``S -> alpha``, where ``S`` is the grammar's start symbol.
r   c              #      #    UR                  UR                  5       S9 H6  n[        R                  US5      nUR	                  US5      (       d  M2  Uv   M8     g 7f)Nr(   r   rC   )productionsr   rX   re   r  )r   rY  rZ  prodr  s        r   r[  TopDownInitRule.apply_  sK     ''GMMO'<D//a8H||Hb)) =s   AA	ArC   Nrx  rC   r   r   r  r  U  s     Ir   r  c                   "    \ rS rSrSrSrS rSrg)TopDownPredictRuleif  a`  
A rule licensing edges corresponding to the grammar productions
for the nonterminal following an incomplete edge's dot.  In
particular, this rule specifies that
``[A -> alpha \* B beta][i:j]`` licenses the edge
``[B -> \* gamma][j:j]`` for each grammar production ``B -> gamma``.

:note: This rule corresponds to the Predictor Rule in Earley parsing.
rh   c              #      #    UR                  5       (       a  g UR                  UR                  5       S9 HC  n[        R	                  XCR                  5       5      nUR                  US5      (       d  M?  Uv   ME     g 7f)Nr  rC   )r6   r  r2   rX   re   r"   r  r   rY  rZ  r   r  r  s         r   r[  TopDownPredictRule.applys  sa     ''DLLN';D//hhjAH||Hb)) <   A/A>5	A>rC   Nrx  rC   r   r   r  r  f  s     Ir   r  c                   $    \ rS rSrSrS rS rSrg)CachedTopDownPredictRulei|  a  
A cached version of ``TopDownPredictRule``.  After the first time
this rule is applied to an edge with a given ``end`` and ``next``,
it will not generate any more edges for edges with that ``end`` and
``next``.

If ``chart`` or ``grammar`` are changed, then the cache is flushed.
c                 <    [         R                  U 5        0 U l        g r<   )r  r   _doner   s    r   r   !CachedTopDownPredictRule.__init__  s    ##D)
r   c              #   h  #    UR                  5       (       a  g UR                  5       UR                  5       pT[        U5      (       d  g U R                  R                  XE4S5      nUS   UL a	  US   UL a  g UR                  US9 H  nUR                  5       (       aL  UR                  5       S   n[        U5      (       a)  XQR                  5       :  d  XR                  U5      :w  a  Md  [        R                  Xu5      n	UR                  U	S5      (       d  M  U	v   M     X4U R                  XE4'   g 7f)N)NNr   rh   r  rC   )r6   r2   r"   r   r  r   r  r+   r   r   r   rX   re   r  )
r   rY  rZ  r   r2   rd   doner  firstr  s
             r   r[  CachedTopDownPredictRule.apply  s    g&&
 zz~~w.=7eQ7 2 ''G'4D xxzz
1u%% 0 0 22ezz%?P6P //<H||Hb)) 5 ',%5

7>"s   DD2D2)r  N)rI   rR   rS   rT   rU   r   r[  rV   rC   r   r   r  r  |  s    6r   r  c                   "    \ rS rSrSrSrS rSrg)BottomUpPredictRulei  a  
A rule licensing any edge corresponding to a production whose
right-hand side begins with a complete edge's left-hand side.  In
particular, this rule specifies that ``[A -> alpha \*]`` licenses
the edge ``[B -> \* A beta]`` for each grammar production ``B -> A beta``.
rh   c              #      #    UR                  5       (       a  g UR                  UR                  5       S9 HC  n[        R	                  XCR                  5       5      nUR                  US5      (       d  M?  Uv   ME     g 7f)Nr+   rC   )r9   r  r(   rX   re   r   r  r  s         r   r[  BottomUpPredictRule.apply  sa     ''DHHJ'7D//jjlCH||Hb)) 8r  rC   Nrx  rC   r   r   r  r    s     Ir   r  c                   "    \ rS rSrSrSrS rSrg)BottomUpPredictCombineRulei  a  
A rule licensing any edge corresponding to a production whose
right-hand side begins with a complete edge's left-hand side.  In
particular, this rule specifies that ``[A -> alpha \*]``
licenses the edge ``[B -> A \* beta]`` for each grammar
production ``B -> A beta``.

:note: This is like ``BottomUpPredictRule``, but it also applies
    the ``FundamentalRule`` to the resulting edge.
rh   c              #   *  #    UR                  5       (       a  g UR                  UR                  5       S9 HX  n[        UR	                  5       UR                  5       UR                  5       S5      nUR                  XS45      (       d  MT  Uv   MZ     g 7fNr  rh   )r9   r  r(   rX   r   r+   r  r  s         r   r[   BottomUpPredictCombineRule.apply  sm     ''DHHJ'7D		TXXZQGH||Hg.. 8s   BB
	BrC   Nrx  rC   r   r   r  r    s    	 Ir   r  c                   "    \ rS rSrSrSrS rSrg)EmptyPredictRulei  z]
A rule that inserts all empty productions as passive edges,
in every position in the chart.
r   c              #      #    UR                  SS9 HX  n[        UR                  5       S-   5       H5  n[        R	                  X45      nUR                  US5      (       d  M1  Uv   M7     MZ     g 7f)NT)emptyrh   rC   )r  r   r   rX   re   r  )r   rY  rZ  r  rd   r  s         r   r[  EmptyPredictRule.apply  s`     ''d'3Du//1A56#33D@<<"--"N 7 4s   AA/"A/rC   Nrx  rC   r   r   r  r    s    
 I#r   r  c                        \ rS rSrS rS rSrg)!FilteredSingleEdgeFundamentalRulei  c              #     #    UR                  5       nXAR                  5       :  =(       a    UR                  U5      nUR                  UR	                  5       SUR                  5       S9 Ho  n[        X%UR                  5       UR                  5       5      (       d  M3  UR                  UR                  5       5      nUR                  XvU5      (       d  Mk  Uv   Mq     g 7fr  )r"   r   r   r   r   r(   _bottomup_filterr+   r.   rj   r  )r   rY  rZ  rv  r"   	nexttokenru  r  s           r   r}  1FilteredSingleEdgeFundamentalRule._apply_complete  s     nn**,,@C	  "z~~?O & 
I  IMMOY]]_UU$55jnn6FG00jQQ"N
   BC4C	Cc              #     #    UR                  UR                  5       SUR                  5       S9 H  nUR                  5       nXQR                  5       :  =(       a    UR	                  U5      n[        X&UR                  5       UR                  5       5      (       d  Mm  UR                  UR                  5       5      nUR                  XsU5      (       d  M  Uv   M     g 7fr  )
r   r"   r2   r   r   r  r+   r.   rj   r  )r   rY  rZ  ru  rv  r"   r  r  s           r   r|  3FilteredSingleEdgeFundamentalRule._apply_incomplete  s     ,,--/t9J9J9L ' 
J .."C..00DUZZ_IIMMOY]]_UU$55jnn6FG00jQQ"N
r  rC   N)rI   rR   rS   rT   r}  r|  rV   rC   r   r   r  r    s    	#	#r   r  c                       \ rS rSrS rSrg)"FilteredBottomUpPredictCombineRulei  c              #     #    UR                  5       (       a  g UR                  5       nXAR                  5       :  =(       a    UR                  U5      nUR	                  UR                  5       S9 Hy  n[        X%UR                  5       5      (       d  M$  [        UR                  5       UR                  5       UR                  5       S5      nUR                  Xs45      (       d  Mu  Uv   M{     g 7fr  )r9   r"   r   r   r  r(   r  r+   rX   r   r  )r   rY  rZ  r   r"   r  r  r  s           r   r[  (FilteredBottomUpPredictCombineRule.apply  s     hhj**,,@C	''DHHJ'7DDHHJ??#DIIKTXXZK<<'22"N	 8s   BC.AC.%	C.rC   N)rI   rR   rS   rT   r[  rV   rC   r   r   r  r    s    
#r   r  c                     [        U5      US-   ::  a  gX#S-      n[        U5      (       a  X:H  $ U R                  XA5      $ )Nrh   T)r   r   is_leftcorner)rZ  r  r+   r.   _nexts        r   r  r    sE    
3x37aLE5!!$$U66r   c                   N    \ rS rSrSr\SSS\4S jrS rS r	SS
 jr
\4S jrSrg	)ChartParseri<  as  
A generic chart parser.  A "strategy", or list of
``ChartRuleI`` instances, is used to decide what edges to add to
the chart.  In particular, ``ChartParser`` uses the following
algorithm to parse texts:

| Until no new edges are added:
|   For each *rule* in *strategy*:
|     Apply *rule* to any applicable edges in the chart.
| Return any complete parses in the chart
r   r/  Tc                 <   Xl         X l        X0l        X@l        XPl        X`l        / U l        / U l        U Hd  nUR                  S:X  a  U R                  R                  U5        M0  UR                  S:X  a  U R                  R                  U5        M]  SU l        Mf     g)ah  
Create a new chart parser, that uses ``grammar`` to parse
texts.

:type grammar: CFG
:param grammar: The grammar used to parse texts.
:type strategy: list(ChartRuleI)
:param strategy: A list of rules that should be used to decide
    what edges to add to the chart (top-down strategy by default).
:type trace: int
:param trace: The level of tracing that should be used when
    parsing a text.  ``0`` will generate no tracing output;
    and higher numbers will produce more verbose tracing
    output.
:type trace_chart_width: int
:param trace_chart_width: The default total width reserved for
    the chart in trace output.  The remainder of each line will
    be used to display edges.
:type use_agenda: bool
:param use_agenda: Use an optimized agenda-based algorithm,
    if possible.
:param chart_class: The class that should be used to create
    the parse charts.
r   rh   FN)
_grammar	_strategy_trace_trace_chart_width_use_agenda_chart_class_axioms_inference_rulesrg  r   )r   rZ  strategytracetrace_chart_width
use_agendachart_classrules           r   r   ChartParser.__init__I  s    B  !"3 &' "D~~"##D)1$%%,,T2#(  r   c                     U R                   $ r<   r  r   s    r   rZ  ChartParser.grammar}  s    }}r   c                     U(       d  g US:  nU H4  nU(       a  [        SU-  5        Sn[        UR                  Xu5      5        M6     g )Nrh   z%s:F)printr9  )r   rY  r  	new_edgesr  
edge_widthprint_rule_headerr   s           r   _trace_new_edgesChartParser._trace_new_edges  sD    !AID edl#$)!%**4<=	 r   Nc                    Uc  U R                   nU R                  n[        U5      nU R                  R	                  U5        U R                  U5      nU R                  nU R                  UR                  5       S-   -  nU(       a  [        UR                  U5      5        U R                  (       a  U R                   H'  n[        UR                  XE5      5      nU" XGXU5        M)     U R                  n	UR                  5       n
U
R                  5         U
(       aR  U
R!                  5       nU	 H3  n[        UR                  XEU5      5      nU(       a
  U" XLXU5        X-  n
M5     U
(       a  MR  U$ SnU(       aM  SnU R"                   H2  n[        UR%                  XE5      5      n['        U5      nU" XLXU5        M4     U(       a  MM  U$ )z
Return the final parse ``Chart`` from which all possible
parse trees can be extracted.

:param tokens: The sentence to be parsed
:type tokens: list(str)
:rtype: Chart
rh   TF)r  r  listr  check_coverager  r  r   r  r@  r  r  r[  r  r   reversepopr  r^  r   )r   r   r  trace_new_edgesrY  rZ  trace_edge_widthaxiomr  inference_rulesagendar   r  edges_addeds                 r   chart_parseChartParser.chart_parse  s    =KKE//f$$V,!!&)--  22u7G7G7IA7MN%,,-=>? U!<=	i@PQ & #33O[[]F NNzz|+D $TZZ%E FI'YGWX'F	 , &&  K# NND $T%:%:5%J KI"%i.K#ECST + + r   c                     U R                  U5      n[        UR                  U R                  R	                  5       US95      $ N)r  )r  r   r  r  r   )r   r   r  rY  s       r   parseChartParser.parse  s7      (ELL!4!4!6:LNOOr   )r  r  r  r  r  r  r  r  r<   )rI   rR   rS   rT   rU   BU_LC_STRATEGYr   r   rZ  r  r  r	   r  rV   rC   r   r   r  r  <  s9    
  2)h>5n (, Pr   r  c                       \ rS rSrSrS rSrg)TopDownChartParseri  z`
A ``ChartParser`` using a top-down parsing strategy.
See ``ChartParser`` for more information.
c                 <    [         R                  " X[        40 UD6  g r<   )r  r   TD_STRATEGYr   rZ  parser_argss      r   r   TopDownChartParser.__init__  s    TKG;Gr   rC   NrI   rR   rS   rT   rU   r   rV   rC   r   r   r  r    s    
Hr   r  c                       \ rS rSrSrS rSrg)BottomUpChartParseri  za
A ``ChartParser`` using a bottom-up parsing strategy.
See ``ChartParser`` for more information.
c                     [        U[        5      (       a  [        R                  " S[        S9  [
        R                  " X[        40 UD6  g )NzTBottomUpChartParser only works for CFG, use BottomUpProbabilisticChartParser instead)category)rH   r   warningswarnDeprecationWarningr  r   BU_STRATEGYr  s      r   r   BottomUpChartParser.__init__  s:    gt$$MM?+
 	TKG;Gr   rC   Nr  rC   r   r   r  r    s    
Hr   r  c                       \ rS rSrSrS rSrg)BottomUpLeftCornerChartParseri  z
A ``ChartParser`` using a bottom-up left-corner parsing strategy.
This strategy is often more efficient than standard bottom-up.
See ``ChartParser`` for more information.
c                 <    [         R                  " X[        40 UD6  g r<   )r  r   r  r  s      r   r   &BottomUpLeftCornerChartParser.__init__  s    TNJkJr   rC   Nr  rC   r   r   r  r    s    Kr   r  c                       \ rS rSrS rSrg)LeftCornerChartParseri  c                 |    UR                  5       (       d  [        S5      e[        R                  " X[        40 UD6  g )NzCLeftCornerParser only works for grammars without empty productions.)is_nonemptyr   r  r   LC_STRATEGYr  s      r   r   LeftCornerChartParser.__init__  s8    ""$$X  	TKG;Gr   rC   N)rI   rR   rS   rT   r   rV   rC   r   r   r  r    s    Hr   r  c                   z    \ rS rSrSr/ S4S jrS rS rS rS r	S	 r
S
 rS r\4S jrS rS rS r\4S jrSrg)SteppingChartParseri  a[  
A ``ChartParser`` that allows you to step through the parsing
process, adding a single edge at a time.  It also allows you to
change the parser's strategy or grammar midway through parsing a
text.

The ``initialize`` method is used to start parsing a text.  ``step``
adds a single edge to the chart.  ``set_strategy`` changes the
strategy used by the chart parser.  ``parses`` returns the set of
parses that has been found by the chart parser.

:ivar _restart: Records whether the parser's strategy, grammar,
    or chart has been changed.  If so, then ``step`` must restart
    the parsing algorithm.
r   c                 Z    S U l         S U l        SU l        [        R	                  XX#5        g r   )_chart_current_chartrule_restartr  r   )r   rZ  r  r  s       r   r   SteppingChartParser.__init__
  s(    "&TH<r   c                 D    [        [        U5      5      U l        SU l        g)zBegin parsing the given tokens.TN)r   r  r  r  r   s     r   r   SteppingChartParser.initialize  s    DL)r   c              #     #    U R                   c  [        S5      e SU l        SU R                   R                  5       S-   -  nU R	                  5        Hs  nU R
                  S:  a  [        U R                  5        U R
                  S:  a$  [        U R                   R                  X!5      5        Uv   U R                  (       d  Ms    O   Sv   M  7f)a8  
Return a generator that adds edges to the chart, one at a
time.  Each time the generator is resumed, it adds a single
edge and yields that edge.  If no more edges can be added,
then it yields None.

If the parser's strategy, grammar, or chart is changed, then
the generator will continue adding edges using the new
strategy, grammar, or chart.

Note that this generator never terminates, since the grammar
or strategy might be changed to values that would add new
edges.  Instead, it yields None when no more edges can be
added with the current strategy and grammar.
Nz Parser must be initialized firstFr/  rh   r   )	r  r   r  r   _parser  r  r  r9  )r   wrD  s      r   stepSteppingChartParser.step  s       ;;?@@!DMt{{--/!34A[[];;?$112;;?$++88>?=== # 
 s   C C
Cc              #      #    U R                   nU R                  nSnUS:  aE  SnU R                   H*  nX@l        UR	                  X5       H  nUS-  nUv   M     M,     US:  a  MD  gg7f)z
A generator that implements the actual parsing algorithm.
``step`` iterates through this generator, and restarts it
whenever the parser's strategy, grammar, or chart is modified.
rh   r   N)r  r  r  r  r^  )r   rY  rZ  r  r  rD  s         r   r  SteppingChartParser._parse>  sk      --AoK*.'..u>A1$KG ? ' Aos   A#A)'A)c                     U R                   $ )z(Return the strategy used by this parser.)r  r   s    r   r  SteppingChartParser.strategyS  s    ~~r   c                     U R                   $ )z'Return the grammar used by this parser.r  r   s    r   rZ  SteppingChartParser.grammarW  s    }}r   c                     U R                   $ )z-Return the chart that is used by this parser.)r  r   s    r   rY  SteppingChartParser.chart[  s    {{r   c                     U R                   $ )z<Return the chart rule used to generate the most recent edge.)r  r   s    r   current_chartrule%SteppingChartParser.current_chartrule_  s    &&&r   c                 j    U R                   R                  U R                  R                  5       U5      $ )z8Return the parse trees currently contained in the chart.)r  r  r  r   )r   r  s     r   r  SteppingChartParser.parsesc  s&    {{!!$--"5"5"7DDr   c                 F    XR                   :X  a  gUSS U l         SU l        g)z
Change the strategy that the parser uses to decide which edges
to add to the chart.

:type strategy: list(ChartRuleI)
:param strategy: A list of rules that should be used to decide
    what edges to add to the chart.
NT)r  r  )r   r  s     r   set_strategy SteppingChartParser.set_strategyk  s#     ~~%!!r   c                 <    XR                   L a  gXl         SU l        g)z&Change the grammar used by the parser.NT)r  r  )r   rZ  s     r   set_grammarSteppingChartParser.set_grammary  s    mm#r   c                 <    XR                   L a  gXl         SU l        g)z)Load a given chart into the chart parser.NT)r  r  )r   rY  s     r   	set_chartSteppingChartParser.set_chart  s    KKr   c                     [        U5      nU R                  R                  U5        U R                  U5        U R	                  5        H  nUb  M    O   U R                  US9$ r  )r  r  r  r   r  r  )r   r   r  rD  s       r   r  SteppingChartParser.parse  sX    f$$V, 	 Ay 
 {{j{11r   )r  r  r  r  r  N)rI   rR   rS   rT   rU   r   r   r  r  r  rZ  rY  r  r	   r  r$  r'  r*  r  rV   rC   r   r   r	  r	    s[      *,1 =B*' !% E (, 2r   r	  c                  0    SSK Jn   U R                  S5      $ )Nr   CFGz
S  -> NP VP
PP -> "with" NP
NP -> NP PP
VP -> VP PP
VP -> Verb NP
VP -> Verb
NP -> Det Noun
NP -> "John"
NP -> "I"
Det -> "the"
Det -> "my"
Det -> "a"
Noun -> "dog"
Noun -> "cookie"
Verb -> "ate"
Verb -> "saw"
Prep -> "with"
Prep -> "under"
)nltk.grammarr0  
fromstringr/  s    r   demo_grammarr3    s     >>	 r   c           	      V	   SSK nSSKnSSKJn	Jn
Jn  [        5       nU(       a  [        S5        [        U5        [        S5        [        U5        UR                  5       n[        U5        [        5         U c~  [        S5        [        S5        [        S5        [        S	5        [        S
5        [        S5        [        SSS9  UR                  R                  5       R                  5       n [        5         [        U 5      n U S;  a  [        S5        g0 nS[        4S[        4S[        4S[         4S.n/ nX;   a  U /nU S:X  a  SnU GH  n[        SUU   S   -   5        [        5         [#        XU   S   US9nUR                  5       nUR%                  U5      n['        UR)                  UR+                  5       5      5      nUR                  5       U-
  XU   S   '   [        S[-        UR/                  5       5      5        U(       a  [-        U5      U:X  d   S5       eU(       a  U H  n[        U5        M     O[        S[-        U5      5        [        5         GM     U S;   Ga  [        S5        [        5         UR                  5       n[1        XS9nUR3                  U5        [5        S 5       H  n[        S!5        UR7                  [        5        [9        UR;                  5       5       H  u  nnUS":  d  Ub  M    O   [        S#5        UR7                  [        5        [9        UR;                  5       5       H  u  nnUS":  d  Ub  M    M     M     UR                  5       U-
  US$'   [        S[-        UR=                  5       R/                  5       5      5        U(       a-  [-        ['        UR)                  5       5      5      U:X  d   S5       eU(       a#  UR)                  5        H  n[        U5        M     O,[        S[-        ['        UR)                  5       5      5      5        [        5         U(       a  U(       d  g[        S%5        [        5         [?        S& U 5       5      nS'[A        U5      -   S(-   nURC                  5       n[E        US) S*9 H  u  nn[        UUU4-  5        M     g)+z'
A demonstration of the chart parsers.
r   N)r0  
Productionnonterminalsz	* Grammarz* Sentence:z  1: Top-down chart parserz  2: Bottom-up chart parserz'  3: Bottom-up left-corner chart parserz3  4: Left-corner chart parser with bottom-up filterz=  5: Stepping chart parser (alternating top-down & bottom-up)z  6: All parsersz
Which parser (1-6)? r2  )r"   123456zBad parser numberzTop-downz	Bottom-upzBottom-up left-cornerzFiltered left-corner)1r   3461234z* Strategy: rh   )r  zNr edges in chart:zNot all parses foundz	Nr trees:56z,* Strategy: Stepping (top-down vs bottom-up)   z*** SWITCH TO TOP DOWN   z*** SWITCH TO BOTTOM UPSteppingz* Parsing timesc              3   8   #    U  H  n[        U5      v   M     g 7fr<   )r   )r   r   s     r   r   demo.<locals>.<genexpr>0  s     +UcSUs   %zs parser: %6.3fsecc                     U S   $ rx   rC   )as    r   <lambda>demo.<locals>.<lambda>3  s    qtr   )r   )#systimenltkr0  r5  r6  r3  r  splitstdinreadlinestripr   r  r  r  r  r  r  r  r  r   r   r   r	  r   r   r$  rN  r  rY  maxr   r   r   )choiceprint_timesprint_grammarprint_treesr  sent	numparsesrH  rI  r0  r5  r6  rZ  r   times
strategieschoicesr  r%  trY  r  r*  r   jrD  maxlenformattimes_itemsparsers                                 r   demor_    s    22 nGkg 
-	$KZZ\F	&M	G ~*++,78CDMN !&C0##%++-[FX!" E +&;'%~6$k2	J G(} nz(3A667X"6q"9GIIKv&ell7==?34)-q"1%&"C$67v;)+C-CC+d  +s6{+# ( ~<=IIK 6
fqA*+OOK(!"''),1r6QY - +,OOK(!"''),1r6QY -  !IIK!Oj"C
(8(8(:$;<tBIIK()Y6N8NN6		d $ +s4		#456 E	
	G+U++F4<"66F++-KK^<	f{"# =r   __main__r   )NTFTre  z$I saw John with a dog with my cookier>  )1rU   r"  rn  r  	functoolsr   r1  r   r   r   nltk.internalsr   nltk.parse.apir   	nltk.treer	   	nltk.utilr
   r   rX   r   r   rV  ra  rr  rz  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r	  r3  r_  rI   rC   r   r   <module>rf     s)  6  	  $ : : 2 "  ! g g gTD#u D#N>%u >%L\ \H,$ ,$^+K
 +Kf' B) )b$ ' "* ,+61 +6f+ &!4 .#( #*#(A #0#)C #7 N	 N	 N 	 N&(%'GP' GPTH HH+ H KK KHK H_2+ _2N8 
	/y$x zF r   