
    Ki                       d Z ddlmZmZ ddlZddlZddlZddlZddlZddl	m
Z
 ddl	mZ ej        j        dk    rd ZeZd Zd	 ZneZd
 Zd Z ej        e          Zd Z G d de          Z G d de          Z G d de          Zd Zd Z ej        d           Z	  G d de           Z! G d de           Z" G d de"          Z# G d de"          Z$ G d d e"          Z% G d! d"e"          Z& G d# d$e"          Z' G d% d&e"          Z( G d' d(e"          Z) G d) d*e           Z* G d+ d,e           Z+ G d- d.e           Z,d=d0Z-d1 Z.d2 Z/d>d4Z0d?d5Z1	 	 d@d6Z2d7 Z3d8 Z4dAd;Z5dBd<Z6dS )Ca  
The ``latexwalker`` module provides a simple API for parsing LaTeX snippets,
and representing the contents using a data structure based on node classes.

LatexWalker will understand the syntax of most common macros.  However,
``latexwalker`` is NOT a replacement for a full LaTeX engine.  (Originally,
``latexwalker`` was designed to extract useful text for indexing for text
database searches of LaTeX content.)

Simple example usage::

    >>> from pylatexenc.latexwalker import LatexWalker, LatexEnvironmentNode
    >>> w = LatexWalker(r"""
    ... \textbf{Hi there!} Here is \emph{a list}:
    ... \begin{enumerate}[label=(i)]
    ... \item One
    ... \item Two
    ... \end{enumerate}
    ... and $x$ is a variable.
    ... """)
    >>> (nodelist, pos, len_) = w.get_latex_nodes(pos=0)
    >>> nodelist[0]
    LatexCharsNode(pos=0, len=1, chars='\n')
    >>> nodelist[1]
    LatexMacroNode(pos=1, len=18, macroname='textbf',
    nodeargd=ParsedMacroArgs(argnlist=[LatexGroupNode(pos=8, len=11,
    nodelist=[LatexCharsNode(pos=9, len=9, chars='Hi there!')],
    delimiters=('{', '}'))], argspec='{'), macro_post_space='')
    >>> nodelist[5].isNodeType(LatexEnvironmentNode)
    True
    >>> nodelist[5].environmentname
    'enumerate'
    >>> nodelist[5].nodeargd.argspec
    '['
    >>> nodelist[5].nodeargd.argnlist
    [LatexGroupNode(pos=60, len=11, nodelist=[LatexCharsNode(pos=61, len=9,
    chars='label=(i)')], delimiters=('[', ']'))]
    >>> nodelist[7].latex_verbatim()
    '$x$'

You can also use `latexwalker` directly in command-line, producing JSON or a
human-readable node tree::

    $ echo '\textit{italic} text' | latexwalker --output-format=json
    {
      "nodelist": [
        {
          "nodetype": "LatexMacroNode",
          "pos": 0,
          "len": 15,
          "macroname": "textit",
    [...]

    $ latexwalker --help
    [...]

The parser can be influenced by specifying a collection of known macros and
environments (the "latex context") that are specified using
:py:class:`pylatexenc.macrospec.MacroSpec` and
:py:class:`pylatexenc.macrospec.EnvironmentSpec` objects in a
:py:class:`pylatexenc.macrospec.LatexContextDb` object.  See the doc of the
module :py:mod:`pylatexenc.macrospec` for more information.
    )print_functionunicode_literalsN   )	macrospec)_utilc                     | S N )strings    w/var/www/development/aibuddy-work/election-extract/venv/lib/python3.11/site-packages/pylatexenc/latexwalker/__init__.pyunicoder   g   s        c                     | S r	   r
   xs    r   <lambda>r   i       ! r   c                     | S r	   r
   r   s    r   r   r   j   r   r   c                 F    t          |                               d          S Nzutf-8)r   encoder   s    r   r   r   n   s    '!**"3"3G"<"< r   c                 ,    |                      d          S r   )decoder   s    r   r   r   o   s    !((7"3"3 r   c                       t          |           S r	   )tuple)argss    r   
_maketupler   t   s     ;;r   c                       e Zd ZdZdS )LatexWalkerErrorz8
    Generic exception class raised by this module.
    N)__name__
__module____qualname____doc__r
   r   r   r   r   z   s          	Dr   r   c                   6     e Zd ZdZd fd	Zd Zd Zd Z xZS )LatexWalkerParseErrora^  
    Represents an error while parsing LaTeX code.

    The following attributes are available if they were provided to the class
    constructor:

    .. py:attribute:: msg

       The error message

    .. py:attribute:: s

       The string that was currently being parsed

    .. py:attribute:: pos
    
       The index in the string where the error occurred, starting at zero.

    .. py:attribute:: lineno

       The line number where the error occurred, starting at 1.

    .. py:attribute:: colno

       The column number where the error occurred in the line `lineno`, starting
       at 1.
    Nc                     d | _         || _        || _        || _        || _        || _        g | _        t          t          |           	                    | 
                                           d S r	   )input_sourcemsgsposlinenocolnoopen_contextssuperr%   __init___dispstr)selfr(   r)   r*   r+   r,   	__class__s         r   r/   zLatexWalkerParseError.__init__   sc     
#T**33DMMOODDDDDr   c           
      h   | j         }| j        r|d                    | j                  z  }|d|                     | j        | j        | j                  z  z   }| j        rS|dz  }t          | j                  D ]9}|\  }}}}|d                    d|                     |||          |          z  }:|S )Nz  in {}z %sz
Open LaTeX blocks:
z{empty:8}{loc:>10}  {what}
 )emptylocwhat)	r(   r'   format_fmt_posr*   r+   r,   r-   reversed)r1   r(   dispcontextr7   r*   r+   r,   s           r   r0   zLatexWalkerParseError._dispstr   s    h 	79##D$5666CUDMM$(DKLLMM 	C,,D#D$677 C C+2(c656==B<@MM#fUZ<[<[=A > C C C r   c                 ,    ||d||fz  S d|z  S d|z  S )Nz@(%d,%d)z@%dz	@ char %dr
   )r1   r*   r+   r,   s       r   r9   zLatexWalkerParseError._fmt_pos   s2     !65/11&>!C  r   c                 *    |                                  S r	   )r0   r1   s    r   __str__zLatexWalkerParseError.__str__       }}r   NNNN)	r    r!   r"   r#   r/   r0   r9   r@   __classcell__r2   s   @r   r%   r%      sz         6	E 	E 	E 	E 	E 	E  ! ! !      r   r%   c                   $     e Zd ZdZd fd	Z xZS )LatexWalkerEndOfStreamz:
    Reached end of input stream (e.g., end of file).
    r4   c                 d    t          t          |                                            || _        d S r	   )r.   rF   r/   final_space)r1   rH   r2   s     r   r/   zLatexWalkerEndOfStream.__init__   s.    $d++44666&r   r4   )r    r!   r"   r#   r/   rC   rD   s   @r   rF   rF      sG         ' ' ' ' ' ' ' ' ' 'r   rF   c                      t          j                    } ddlm} |D ]0\  }}|                     ||d         |d         |d                    1| S )a  
    Return a :py:class:`pylatexenc.macrospec.LatexContextDb` instance
    initialized with a collection of known macros and environments.

    TODO: document categories.

    If you want to add your own definitions, you should use the
    :py:meth:`pylatexenc.macrospec.LatexContextDb.add_context_category()`
    method.  If you would like to override some definitions, use that method
    with the argument `prepend=True`.  See docs for
    :py:meth:`pylatexenc.macrospec.LatexContextDb.add_context_category()`.

    If there are too many macro/environment definitions, or if there are some
    irrelevant ones, you can always filter the returned database using
    :py:meth:`pylatexenc.macrospec.LatexContextDb.filter_context()`.

    .. versionadded:: 2.0
 
       The :py:class:`pylatexenc.macrospec.LatexContextDb` class as well as this
       method, were all introduced in `pylatexenc 2.0`.
       )specsmacrosenvironmentsspecials)rM   rN   rO   )r   LatexContextDb_defaultspecsrL   add_context_category)dbrL   catcatspecss       r   get_default_latex_context_dbrV      sz    , 
	!	#	#B$$$$$$ ? ?X
'/'9-5n-E)1*)= 	  	? 	? 	? 	?
 Ir   c                     t          j        d           t          j        | ||          }|j        |_        ||_        ||_        d|j        _	        |S )a  
    .. deprecated:: 2.0

       Use :py:func:`pylatexenc.macrospec.std_macro` instead which does the same
       thing, or invoke the :py:class:`~pylatexenc.macrospec.MacroSpec` class
       directly (or a subclass).

       In `pylatexenc 1.x`, `MacrosDef` was a class.  Since `pylatexenc 2.0`,
       `MacrosDef` is a function which returns a
       :py:class:`~pylatexenc.macrospec.MacroSpec` instance.  In this way the
       earlier idiom ``MacrosDef(...)`` still works in `pylatexenc 2`.  The
       field names of the constructed object might have changed since
       `pylatexenc 1.x`, so you might have to adapt existing code if you were
       accessing individual fields of `MacrosDef` objects.

       In the object returned by `MacrosDef()`, we provide the legacy attributes
       `macname`, `optarg`, and `numargs`, so that existing code accessing those
       properties can continue to work.
    z`pylatexenc.latexwalker.MacrosDef` is now obsolete. It should still work in most use cases, but new code should use `pylatexenc.macrospec.MacroSpec` instead.T)
r   pylatexenc_deprecated_2r   	std_macro	macronamemacnameoptargnumargsargs_parser&_like_pylatexenc1x_ignore_leading_star)r[   r\   r]   ms       r   	MacrosDefra      s]    ( 
!	4   	GVW55AAIAHAI <@AM8Hr   c                  p    t          d t                                                      D                       S )Nc                      g | ]}|j         |fS r
   )rZ   ).0r`   s     r   
<listcomp>z<lambda>.<locals>.<listcomp>  s/     # # # 
a# # #r   )dictrV   iter_macro_specsr
   r   r   r   r     s>    T # #-//@@BB# # #   r   )generate_dict_fnc                   F     e Zd ZdZd
 fd	Zd Zd Zd Zd Zd Z	d	Z
 xZS )
LatexTokenaq  
    Represents a token read from the LaTeX input.

    This is used internally by :py:class:`LatexWalker`'s methods.  You probably
    don't need to worry about individual tokens.  Rather, you should use the
    high-level functions provided by :py:class:`LatexWalker` (e.g.,
    :py:meth:`~LatexWalker.get_latex_nodes()`).  So most likely, you can ignore
    this class entirely.

    Instances of this class are what the method
    :py:meth:`LatexWalker.get_token()` returns.  See the doc of that function
    for more information on how tokens are parsed.

    This is not the same thing as a LaTeX token, it's just a part of the input
    which we treat in the same way (e.g. a bunch of content characters, a
    comment, a macro, etc.)

    Information about the object is stored into the fields `tok` and `arg`. The
    `tok` field is a string which identifies the type of the token. The `arg`
    depends on what `tok` is, and describes the actual input.

    Additionally, this class stores information about the position of the token
    in the input stream in the field `pos`.  This `pos` is an integer which
    corresponds to the index in the input string.  The field `len` stores the
    length of the token in the input string.  This means that this token spans
    in the input string from `pos` to `pos+len`.

    Leading whitespace before the token is not returned as a separate
    'char'-type token, but it is given in the `pre_space` field of the token
    which follows.  Pre-space may contain a newline, but not two consecutive
    newlines.

    The `post_space` is only used for 'macro' and 'comment' tokens, and it
    stores any spaces encountered after a macro, or the newline with any
    following spaces that terminates a LaTeX comment.  When we encounter two
    consecutive newlines these are not included in `post_space`.

    The `tok` field may be one of:

      - 'char': raw character(s) which have no special LaTeX meaning and which
        are part of the text content.
        
        The `arg` field contains the characters themselves.

      - 'macro': a macro invocation, but not ``\begin`` or ``\end``
        
        The `arg` field contains the name of the macro, without the leading
        backslash.

      - 'begin_environment': an invocation of ``\begin{environment}``.
        
        The `arg` field contains the name of the environment inside the braces.

      - 'end_environment': an invocation of ``\end{environment}``.
        
        The `arg` field contains the name of the environment inside the braces.

      - 'comment': a LaTeX comment delimited by a percent sign up to the end of
        the line.
        
        The `arg` field contains the text in the comment line, not including the
        percent sign nor the newline.

      - 'brace_open': an opening brace.  This is usually a curly brace, and
        sometimes also a square bracket.  What is parsed as a brace depends on
        the arguments to :py:meth:`~LatexWalker.get_token()`.
        
        The `arg` is a string which contains the relevant brace character.
        
      - 'brace_close': a closing brace.  This is usually a curly brace, and
        sometimes also a square bracket.  What is parsed as a brace depends on
        the arguments to :py:meth:`~LatexWalker.get_token()`.
        
        The `arg` is a string which contains the relevant brace character.

      - 'mathmode_inline': a delimiter which starts/ends inline math.  This is
        (e.g.) a single '$' character which is not part of a double '$$'
        display environment delimiter.

        The `arg` is the string value of the delimiter in question ('$')

      - 'mathmode_display': a delimiter which starts/ends display math, e.g.,
        ``\[``.

        The `arg` is the string value of the delimiter in question (e.g.,
        ``\[`` or ``$$``)

      - 'specials': a character or character sequence that has a special
        meaning in LaTeX.  E.g., '~', '&', etc.

        The `arg` field is then the corresponding
        :py:class:`~pylatexenc.macrospec.SpecialsSpec` instance.  [The rationale
        for setting `arg` to a `SpecialsSpec` instance, in contrast to the
        behavior for macros and envrionments, is that macros and environments
        are delimited directly by LaTeX syntax and are determined unambiguously
        without any lookup in the latex context database.  This is not the case
        for specials.]
    r4   c                    || _         || _        || _        || _        || _        || _        g d| _        | j         dv r| j                            d           t          t          |           
                                 d S )Ntokargr*   len	pre_space)macrocomment
post_space)rm   rn   r*   ro   rp   rs   _fieldsappendr.   rj   r/   )r1   rm   rn   r*   ro   rp   rs   r2   s          r   r/   zLatexToken.__init__  s    "$@@@8+++L---j$((*****r   c                 D    t          |                                           S r	   _unicode_from_strr@   r?   s    r   __unicode__zLatexToken.__unicode__       000r   c                 \     dd                      fd j        D                       z   dz   S )NzLatexToken(, c                 :    g | ]}|d t          |          S =getattrrd   kr1   s     r   re   z'LatexToken.__repr__.<locals>.<listcomp>  s<     0 0 0 "#74???3 0 0 0r   ))joinrt   r?   s   `r   __repr__zLatexToken.__repr__  sS    II 0 0 0 0!%0 0 0 1 11 	r   c                 *    |                                  S r	   r   r?   s    r   r@   zLatexToken.__str__  rA   r   c                 H     t           fd j        D                       S )Nc              3   \   K   | ]&}t          |          t          |          k    V  'd S r	   r   rd   fotherr1   s     r   	<genexpr>z$LatexToken.__eq__.<locals>.<genexpr>  s<      TTgdA&&'%*;*;;TTTTTTr   )allrt   r1   r   s   ``r   __eq__zLatexToken.__eq__  s,    TTTTTdlTTTVVVr   c                     t           S r	   NotImplementedr   s     r   __ne__zLatexToken.__ne__      N2r   NrI   )r    r!   r"   r#   r/   ry   r   r@   r   r   __hash__rC   rD   s   @r   rj   rj   :  s        a aD
+ 
+ 
+ 
+ 
+ 
+1 1 1    W W W 322HHHHHr   rj   c                   \     e Zd ZdZ	 	 d fd	Zd Zd Zd Zd Zd Z	dZ
d	 Zd
 Zd Z xZS )	LatexNodea[  
    Represents an abstract 'node' of the latex document.

    Use :py:meth:`nodeType()` to figure out what type of node this is, and
    :py:meth:`isNodeType()` to test whether it is of a given type.

    You should use :py:meth:`LatexWalker.make_node()` to create nodes, so that
    the latex walker has the opportunity to do some additional setting up.

    All nodes have the following attributes:

    .. py:attribute:: parsing_state

       The parsing state at the time this node was created.  This object stores
       additional context information for this node, such as whether or not this
       node was parsed in a math mode block of LaTeX code.

       See also the :py:meth:`LatexWalker.make_parsing_state()` and the
       `parsing_state` argument of :py:meth:`LatexWalker.get_latex_nodes()`.

    .. py:attribute:: pos

       The position in the parsed string that this node represents.  The parsed
       string can be recovered as `parsing_state.s`, see
       :py:attr:`ParsingState.s`.

    .. py:attribute:: len

       How many characters in the parsed string this node represents, starting
       at position `pos`.  The parsed string can be recovered as
       `parsing_state.s`, see :py:attr:`ParsingState.s`.

    .. versionadded:: 2.0
       
       The attributes `parsing_state`, `pos` and `len` were added in
       `pylatexenc 2.0`.
    Nc                 J    t          t          |           j        di | || _        || _        || _        t          ddgt          |          z             | _        |8t          t          | j                  t          |          z             | _	        d S | j        | _	        d S )Nr*   ro   r
   )
r.   r   r/   parsing_stater*   ro   r   listrt   _redundant_fields)r1   rt   r   r   r*   ro   kwargsr2   s          r   r/   zLatexNode.__init__  s     	(i'11&111*eU^d7mm;<<(%*4+=+=EV@W@W+W%X%XD"""%)\D"""r   c                     t           S )a  
        Returns the class which corresponds to the type of this node.  This is a
        Python class object, that is one of
        :py:class:`~pylatexenc.latexwalker.LatexCharsNode`,
        :py:class:`~pylatexenc.latexwalker.LatexGroupNode`, etc.
        )r   r?   s    r   nodeTypezLatexNode.nodeType  s
     r   c                 "    t          | |          S )z
        Returns `True` if the current node is of the given type.  The argument `t`
        must be a Python class such as,
        e.g. :py:class:`~pylatexenc.latexwalker.LatexGroupNode`.
        )
isinstance)r1   ts     r   
isNodeTypezLatexNode.isNodeType  s     $"""r   c                 z    | j         t          d          | j         j        | j        | j        | j        z            S )z
        Return the chunk of LaTeX code that this node represents.

        This is a shorthand for ``node.parsing_state.s[node.pos:node.pos+node.len]``.
        NzNCan't use latex_verbatim() on node because we don't have any parsing_state set)r   	TypeErrorr)   r*   ro   r?   s    r   latex_verbatimzLatexNode.latex_verbatim  sE     % 9 : : :!#DHtx/@$@AAr   c                      d uox                                                                   k    oNj         j        u o@j         j        k    o0j         j        k    o t	           fd j        D                       S )Nc              3   \   K   | ]&}t          |          t          |          k    V  'd S r	   r   r   s     r   r   z#LatexNode.__eq__.<locals>.<genexpr>%  s<      PPQ'$""geQ&7&77PPPPPPr   )r   r   r*   ro   r   rt   r   s   ``r   r   zLatexNode.__eq__  s    D  MMOOu~~///4#55 I! I!	
 PPPPP$,PPP 	r   c                     t           S r	   r   r   s     r   r   zLatexNode.__ne__)  r   r   c                 D    t          |                                           S r	   rw   r?   s    r   ry   zLatexNode.__unicode__-  rz   r   c                 *    |                                  S r	   r   r?   s    r   r@   zLatexNode.__str__/  rA   r   c                                                        j        dz   d                    t           j                            z   d                     fd j        D                       z   dz   S )N(z"parsing_state=<parsing state {}>, r|   c                 :    g | ]}|d t          |          S r~   r   r   s     r   re   z&LatexNode.__repr__.<locals>.<listcomp>5  s,    LLL74???3LLLr   r   )r   r    r8   idr   r   rt   r?   s   `r   r   zLatexNode.__repr__1  ss    MMOO$s*0774;M8N8NOOPIILLLLdlLLLMMN 	r   rB   )r    r!   r"   r#   r/   r   r   r   r   r   r   ry   r@   r   rC   rD   s   @r   r   r     s        $ $J 37372 2 2 2 2 2&  # # #	B 	B 	B   322H1 1 1        r   r   c                   (     e Zd ZdZ fdZd Z xZS )LatexCharsNodez
    A string of characters in the LaTeX document, without any special LaTeX
    code.

    .. py:attribute:: chars

       The string of characters represented by this node.
    c                 Z     t          t          |           j        dddi| || _        d S )Nrt   )charsr
   )r.   r   r/   r   )r1   r   r   r2   s      r   r/   zLatexCharsNode.__init__C  sF    ,nd##, 	
 	
 	
	
 	
 	
 


r   c                     t           S r	   )r   r?   s    r   r   zLatexCharsNode.nodeTypeJ      r   r    r!   r"   r#   r/   r   rC   rD   s   @r   r   r   :  sQ                   r   r   c                   (     e Zd ZdZ fdZd Z xZS )LatexGroupNodea  
    A LaTeX group delimited by braces, ``{like this}``.

    Note: in the case of an optional macro or environment argument, this node is
    also used to represents a group delimited by square braces instead of curly
    braces.

    .. py:attribute:: nodelist

       A list of nodes describing the contents of the LaTeX braced group.  Each
       item of the list is a :py:class:`LatexNode`.

    .. py:attribute:: delimiters

       A 2-item tuple that stores the delimiters for this group node.  Usually
       this is `('{', '}')`, except for optional macro arguments where this
       might be for instance `('[', ']')`.

       .. versionadded:: 2.0

          The `delimiters` field was added in `pylatexenc 2.0`.
    c                     |                     dd          } t          t          |           j        dddi| || _        || _        d S )N
delimiters{}rt   )nodelistr   r
   )popr.   r   r/   r   r   )r1   r   r   r   r2   s       r   r/   zLatexGroupNode.__init__d  s`    ZZj99
,nd##, 	
 	
.	
	
 	
 	
 !$r   c                     t           S r	   )r   r?   s    r   r   zLatexGroupNode.nodeTypem  r   r   r   rD   s   @r   r   r   M  sQ         ,% % % % %      r   r   c                   (     e Zd ZdZ fdZd Z xZS )LatexCommentNodeag  
    A LaTeX comment, delimited by a percent sign until the end of line.

    .. py:attribute:: comment

       The comment string, not including the '%' sign nor the following newline

    .. py:attribute:: comment_post_space

       The newline that terminated the comment possibly followed by spaces
       (e.g., indentation spaces of the next line)

    c                     |                     dd          } t          t          |           j        dddi| || _        || _        d S )Ncomment_post_spacer4   rt   )rr   r   r
   )r   r.   r   r/   rr   r   )r1   rr   r   r   r2   s       r   r/   zLatexCommentNode.__init__~  sf    #ZZ(<bAA.%%. 	
 	
9	
	
 	
 	

 "4r   c                     t           S r	   )r   r?   s    r   r   zLatexCommentNode.nodeType  s    r   r   rD   s   @r   r   r   p  sQ         	5 	5 	5 	5 	5             r   r   c                   (     e Zd ZdZ fdZd Z xZS )LatexMacroNodea  
    Represents a macro type node, e.g. ``\textbf``

    .. py:attribute:: macroname

       The name of the macro (string), *without* the leading backslash.

    .. py:attribute:: nodeargd

       The :py:class:`pylatexenc.macrospec.ParsedMacroArgs` object that
       represents the macro arguments.

       For macros that do not accept any argument, this is an empty
       :py:class:`~pylatexenc.macrospec.ParsedMacroArgs` instance.  The
       attribute `nodeargd` can be `None` even for macros that accept arguments,
       in the situation where :py:meth:`LatexWalker.get_latex_expression()`
       encounters the macro when reading a single expression.

       Arguments must be declared in the latex context passed to the
       :py:class:`LatexWalker` constructor, using a suitable
       :py:class:`pylatexenc.macrospec.MacroSpec` object.  Some known macros are
       already declared in the default latex context.

       .. versionadded:: 2.0

          The `nodeargd` attribute was introduced in `pylatexenc 2`.

    .. py:attribute:: macro_post_space

       Any spaces that were encountered immediately after the macro.

    The following attributes are obsolete since `pylatexenc 2.0`.

    .. py:attribute:: nodeoptarg

       .. deprecated:: 2.0

          Macro arguments are stored in `nodeargd` in `pylatexenc 2`.  Accessing
          the argument `nodeoptarg` will still give a first optional argument
          for standard latex macros, for backwards compatibility.

       If non-`None`, this corresponds to the optional argument of the macro.

    .. py:attribute:: nodeargs

       .. deprecated:: 2.0

          Macro arguments are stored in `nodeargd` in pylatexenc 2.  Accessing
          the argument `nodeargs` will still provide a list of argument nodes
          for standard latex macros, for backwards compatibility.

       A list of arguments to the macro. Each item in the list is a
       :py:class:`LatexNode`.
    c                 f   |                     dt          j                              }|                     dd          }|                     dd           }|                     dg           } t          t          |           j        d	ddd| || _        || _        || _        || _	        || _
        d S )
Nnodeargdmacro_post_spacer4   
nodeoptargnodeargs)rZ   r   r   )r   r   rt   r   r
   )r   r   ParsedMacroArgsr.   r   r/   rZ   r   r   r   r   )r1   rZ   r   r   r   r   r   r2   s          r   r/   zLatexMacroNode.__init__  s    J	(A(C(CDD$6;;::lD11
J++,nd##, 	A 9	 	 	 	 	
 #  0$ r   c                     t           S r	   )r   r?   s    r   r   zLatexMacroNode.nodeType  r   r   r   rD   s   @r   r   r     sR        5 5l! ! ! ! !&      r   r   c                   (     e Zd ZdZ fdZd Z xZS )LatexEnvironmentNodea{  
    A LaTeX Environment Node, i.e. ``\begin{something} ... \end{something}``.

    .. py:attribute:: environmentname

       The name of the environment ('itemize', 'equation', ...)

    .. py:attribute:: nodelist

       A list of :py:class:`LatexNode`'s that represent all the contents between
       the ``\begin{...}`` instruction and the ``\end{...}`` instruction.

    .. py:attribute:: nodeargd

       The :py:class:`pylatexenc.macrospec.ParsedMacroArgs` object that
       represents the arguments passed to the environment.  These are arguments
       that are present after the ``\begin{xxxxxx}`` command, as in
       ``\begin{tabular}{ccc}`` or ``\begin{figure}[H]``.  Arguments must be
       declared in the latex context passed to the :py:class:`LatexWalker`
       constructor, using a suitable
       :py:class:`pylatexenc.macrospec.EnvironmentSpec` object.  Some known
       environments are already declared in the default latex context.

       .. versionadded:: 2.0

          The `nodeargd` attribute was introduced in `pylatexenc 2`.

    The following attributes are available, but they are obsolete since
    `pylatexenc 2.0`.

    .. py:attribute:: envname

       .. deprecated:: 2.0

          This attribute was renamed `environmentname` for consistency with the
          rest of the package.

    .. py:attribute:: optargs

       .. deprecated:: 2.0

          Macro arguments are stored in `nodeargd` in `pylatexenc 2`.  Accessing
          the argument `optargs` will still give a list of initial optional
          arguments for standard latex macros, for backwards compatibility.

    .. py:attribute:: args

       .. deprecated:: 2.0

          Macro arguments are stored in `nodeargd` in `pylatexenc 2`.  Accessing
          the argument `args` will still give a list of curly-brace-delimited
          arguments for standard latex macros, for backwards compatibility.
    c                 H   |                     dt          j                              }|                     dg           }|                     dg           } t          t          |           j        dddd| || _        || _        || _        || _	        || _
        || _        d S )Nr   optargsr   )environmentnamer   r   )envnamer   r   r   r
   )r   r   r   r.   r   r/   r   r   r   r   r   r   )r1   r   r   r   r   r   r   r2   s          r   r/   zLatexEnvironmentNode.__init__  s    ::j)*C*E*EFF**Y++zz&"%%2"D))2 	@ >	 	 	 	 	
  /  &			r   c                     t           S r	   )r   r?   s    r   r   zLatexEnvironmentNode.nodeType%  s    ##r   r   rD   s   @r   r   r     sR        4 4l    &$ $ $ $ $ $ $r   r   c                   (     e Zd ZdZ fdZd Z xZS )LatexSpecialsNodeaz  
    Represents a specials type node, e.g. ``&`` or ``~``

    .. py:attribute:: specials_chars

       The name of the specials (string), *without* the leading backslash.

    .. py:attribute:: nodeargd

       If the specials spec (cf. :py:class:`~pylatexenc.macrospec.SpecialsSpec`)
       has `args_parser=None` then the attribute `nodeargd` is set to `None`.
       If `args_parser` is specified in the spec, then the attribute `nodeargd`
       is a :py:class:`pylatexenc.macrospec.ParsedMacroArgs` instance that 
       represents the arguments to the specials.

       The `nodeargd` attribute can also be `None` even if the specials expects
       arguments, in the special situation where
       :py:meth:`LatexWalker.get_latex_expression()` encounters this specials.

       Arguments must be declared in the latex context passed to the
       :py:class:`LatexWalker` constructor, using a suitable
       :py:class:`pylatexenc.macrospec.SpecialsSpec` object.  Some known latex
       specials are already declared in the default latex context.

    .. versionadded:: 2.0

       Latex specials were introduced in `pylatexenc 2.0`.
    c                     |                     dd           } t          t          |           j        dddi| || _        || _        d S )Nr   rt   )specials_charsr   r
   )r   r.   r   r/   r   r   )r1   r   r   r   r2   s       r   r/   zLatexSpecialsNode.__init__E  sb    J--/&&/ 	 	3		 	 	 - r   c                     t           S r	   )r   r?   s    r   r   zLatexSpecialsNode.nodeTypeO  s      r   r   rD   s   @r   r   r   (  sQ         8! ! ! ! !! ! ! ! ! ! !r   r   c                   ,     e Zd ZdZg f fd	Zd Z xZS )LatexMathNodea   
    A Math node type.

    Note that currently only 'inline' math environments are detected.

    .. py:attribute:: displaytype

       Either 'inline' or 'display', to indicate an inline math block or a
       display math block. (Note that math environments such as
       ``\begin{equation}...\end{equation}``, are reported as
       :py:class:`LatexEnvironmentNode`'s, and not as
       :py:class:`LatexMathNode`'s.)

    .. py:attribute:: delimiters

       A 2-item tuple containing the begin and end delimiters used to delimit
       this math mode section.

       .. versionadded:: 2.0

          The `delimiters` attribute was introduced in `pylatexenc 2`.

    .. py:attribute:: nodelist
    
       The contents of the environment, given as a list of
       :py:class:`LatexNode`'s.
    c                     |                     dd          } t          t          |           j        dddi| || _        || _        || _        d S )Nr   NNrt   )displaytyper   r   r
   )r   r.   r   r/   r   r   r   )r1   r   r   r   r   r2   s        r   r/   zLatexMathNode.__init__q  sh    ZZl;;
+mT""+ 	
 	
=	
	
 	
 	

 ' $r   c                     t           S r	   )r   r?   s    r   r   zLatexMathNode.nodeType}  s    r   r   rD   s   @r   r   r   U  s[         6 .0 
% 
% 
% 
% 
% 
%      r   r   c                   *     e Zd Z fdZd Zd Z xZS )_PushPropOverridec                     t          t          |                                            || _        || _        || _        d S r	   )r.   r   r/   objpropname	new_value)r1   r   r   r   r2   s       r   r/   z_PushPropOverride.__init__  s9    &&//111 "r   c                     | j         ?t          | j        | j                  | _        t          | j        | j        | j                    | S r	   )r   r   r   r   initvalsetattrr?   s    r   	__enter__z_PushPropOverride.__enter__  s<    >%"48T];;DLDHdmT^<<<r   c                 X    | j         "t          | j        | j        | j                   d S d S r	   )r   r   r   r   r   )r1   typevalue	tracebacks       r   __exit__z_PushPropOverride.__exit__  s0    >%DHdmT\::::: &%r   )r    r!   r"   r/   r   r   rC   rD   s   @r   r   r     sV        # # # # #  ; ; ; ; ; ; ;r   r   c                   <     e Zd ZdZ fdZd Zd ZddZd Z xZ	S )	ParsingStateaX
  
    Stores some information about the current parsing state, such as whether we
    are currently in a math mode block.

    One of the ideas of `pylatexenc` is to make the parsing of LaTeX code mostly
    state-independent mark-up parsing (in contrast to a full TeX engine, whose
    state constantly changes and whose parsing behavior is altered dynamically
    while parsing).  However a minimal state of the context might come in handy
    sometimes.  Perhaps some macros or specials should behave differently in
    math mode than in text mode.

    This class also stores some essential information that is associated with
    :py:class:`LatexNode`\ 's and which provides a context to better understand
    the node structure.  For instance, we store the original parsed string, and
    each node refers to which part of the string they represent.
    
    .. py:attribute:: s

       The string that is parsed by the :py:class:`LatexWalker`

    .. py:attribute:: latex_context

       The latex context (with macros/environments specifications) that was used
       when parsing the string `s`.  This is a
       :py:class:`pylatexenc.macrospec.LatexContextDb` object.

    .. py:attribute:: in_math_mode

       Whether or not we are in a math mode chunk of LaTeX (True or False).
       This can be inline or display, and can be caused by an equation
       environment.

    .. py:attribute:: math_mode_delimiter

       Information about the kind of math mode we are currently in, if
       `in_math_mode` is `True`.  This is a string which can be set to aid the
       parser.  The parser sets this field to the math mode delimiter that
       initiated the math mode (one of ``'$'``, ``'$$'``, ``r'\('``, ``r'\)'``).
       For user-initiated math modes (e.g. by a custom environment definition),
       you can set this string to any custom value EXCEPT any of the core math
       mode delimiters listed above.

       .. note:: The tokenizer/parser relies on the value of the
                 `math_mode_delimiter` attribute to disambiguate two consecutive
                 dollar signs ``...$$...`` into either a display math mode
                 delimiter or two inline math mode delimiters (as in
                 ``$a$$b$``).  You should only set `math_mode_delimiter='$'` if
                 you know what you're doing.

    .. versionadded:: 2.0
 
       This class was introduced in version 2.0.

    .. versionadded:: 2.7

       The attribute `math_mode_delimiter` was introduced in version 2.7.

    .. versionchanged:: 2.7

       All arguments must now be specified as keyword arguments as of version
       2.7.
    c                     t          t          |                                            d | _        d | _        d| _        d | _        d| _        |                    dd          }| 	                    ||           d S )NF)r)   latex_contextin_math_modemath_mode_delimiter_do_sanitizeT)do_sanitize)
r.   r   r/   r)   r   r   r   rt   r   _set_fields)r1   r   r   r2   s      r   r/   zParsingState.__init__  sw    lD!!**,,,!!#' Vjj66[99999r   c                 r     | j         dddi|                                 }|                    |           |S )a(  
        Return a new :py:class:`ParsingState` instance that is a copy of the current
        parsing state, but where the given properties keys have been set to the
        corresponding values (given as keyword arguments).

        This makes it easy to create a sub-context in a given parser.  For
        instance, if we enter math mode, we might write::

           parsing_state_inner = parsing_state.sub_context(in_math_mode=True)

        If no arguments are provided, this returns a copy of the present parsing
        context object.
        r   Fr
   )r2   
get_fieldsr   )r1   r   ps      r   sub_contextzParsingState.sub_context  sA     DNCCC1B1BCC	fr   c                 D     t           fd j        D                       S )zl
        Returns the fields and values associated with this `ParsingState` as a
        dictionary.
        c                 4    g | ]}|t          |          fS r
   r   )rd   r   r1   s     r   re   z+ParsingState.get_fields.<locals>.<listcomp>  s(    AAAqaq))*AAAr   )rf   rt   r?   s   `r   r   zParsingState.get_fields  s*    
 AAAADLAAABBBr   Tc                     |                                 D ]B\  }}|| j        vr#t          d                    ||                    t	          | ||           C|r|                     |           d S d S )Nz'Invalid field for ParsingState: {}={!r})given_fields)itemsrt   
ValueErrorr8   r   	_sanitize)r1   r   r   r   vs        r   r   zParsingState._set_fields  s    LLNN 	  	 DAq$$ !J!Q!QRSUV!W!WXXXD!Q 	0 NNN/////	0 	0r   c                     | j         s4| j        r/d| _        d|v r&t                              d| j                   dS dS dS dS )aC  
        Sanitize the parsing state.  E.g., clear any `math_mode_delimiter` if
        `in_math_mode` is `False`.

        The argument `given_fields` is what fields the user required to set;
        this is used to generate warnings if incompatible field configurations
        were explicitly required to be set.
        Nr   zFParsingState: You set math_mode_delimiter=%r but in_math_mode is False)r   r   loggerwarning)r1   r  s     r   r  zParsingState._sanitize
  sq       	T%= 	'+D$$44,-1-E    	 	 	 	44r   T)
r    r!   r"   r#   r/   r   r   r   r  rC   rD   s   @r   r   r     s        = =|
: 
: 
: 
: 
:  (C C C
0 
0 
0 
0      r   r   c                        e Zd ZdZd fd	Zd Zd Zd Z	 	 ddZd	 Z	d
 Z
ddZddZddZddZddZd Z	 	 	 	 ddZ xZS )LatexWalkeraR  
    A parser which walks through an input stream, parsing it as LaTeX markup.

    Arguments:

      - `s`: the string to parse as LaTeX code

      - `latex_context`: a :py:class:`pylatexenc.macrospec.LatexContextDb`
        object that provides macro and environment specifications with
        instructions on how to parse arguments, etc.  If you don't specify this
        argument, or if you specify `None`, then the default database is used.
        The default database is obtained with
        :py:func:`get_default_latex_context_db()`.

        .. versionadded:: 2.0

           This `latex_context` argument was introduced in version 2.0.

    Additional keyword arguments are flags which influence the parsing.
    Accepted flags are:

      - `tolerant_parsing=True|False` If set to `True`, then the parser
        generally ignores syntax errors rather than raising an exception.

      - `strict_braces=True|False` This option refers specifically to reading a
        encountering a closing brace when an expression is needed.  You
        generally won't need to specify this flag, use `tolerant_parsing`
        instead.

    The methods provided in this class perform various parsing of the given
    string `s`.  These methods typically accept a `pos` parameter, which must be
    an integer, which defines the position in the string `s` to start parsing.

    These methods, unless otherwise documented, return a tuple `(node, pos,
    len)`, where node is a :py:class:`LatexNode` describing the parsed content,
    `pos` is the position at which the LaTeX element of iterest was encountered,
    and `len` is the length of the string that is considered to be part of the
    `node`.  That is, the position in the string that is immediately after the
    node is `pos+len`.

    The following obsolete flag is accepted by the constructor for backwards
    compatibility with `pylatexenc 1.x`:

      - `macro_dict`: This argument is kept for compatibility with `pylatexenc
        1.x`.  This is a dictionary of known LaTeX macro specifications.  If
        specified, this should be a dictionary where the keys are macro names
        and values are :py:class:`pylatexenc.macrospec.MacroSpec` instances, as
        returned for instance by the `pylatexenc 1.x`-emulating function
        :py:func:`MacrosDef`.  If you specify this argument, you cannot provide
        a custom `latex_context`.  This argument is superseded by the
        `latex_context` argument.  Furthermore, if you specify this argument, no
        specials are parsed so that the behavior closer to `pylatexenc 1.x`.

        .. deprecated:: 2.0
    
           The `macro_dict` argument has been replaced by the much more powerful
           `latex_context` argument which allows you to further provide
           environment specifications, etc.
    
      - `keep_inline_math=True|False`: Obsolete option.  In `pylatexenc 1.x`,
        this option triggered a weird behavior especially since there is a
        similarly named option in
        :py:class:`pylatexenc.latex2text.LatexNodes2Text` with a different
        meaning.  [See `Issue #14
        <https://github.com/phfaist/pylatexenc/issues/14>`_.]  You should now
        only use the option `math_mode=` in
        :py:class:`pylatexenc.latex2text.LatexNodes2Text`.

        .. deprecated:: 2.0

           This option is ignored starting from `pylatexenc 2`.  Instead, you
           should set the option `math_mode=` accordingly in
           :py:class:`pylatexenc.latex2text.LatexNodes2Text`.


    .. py:attribute:: s
    
       The string that is being parsed.

       Do NOT modify this attribute.
    Nc                    || _         d | _        d| _        |d|v rt          j        d           |                    dd           }t                      }|                    dg          }|                    d|	                                |
                                           n"t                      }nd|v rt          d          t          | j         |          | _        |                    d	d
          | _        |                    dd          | _        d|v rt          j        d           |d= |r-t                               d|                                           t'          t(          |                                            d S )NF
macro_dictzThe `macro_dict=...` option in LatexWalker() is obsolete since pylatexenc 2.  It'll still work, but please consider using instead the more versatile option `latex_context=...`.rN   )
keep_whichcustomz@Cannot specify both `latex_context=` and `macro_dict=` arguments)r)   r   tolerant_parsingTstrict_braceskeep_inline_mathzThe keep_inline_math=... option in LatexWalker() has no effect in pylatexenc 2.  Please consider using the more versatile option math_mode=... in LatexNodes2Text() instead.z.LatexWalker(): Unknown flag(s) encountered: %r)r)   _line_no_calcdebug_nodesr   rX   r   rV   filter_contextrR   valuesiter_environment_specsr   r   default_parsing_stater  r  r  r	  keysr.   r  r/   )r1   r)   r   r   r  default_latex_contextr2   s         r   r/   zLatexWalker.__init__u  s    "  v%%-E   $ZZd;;
(D(F(F% 5 D D ./ !E ! ! 22%%'')@@BB    != > > v%%V   &2f'&
 &
 &
" !'

+=t D D#ZZ??'')>  
 )* 	\NNKV[[]][[[k4  ))+++++r   c                 &     | j         j        di |S )a^  
        Return a new parsing state object that corresponds to the current string
        that we are parsing (`s` provided to the constructor) and the current
        latex context (`latex_context` provided to the constructor).

        If no arguments are provided, this returns the default parsing state.

        If keyword arguments are provided, then they can override fields from
        the default parsing state.  For instance, if we enter math mode, you
        might use::
        
          parsing_state_mathmode = \
              my_latex_walker.make_parsing_state(in_math_mode=True)
        r
   )r  r   )r1   r   s     r   make_parsing_statezLatexWalker.make_parsing_state  s      6t)5?????r   c                 "    | j         | j        ddS )aW  
        The parse flags currently set on this object.  Returns a dictionary with
        keys 'keep_inline_math', 'tolerant_parsing' and 'strict_braces'.

        .. deprecated:: 2.0

           The 'keep_inline_math' key is always set to `None` starting in
           `pylatexenc 2` and might be removed entirely in future versions.
        N)r  r  r  )r  r  r?   s    r   parse_flagszLatexWalker.parse_flags  s"     !% 5!/ $	
 
 	
r   c                 <    t                               d|           d S )Nz0Ignoring parse error (tolerant parsing mode): %s)r  info)r1   excs     r   _report_ignore_parse_errorz&LatexWalker._report_ignore_parse_error  s    FLLLLLr   Tc           	      6    |                                  }dg}|r||z  }d|v r|                    d          s|dgz  } j        d fd}t                    k     r                                         rq         z  dz                      d          rt          d	dd
z
  d
dd                   S t                    k     r                                         qt                    k    rt                             dk    rQdz   t                    k    rt                      dz            }	d}
d
}dz                                            r{d}
|z   t                    k     rc|z                                            rF|	|z            z  }	|dz  }|z   t                    k     r|z                                            F|	dv rt          dd|	z   |          S |	dv rt          dd|	z   |          S |r|	dv rt          j
        d|z   d                   }|- |d                    |	          |d|	z             \  }}|r||S t          |	dk    rdnd|                    d          ||                                z             S d}|
r|z   t                    k     r|z                                            rk||z            z  }|dz  }|                    d          r|dd         }|d
z  }n3|z   t                    k     r|z                                            kt          d|	||          S          dk    rt          j        d                                        }d}||                    d                              d           r1|                                z
  }|                                z
  }d}nY|                                z
  }|                                z
  }|                                }nt                    z
  }|}d}t          d!dz   |z            ||          S t%          | \  }}         |v rt          d"         d          S          |v rt          d#         d          S                     d$          r&|j        r|j        d%k    st          dd$d
          S                     d%          rt          dd%d          S |j                            |&          }|&t          d'|t          |j                            S t          d	         d          S )(a+	  
        Parses the latex content given to the constructor (and stored in `self.s`),
        starting at position `pos`, to parse a single "token", as defined by
        :py:class:`LatexToken`.

        Parse the token in the stream pointed to at position `pos`.

        For tokens of type 'char', usually a single character is returned.  The
        only exception is at paragraph boundaries, where a single 'char'-type
        token has argument '\\n\\n'.

        Returns a :py:class:`LatexToken`. Raises
        :py:exc:`LatexWalkerEndOfStream` if end of stream reached.

        The argument `include_brace_chars=` allows to specify additional pairs
        of single characters which should be considered as braces (i.e., of
        'brace_open' and 'brace_close' token types).  It should be a list of
        2-item tuples, for instance ``[('[', ']'), ('<', '>')]``.  The pair
        `('{', '}')` is always considered as braces.  The delimiters may not
        have more than one character each.

        If `environments=False`, then ``\begin`` and ``\end`` tokens count as
        regular 'macro' tokens (see :py:class:`LatexToken`); otherwise (the
        default) they are considered as the token types 'begin_environment' and
        'end_environment'.

        The parsing of the tokens might be influcenced by the `parsing_state` (a
        :py:class:`ParsingState` instance).  Currently, the only influence this
        has is that some latex specials are parsed differently if in math mode.
        See doc for :py:class:`ParsingState`.  If `parsing_state` is `None`, the
        default parsing state returned by :py:meth:`make_parsing_state()` is
        used.

        .. deprecated:: 2.0

           The flag `keep_inline_math` is only accepted for compatibiltiy with
           earlier versions of `pylatexenc`, but it has no effect starting in
           `pylatexenc 2`.  See the :py:class:`LatexWalker` class doc.

        .. deprecated:: 2.0

           If `brackets_are_chars=False`, then square bracket characters count
           as 'brace_open' and 'brace_close' token types (see
           :py:class:`LatexToken`); otherwise (the default) they are considered
           just like other normal characters.

        .. versionadded:: 2.0

           The `parsing_state` argument was introduced in version 2.0.
        Nr   brackets_are_chars[]r4   c                     t          d| d                    d          }j        r+                    |           d t	          d||          fS |d fS )Nr)   r*   r(   Tas_dictcharrl   r
   )r%   pos_to_lineno_colnor  r#  rj   )r(   ro   placeholderer*   r)   r1   spaces       r   _token_parse_errorz1LatexWalker.get_token.<locals>._token_parse_error8  s    %   **3*==	 A $ //222Z##     d7Nr   rK   z

r-  r   rl   )rH   \FTmathmode_display)r   r   mathmode_inline)beginendz^\s*\{([\w* ._-]+)\}z+Bad \{} macro: expected {{environmentname}})r(   ro   r/  r7  begin_environmentend_environmentrq   )rm   rn   r*   ro   rp   rs   %z(\n|\r|\n\r)(?P<extraspace>\s*)
extraspace)
z
rr   
brace_openbrace_close$$$r   rO   )r  r   r)   ro   isspaceendswithrj   rF   isalpharematchr8   groupr8  compilesearch
startswithstartzipr   r   r   test_for_specialsr   )r1   r*   include_brace_charsrN   r  r   r   brace_charsr2  rq   isalphamacroienvmatchr0  r   rs   r`   mlenarglenmspaceopenbracecharsclosebracecharssspecr)   r1  s   ``                     @@r   	get_tokenzLatexWalker.get_token  s   j   3355M!l 	/..K6))::233 ,
|+F$	 	 	 	 	 	 	 	$ CFFllqv~~//lQsVOE1HC~~f%% 8!f&c!e,1#2#J8 8 8 8	 CFFllqv~~//l #a&&==(U;;;;S6T>>1uA,...c!eHE LAQx!! #!eCFFllqQx'7'7'9'9lQs1uX%EFA !eCFFllqQx'7'7'9'9l 
""!&8d5j&)qEC C C C
""!&7T%Z&)qEC C C C  )9 9 98$;Qs1uvvYGG#--JQQRWXX$(J  DAq
   H!050@0@,,FW q))(,,..(#    J !eCFFllqQx'7'7'9'9l!CE(*JFA!**622  &0_
Q !eCFFllqQx'7'7'9'9l 'u#1(-*F F F F S6S==
=>>EEaMMAD}77<((335JLL 	' WWYYs]F7799S=DFFWWYYs]F55773;DWWYYFFQ)3q5V3C1D#SW(-&B B B B +.{*;'S6^##,AcFV[\\\\S6_$$-QsV!W\]]]] <<c"" 	C ". C=3TX[3[3[!&8d&)qEC C C C<<S!! 	_"3#1X]^^^^+==s- > 
 
 *%"%3u/C+D+DPUW W W W
 f!C&cqERRRRr   c                     |                     d          |                     d          |                     d          }}} |d|||d|}| j        rt                              d|           |S )a  
        Create and return a node of type `node_class` which holds a representation
        of the latex code at position `pos` and of length `len` in the parsed
        string.

        The node class should be a :py:class:`LatexNode` subclass.  Keyword
        arguments are supplied directly to the constructor of the node class.

        Mandatory keyword-only arguments are 'pos', 'len', and 'parsing_state'.

        All nodes produced by :py:meth:`get_latex_nodes()` and friends use this
        method to create node classes.

        .. versionadded:: 2.0
        
           This method was introduced in `pylatexenc 2.0`.
        r*   ro   r   )r*   ro   r   zNew node: %rr
   )r   r  r  debug)r1   
node_classr   r*   ro   r   nodes          r   	make_nodezLatexWalker.make_node  s|    ( JJuvzz%00&**_2M2M  S zRcs-RR6RR 	/LL...r   c                 ,     | j         |f|||d|||fS )N)r   r*   ro   )r`  )r1   nclassr   r*   ro   r   s         r   _mknodeposlenzLatexWalker._mknodeposlen  s3    DN6[CS[[TZ[[
 	
r   Fc                     | j         t          j        | j                  | _         | j                             ||          S )a}  
        Return the line and column number corresponding to the given `pos` in our
        string `self.s`.

        The first time this function is called, line numbers are calculated for
        the entire string.  These are cached for future calls which are then
        fast.

        Return a tuple `(lineno, colno)` giving line number and column number.
        Line numbers start at 1 and column numbers start at zero, i.e., the
        beginning of the document (`pos=0`) has line and column number `(1,0)`.
        If `as_dict=True`, then a dictionary with keys 'lineno', 'colno' is
        returned instead of a tuple.
        Nr+  )r  r   LineNumbersCalculatorr)   r.  )r1   r*   r,  s      r   r.  zLatexWalker.pos_to_lineno_colno  s>      %!&!<TV!D!DD!55c75KKKr   c                    ||                                  }t          | d|          5  |                     |d|          }|j        dk    r|j        dk    r`| j        s)t          d| j        |fi |                     |d	          | 	                    t          |d
|j        d          cddd           S | 	                    t          ||j        d|j        dd|j        |j        	  	        cddd           S |j        dk    r@| 	                    t          ||j        j        d|j        |j                  cddd           S |j        dk    r0|                     |j        |j        z   |          cddd           S |j        dk    r(|                     |j        |          cddd           S |j        dk    r| j        rH| j        sAt          d                    |j                  | j        |fi |                     |d	          | 	                    t          |d
|j        d          cddd           S |j        dk    r:| 	                    t          ||j        |j        |j                  cddd           S |j        dv r|j                            d          rB| 	                    t          ||j        dd|j        |j        |j                  cddd           S | 	                    t          ||j        |j        |j                  cddd           S t          d                    |j                  | j        |fi |                     |d	          # 1 swxY w Y   dS )aI  
        Parses the latex content given to the constructor (and stored in `self.s`),
        starting at position `pos`, to parse a single LaTeX expression.

        Reads a latex expression, e.g. macro argument. This may be a single char, an escape
        sequence, or a expression placed in braces.  This is what TeX calls a "token" (and
        not what we call a token... anyway).

        Parsing might be influenced by the `parsing_state`.  See doc for
        :py:class:`ParsingState`.  If `parsing_state` is `None`, then the
        default parsing state is used.

        Returns a tuple `(node, pos, len)`, where `pos` is the position of the
        first char of the expression and `len` the length of the expression.

        .. versionadded:: 2.0

           The `parsing_state` argument was introduced in version 2.0.
        Nr  F)rN   r   rq   r8  zExpected expression, got \endTr+  r4   r   r   r   r*   ro   r   rZ   r   r   r   r   r*   ro   rO   r   r   r   r*   ro   rr   rC  r?  r@  z+Expected expression, got closing brace '{}'r-  r6  r5  r4  )r   rZ   r   r   r   r*   ro   zUnknown token type: {})r  r   r[  rm   rn   r  r%   r)   r.  rc  r   r*   r   rs   ro   r   r   get_latex_expressionget_latex_braced_groupr  r8   rL  )r1   r*   r  r   rm   s        r   rk  z LatexWalker.get_latex_expression  sa   *   3355Mt_mDD L	? L	?..5.VVCw'!!7e##0 93< FCK K #66sD6IIK K K
  $11.@M8:69g67	  2  9  9L	? L	? L	? L	? L	? L	? L	? L	?$ )).8E47G37;>>59D.1g37 * D D%L	? L	? L	? L	? L	? L	? L	? L	?2 w*$$))*;8E9<9O37.1g37	 * D D5L	? L	? L	? L	? L	? L	? L	? L	?> w)##00P]0^^AL	? L	? L	? L	? L	? L	? L	? L	?B w,&&2237-2XXEL	? L	? L	? L	? L	? L	? L	? L	?F w-''
 % d.C /ELLSWUU  2232EE  
 )).8E02.1g1 * > >]L	? L	? L	? L	? L	? L	? L	? L	?d w&  )).8E03.1g.1g	 * 7 7gL	? L	? L	? L	? L	? L	? L	? L	?p wAAA7%%d++ ;--n<I8;9=7;?B~25'25' . ; ;wL	? L	? L	? L	? L	? L	? L	? L	?H  --n<I47G25'25'	 . ; ;IL	? L	? L	? L	? L	? L	? L	? L	?T ((//88$&#? ?**3*==? ? ?UL	? L	? L	? L	? L	? L	? L	? L	? L	? L	?sK   BM"76M":>M".M" &M"3A=M"=8M"AM"'-M"!AM""M&)M&c                     ||                                  }	 |                     |dgd|          }n# t          $ r Y dS w xY w|j        dk    r#|j        dk    r|                     |d|          S dS )a  
        Parses the latex content given to the constructor (and stored in `self.s`),
        starting at position `pos`, to attempt to parse an optional argument.

        Parsing might be influenced by the `parsing_state`. See doc for
        :py:class:`ParsingState`.  If `parsing_state` is `None`, the default
        parsing state is used.

        Attempts to parse an optional argument. If this is successful, we return
        a tuple `(node, pos, len)` if success where `node` is a
        :py:class:`LatexGroupNode`.  Otherwise, this method returns None.

        .. versionadded:: 2.0

           The `parsing_state` argument was introduced in version 2.0.
        Nr&  F)rP  rN   r   r?  r'  
brace_typer   )r  r[  rF   rm   rn   rl  )r1   r*   r   rm   s       r   get_latex_maybe_optional_argz(LatexWalker.get_latex_maybe_optional_argi  s    $   3355M	..:,UZ/< ! > >CC% 	 	 	 44		 7l""sw#~~..ss=J / L L L ts   3 
A Ar   c           	      t   ||                                  }d}|dk    rd}nF|dk    rd}n=|dk    rd}n4|dk    rd	}n+t          |          d
k    r|\  }}nt          d|z            d}|r|dk    r||fg}|                     |||          }|j        dk    s|j        |k    r8t          d| j        |d| j        |         z  d|                     |d          | 	                    |j
        |j        z   ||f|          \  }}}	|                     t          ||||f|j
        ||	z   |j
        z
            S )a  
        Parses the latex content given to the constructor (and stored in `self.s`),
        starting at position `pos`, to read a latex group delimited by braces.

        Reads a latex expression enclosed in braces ``{ ... }``. The first token of
        `s[pos:]` must be an opening brace.

        Parsing might be influenced by the `parsing_state`.  See doc for
        :py:class:`ParsingState`.  If `parsing_state` is `None`, the default
        parsing state is used.

        Returns a tuple `(node, pos, len)`, where `node` is a
        :py:class:`LatexGroupNode` instance, `pos` is the position of the first
        char of the expression (which has to be an opening brace), and `len` is
        the length of the group, including the closing brace (relative to the
        starting position).

        The group must be delimited by the given `brace_type`.  `brace_type` may
        be one of ``{``, ``[``, ``(`` or ``<``, or a 2-item tuple of two
        distinct single characters providing the opening and closing brace
        chars (e.g., ``("<", ">")``).

        .. versionadded:: 2.0

           The `parsing_state` argument was introduced in version 2.0.
        Nr   r   r'  r(  r   r   <>r   z3Invalid brace type for get_latex_braced_group(): %srP  r   r?  z8get_latex_braced_group: not an opening brace/bracket: %sr*  Tr+  )stop_upon_closing_bracer   )r   r   r   r*   ro   r
   )r  ro   r  r[  rm   rn   r%   r)   r.  get_latex_nodesr*   rc  r   )
r1   r*   ro  r   closing_bracerP  firsttokr   nposnlens
             r   rl  z"LatexWalker.get_latex_braced_group  s   8   3355MMM3MM3MM3MM__!!(2%JRU_`aaa" 	@*++$.#>"?>>#;N0= " ? ?<<''X\Z-G-G' &NQUQWX[Q\]  **3*==	   "&!5!5L8<'%/$?' "6 "
 "
4 !!.80=.8--H(0(,thl(B	 " D D 	Dr   c                 
   ||                                  }|}|                     ||          }|j        dk    s|D|j        |k    r9t	          d| j        |d||ndd|j        d|                     |d	          ||j        }|j        |j        z   }|j	        
                    |          }|t          j        d
          }	 |                    | ||          }nR# t          t          f$ r>}|                     ||d                    |                    }||d|di f}Y d}~nd}~ww xY wt          |          dk    r|\  }	}
}}n|\  }	}
}i }|
|z   }|                    d|          }|j        r|                    dd|z   dz             }|                     |||          \  }}}|	"|	j        r|	j        d         }|	j        d         }ndg }}|                     t.          ||||	|g||||z   |z
  	  	        S )a  
        Parses the latex content given to the constructor (and stored in `self.s`),
        starting at position `pos`, to read a latex environment.

        Reads a latex expression enclosed in a
        ``\begin{environment}...\end{environment}``.  The first token in the
        stream must be the ``\begin{environment}``.

        If `environmentname` is given and nonempty, then additionally a
        :py:exc:`LatexWalkerParseError` is raised if the environment in the
        input stream does not match the provided environment name.

        Arguments to the begin environment command are parsed according to the
        corresponding specification in the given latex context `latex_context`
        provided to the constructor.  The environment name is looked up as a
        "macro name" in the macro spec.

        Parsing might be influenced by the `parsing_state`.  See doc for
        :py:class:`ParsingState`.  If `parsing_state` is `None`, the default
        parsing state is used.

        Returns a tuple (node, pos, len) where node is a
        :py:class:`LatexEnvironmentNode`.

        .. versionadded:: 2.0

           The `parsing_state` argument was introduced in version 2.0.
        NrC  r9  z'get_latex_environment: expected \begin{z<environment name>z}: r*  Tr+  r4   wr*   r   z'arguments of environment "\begin{{{}}}"r      inner_parsing_stater   r   r   r   )stop_upon_end_environmentr   rK   )r   r   r   r   r   r   r*   ro   r
   )r  r[  rm   rn   r%   r)   r.  r*   ro   r   get_environment_specr   EnvironmentSpec
parse_argsrF   _exchandle_parse_subexpressionr8   getis_math_moder   rv  legacy_nodeoptarg_nodeargsrc  r   )r1   r*   r   r   startposrx  env_spec
argsresultr0  argdaposalenadicparsing_state_innerr   ry  rz  legnodeoptarglegnodeargss                      r   get_latex_environmentz!LatexWalker.get_latex_environment  s   <   3355M>>#]>CC<...'HLO,K,K' &C'6'BOOH\\\LL  **3*==   #&lOlX\) .CCOTT 044H		,!,,tM,ZZJJ&(=> 	, 	, 	,33<CCOTT A
 }AgQ+JJJJJJ	, z??a'1$T4tt!+T4DTk"hh'<mLL  	"/";";!$'$7$; #< # #
 "&!5!5cP_DW "6 "Y "Y4  ? ;A>M9!<KK)-r;M!!"60=2A+3+/+8/'2&.&*4i&8 " 	: 	: 		:s   
C# #D244D--D2c                 2   t          |t                    rGt          d| j        |j        d                    |          d|                     |j        d          }t          |dd          5|j        .|j	        '|                     |j                  \  |_        |_	        |j
                            t          d                    |          |j        g|                     |j                  R             | j        r|                     |           dS |S )	a  
        (INTERNAL.) Handle an exception raised by a method that you called to parse
        a macro arguments or another "sub-expression".  Use as::

            except (LatexWalkerEndOfStream, LatexWalkerParseError) as e:
                e = self._exchandle_parse_subexpression(e, <tok>, "what this is about")
                if e is not None: raise e
                ... # do sth to recover from parse error in tolerant mode

        Use in an exception handler that captures both `LatexWalkerEndOfStream`
        and `LatexWalkerParseError`.  Returns what exception you should raise if
        you got one of these while parsing, e.g., macro arguments.
        zEnd of input while parsing {}r*  Tr+  r*   Nz{}r
   )r   rF   r%   r)   r*   r8   r.  r   r+   r,   r-   ru   r   r  r#  )r1   r0  rm   r7   s       r   r  z*LatexWalker._exchandle_parse_subexpression@  s*    a/00 	% &G3::4@@  **37D*AA	 A 1eT"".183C $ 8 8 ? ?AHag	t{{4((#' ;0099; ; ;	
 	
 	

   	++A...4r   r   c           
           |                                  }g }dd}rGdk    rd}n3dk    rd}n*dk    rd}n!dk    rd	}nt                    d
k    r\  }dk    r|fg:|j        s3t                              d                    |j                             |}	 G d d          }
 |
||          } fd}	 	  |||          }n# t          $ r}ssrr	dz   dz   }nr	dz   dz   }n
rdz   dz   }t          d j        |j	        d                    |          d 
                    t           j                  d          } j        r                     |           d}n||}Y d}~n:d}~wt          $ r*} j        r                     |           d}n Y d}~nd}~ww xY w|rt          |t                    rC|                    |j	        |j                   |xj	        t          |j                  z  c_	        |j        r]|                                \  }}                     t&          |j        ||t          |                    }|                    |           ||	|j	        |	z
  fS )a'  
        Parses the latex content given to the constructor (and stored in `self.s`)
        into a list of nodes.

        Returns a tuple `(nodelist, pos, len)` where:

          - `nodelist` is a list of :py:class:`LatexNode`\ 's representing the
            parsed LaTeX code.

          - `pos` is the same as the `pos` given as argument; if there is
            leading whitespace it is reported in `nodelist` using a
            :py:class:`LatexCharsNode`.

          - `len` is the length of the parsed expression.  If one of the
            `stop_upon_...=` arguments are provided (cf below), then the `len`
            includes the length of the token/expression that stopped the
            parsing.
        
        If `stop_upon_closing_brace` is given and set to a character, then
        parsing stops once the given closing brace is encountered (but not
        inside a subgroup).  The brace is given as a character, ']', '}', ')',
        or '>'.  Alternatively you may specify a 2-item tuple of two single
        distinct characters representing the opening and closing brace chars.
        The returned `len` includes the closing brace, but the closing brace is
        not included in any of the nodes in the `nodelist`.

        If `stop_upon_end_environment` is provided, then parsing stops once the
        given environment was closed.  If there is an environment mismatch, then
        a `LatexWalkerParseError` is raised except in tolerant parsing mode (see
        :py:meth:`parse_flags()`).  Again, the closing environment is included
        in the length count but not the nodes.

        If `stop_upon_closing_mathmode` is specified, then the parsing stops
        once the corresponding math mode (assumed already open) is closed.  This
        argument may take the values `None` (no particular request to stop at
        any math mode token), or one of ``$``, ``$$``, ``\)`` or ``\]``
        indicating a closing math mode delimiter that we are expecting and at
        which point parsing should stop.

        If the token '$' (respectively '$$') is encountered, it is interpreted
        as the *beginning* of a new math mode chunk *unless* the argument
        `stop_upon_closing_mathmode=...` has been set to '$' (respectively
        '$$').

        If `read_max_nodes` is non-`None`, then it should be set to an integer
        specifying the maximum number of top-level nodes to read before
        returning.  (Top-level nodes means that macro arguments, environment or
        group contents, etc., do not count towards `read_max_nodes`.)  If
        `None`, the entire input string will be parsed.

        .. note::

           There are a few important differences between
           ``get_latex_nodes(read_max_nodes=1)`` and ``get_latex_expression()``:
           The former reads a logical node of the LaTeX document, which can be a
           sequence of characters, a macro invocation with arguments, or an
           entire environment, but the latter reads a single LaTeX "token" in
           a similar way to how LaTeX parses macro arguments.

           For instance, if a macro is encountered, then
           ``get_latex_nodes(read_max_nodes=1)`` will read and parse its
           arguments, and include it in the corresponding
           :py:class:`LatexMacroNode`, whereas ``get_latex_expression()`` will
           return a minimal :py:class:`LatexMacroNode` with no arguments
           regardless of the macro's argument specification.  The same holds for
           latex specials.  For environments,
           ``get_latex_nodes(read_max_nodes=1)`` will return the entire parsed
           environment into a :py:class:`LatexEnvironmentNode`, whereas
           ``get_latex_expression()`` will return a :py:class:`LatexMacroNode`
           named 'begin' with no arguments.

        Parsing might be influenced by the `parsing_state`.  See doc for
        :py:class:`ParsingState`.  If `parsing_state` is `None`, the default
        parsing state is used.

        .. versionadded:: 2.0

           The `parsing_state` argument was introduced in version 2.0.
        Nr   r   r(  r'  r   r   rs  rr  r   zlCall to LatexWalker.get_latex_nodes(stop_upon_closing_mathmode={!r}) but parsing state has in_math_mode={!r}c                   "    e Zd ZddZd Zd ZdS )/LatexWalker.get_latex_nodes.<locals>.PosPointerr4   Nc                 >    || _         || _        || _        || _        d S r	   )r*   r   	lastcharslastchars_pos)r1   r*   r   r  r  s        r   r/   z8LatexWalker.get_latex_nodes.<locals>.PosPointer.__init__  s&    %2"!*%2"""r   c                 F    | xj         |z  c_         | j        	|| _        d S d S r	   )r  r  )r1   r*   r   s      r   push_lastcharsz>LatexWalker.get_latex_nodes.<locals>.PosPointer.push_lastchars  s1    %'%-),D&&& .-r   c                 >    | j         | j        f}d| _        d | _         |S )Nr4   )r  r  )r1   ress     r   flush_lastcharsz?LatexWalker.get_latex_nodes.<locals>.PosPointer.flush_lastchars  s%    ($.8!#%)"
r   )r4   N)r    r!   r"   r/   r  r  r
   r   r   
PosPointerr    sF        3 3 3 3- - -
    r   r  )r*   r   c                     	 $                     |j        "|j                  }n8# t          $ r}$j        r|cY d}~S  d}~wt
          $ r}$j        rJ  d}~ww xY w|j        |j        z   |_        |j        dk    r@|                    |j        t          |j	                  z
  |j	        |j
        z              dS t          |j                  r|                                \  }}$                    t          |j        ||j	        z   ||j        |z
            }|                     |           #r!t          |           #k    r|j        |_        dS nt          |j	                  r$                    t          |j        |j	        |j        t          |j	                  z
  t          |j	                            }|                     |           #r!t          |           #k    r|j        |_        dS |j        dk    rI|j
        %k    r<t          d3$j        |j        d	|j
        z  d
$                    |j        d          dS |j        dk    r'sLt          d3$j        |j        d                    |j
                  d
$                    |j        d          |j
        'k    rMt          d3$j        |j        d                    |j
        '          d
$                    |j        d          dS |j        dv r&o|j
        &k    rdS |j
        dv rMt          d3$j        |j        d                    |j
        &          d
$                    |j        d          |j
        dv sJ nU|j
        dv rLt          d3$j        |j        d                    |j
                  d
$                    |j        d          ddd                    |j
        |j
                  }|j
        dv rdnd}	|j                            d|j
                  }
	 $                    |j        ||
          \  }}}nn# t
          $ ra}|j                            t/          d                    |j
                  |j        g$                    |j                  R              d}~ww xY w||z   |_        |                     $                    t0          |j        |	||j
        |f|j        ||z   |j        z
                       #rt          |           #k    rdS dS |j        dk    rg$                    t2          |j        |j
        |j        |j        |j                  }|                     |           #rt          |           #k    rdS dS |j        d k    r	 $                    |j        |j
        |j        !          \  }}}nV# t
          $ rI}|j                            t/          d"|j        g$                    |j                  R              d}~ww xY w||z   |_        |                     |           #rt          |           #k    rdS dS |j        d#k    r	 $                    |j        |j
        |j        $          \  }}}nn# t
          $ ra}|j                            t/          d%                    |j
                  |j        g$                    |j                  R              d}~ww xY w||z   |_        |                     |           #rt          |           #k    rdS dS |j        d&k    r|j
        }|j        j                            |          }|t?          j         d'          }	 |!                    $|j        |j        z   |j        (          }n_# t          t
          f$ rK}$"                    ||d)                    |                    }||d|j        |j        z   d*i f}Y d}~nd}~ww xY wt          |          d+k    r|\  }}}}n|\  }}}i }||z   |_        |"|j#        r|j#        d*         }|j#        d,         }ndg }}$                    tH          |j        |j
        ||j        |||j        |j        |j        z
  -	  	        }|                     |           d.|v r|d.         |_        #rt          |           #k    rdS dS |j        d/k    rJ|j
        }|j        |j        z   |_        d}	 |!                    $|j        |j        (          } n\# t          t
          f$ rH}$"                    ||d0                    |j%                            }||d|j        d*i f} Y d}~nd}~ww xY w| .t          |           d+k    r| \  }}}}!n| \  }}}i }!||z   |_        ni }!$                    tL          |j        |j%        ||j        |j        |j        z
  1          }|                     |           d.|!v r|!d.         |_        #rt          |           #k    rdS dS t          d3$j        |j        d2                    |          d
$                    |j        d          )4a  
            Read a single token and process it, recursing into brace blocks and
            environments etc if needed, and appending stuff to nodelist.

            Return True whenever we should stop trying to read more. (e.g. upon
            reaching the a matched stop_upon_end_environment etc.)  Can return
            an exception instance to give more information than simply `True`.
            rt  Nr-  r*   r   Frg  Tr@  z*Unexpected mismatching closing brace: '%s'r*  r+  r:  z$Unexpected closing environment: '{}'zDUnexpected mismatching closing environment: '{}', was expecting '{}'rj  )\)\]z2Mismatching closing math mode: '{}', expected '{}')rB  rA  \(\[z"Unexpected closing math mode: '{}'r  r  )r  r  )r  rB  inlinedisplayr  )stop_upon_closing_mathmoder   zmath mode "{}")r   r   r   r   r*   ro   rr   )r   rr   r   r*   ro   r?  rn  z
open bracer9  )r   r   zbegin environment "{}"rq   r4   r|  zarguments of macro "{}"r   r~  rK   rh  new_parsing_staterO   zarguments of specials "{}"ri  zUnknown token: {!r}r
   )'r[  r*   r   rF   r  r%   ro   rm   r  rp   rn   r  r  r`  r   ru   r)   r.  r8   r  r   rv  r-   r   r   r   rs   rl  r  r   get_macro_specr   	MacroSpecr  r  r  r   r   r   )(r   r   rm   r0  charsposr   strnodespacestrnodecorresponding_closing_mathmoder   r  mathinline_nodelistmposrU  commentnode	groupnodebposblenenvnodeeposelenrZ   mspecmargsresultr   maposmalenmdicr   r   r_  rZ  r  spdicrP  read_max_nodesr1   ru  r  r  s(                                     r   do_readz,LatexWalker.get_latex_nodes.<locals>.do_read  s   nnQU@S34? % D D)   ( HHHHHH(     0111	 Gcg%AE w&    cgCM0B0B&B(+(? ! B B Bu 1;  "#"3"3"5"5%..78/4S]/B-537X;M ) O O (((!  c(mm~&E&EGAE4S]##    $~~n<=O47M25'#cm:L:L2L25cm2D2D	  .  F  F
 ---!  c(mm~&E&EGAE4 w-''7555/ &GH#'R  2237D2II	   tw+++0 / &GCJJ37SS  2237D2II	   W 999/ &G228&B[2\2\	 
 2237D2II   twAAA-9w"<<<#tw.00 4 "f # T [ [ #)C! !  #66sw6MM   7&??????W..
 0 &G@GGPP  2237D2II	   "%0044SWcgFF /*-'\*A*Ahhy&'o&A&A!%(+ 'B ' '#
	8<8L8L3Q&9 9M 9 95($
 -   O**J7G7N7Nsw7W7WY\Y` -[8<8P8PQTQX8Y8Y-[ -[ -[ ] ] ] t!"#/ +0 #)GHT$Ysw%6 !/ ! !    "  c(mm~&E&E4w)##"nn-=;<?58W@C14cg	 - G G
 ,,,!  c(mm~&E&E4w,&&.2.I.I#&7&'o /J / /+Ydd -   O**J|SW -[8<8P8PQTQX8Y8Y-[ -[ -[ ] ] ]
 t	***!  c(mm~&E&E4w---,0,F,F(+&'o -G - -)WdDD
 -   O**"#;#B#B37#K#KSW G$($<$<SW$E$EG G G    t(((!  c(mm~&E&E4w'!!G	5DDYOO=%/33EC((4SWsw5F78 ) H H  K /0EF C C C;;3::9EE A
 }Ag#'37):Ar"BKKKKKKC {##q((5@2XueTT/:,XueD'H,O'!)!DQ!GJ'B1EHH+/J~~n45O03/77:~1;/7*-'*+%- & 	9 	9 %%%&$..&*+>&?AO!  c(mm~&E&E4tw*$$#')	/**TquAO*\\CC.0EF / / /;;6==e>RSS A
 }Ag2.CCCCCC/ ?3xx1}}:=75%3605% "!EMAEE E~~&745O5:5I/7*-'*+%- & 9 9 %%%&%//&+,?&@AO!  c(mm~&E&E4t ( &E)0055  **15$*??	  s   "& 
A?A?A
AA!Q 
R,AR''R, +W 
XAXX&+Z 
[=A[88[=*^, ,`=A``"d0 0f	>ff	T'z\end{z*Unexpected end of stream, was expecting {}r*  r+  Fr  rg  r
   )r  ro   r   r  r	  r8   rF   r%   r)   r*   r.  r  r#  r   r  rH   r  r  r`  r   r   ru   )r1   r*   ru  r  r  r  r   r   )opening_brace_for_stop_upon_closing_braceorigposr  r   r  r_endnowr0  	expectingr  r   r  rP  s   ` ````             @r   rv  zLatexWalker.get_latex_nodese  s   h   3355M"481" 	&#--<?99(C//<?99(C//<?99(C//<?99,--22+ S9;R '#-->@WX'#
 &1-:T1NN;<BF/"/= =   	 	 	 	 	 	 	 	$ J3m<<<J	 J	 J	 J	 J	 J	 J	 J	 J	 J	\
2	< "78Q//) ! ! !* !.G !0! / G$'(?$?$C		2 G$,-F$Fs$J		3 G$'(B$B3$F	- &EH#VI..	 
 223tv;;2MM A ,  77:::#' H(   ( 33A666$HH HHHH  < h(>?? 7$$+3+? % A A AEES!5666EE; -&'&7&7&9&9OHe"nn^;<?3819s5zz - K KG OOG,,, '157?;;e2	<s%   C 
G 'BF		G  F;;G r	   )NTNN)Fr   )r   N)r   NNNNN)r    r!   r"   r#   r/   r  r  r#  r[  r`  rc  r.  rk  rp  rl  r  r  rv  rC   rD   s   @r   r  r  "  s       P PdF, F, F, F, F, F,R@ @ @"
 
 
"M M M EI7;cS cS cS cSL  6
 
 
L L L L,d? d? d? d?N" " " "JED ED ED EDPg: g: g: g:T" " "J >B26HL&*R< R< R< R< R< R< R< R<r   r  Tc                 H    t          | fi |                    |||          S )z
    Parse the next token in the stream.

    Returns a `LatexToken`. Raises `LatexWalkerEndOfStream` if end of stream reached.

    .. deprecated:: 1.0
       Please use :py:meth:`LatexWalker.get_token()` instead.
    )r*   r%  rN   )r  r[  )r)   r*   r%  rN   r  s        r   r[  r[  	  s<     q((K((22sFX@L 3 N N Nr   c                 D    t          | fi |                    |          S )ap  
    Reads a latex expression, e.g. macro argument. This may be a single char, an escape
    sequence, or a expression placed in braces.

    Returns a tuple `(<LatexNode instance>, pos, len)`. `pos` is the first char of the
    expression, and `len` is its length.

    .. deprecated:: 1.0
       Please use :py:meth:`LatexWalker.get_latex_expression()` instead.
    r*   )r  rk  r)   r*   r  s      r   rk  rk  	  s+     q((K((==#=FFFr   c                 D    t          | fi |                    |          S )z
    Attempts to parse an optional argument. Returns a tuple `(groupnode, pos, len)` if
    success, otherwise returns None.

    .. deprecated:: 1.0
       Please use :py:meth:`LatexWalker.get_latex_maybe_optional_arg()` instead.
    r  )r  rp  r  s      r   rp  rp  	  s+     q((K((EE#ENNNr   r   c                 F    t          | fi |                    ||          S )a  
    Reads a latex expression enclosed in braces {...}. The first token of `s[pos:]` must
    be an opening brace.

    Returns a tuple `(node, pos, len)`. `pos` is the first char of the
    expression (which has to be an opening brace), and `len` is its length,
    including the closing brace.

    .. deprecated:: 1.0
       Please use :py:meth:`LatexWalker.get_latex_braced_group()` instead.
    )r*   ro  )r  rl  )r)   r*   ro  r  s       r   rl  rl  	  s.     q((K((??CT^?___r   c                 F    t          | fi |                    ||          S )aY  
    Reads a latex expression enclosed in a \begin{environment}...\end{environment}. The first
    token in the stream must be the \begin{environment}.

    Returns a tuple (node, pos, len) with node being a :py:class:`LatexEnvironmentNode`.

    .. deprecated:: 1.0
       Please use :py:meth:`LatexWalker.get_latex_environment()` instead.
    )r*   r   )r  r  )r)   r*   r   r  s       r   r  r  	  s9     q((K((>>3O^ ? ` ` `r   c                 H    t          | fi |                    |||          S )a|  
    Parses latex content `s`.

    Returns a tuple `(nodelist, pos, len)` where nodelist is a list of `LatexNode` 's.

    If `stop_upon_closing_brace` is given, then `len` includes the closing brace, but the
    closing brace is not included in any of the nodes in the `nodelist`.

    .. deprecated:: 1.0
       Please use :py:meth:`LatexWalker.get_latex_nodes()` instead.
    )ru  r  r  )r  rv  )r)   r*   ru  r  r  r  s         r   rv  rv  	  s:     q((K((88 7";#= 9   r   c                    d }d}| D ]}||                     t                    r||j        z  }+|                     t                    r%|d|j        |j         ||j                  z  }j|                     t                    r||j         ||j                  z  }|                     t                    r|d|j
        z   |j        z   z  }|                     t                    r5||j        d         t          |j                  z   |j        d         z   z  } |                     t                     rD|d|j        d ||j                  z  }|t          |j                  z  }|d	|j        z  z  }~|                     t$                    r5||j        d         t          |j                  z   |j        d         z   z  }|d
|                                j        z  z  }|S )Nc                 T   | | j         | j        dS d}t          | j         | j                  D ]x\  }}|dk    r||t          |g          z  }!|dk    r||t          |g          z  }=|dk    r|t          |g          z  }Wt	          d                    |                    |S )Nr4   *r'  r   zUnknown argument type: {!r})argspecargnlistrN  nodelist_to_latexr  r8   )r   	argslatexargtargns       r   add_argsz#nodelist_to_latex.<locals>.add_args
  s    x/78;L;T2	h.0ABB 	M 	MJD$s{{#!2D6!:!::I#!2D6!:!::I.v666		 !>!E!Ed!K!KLLLr   r4   r4  r;  r   rK   z\begin{r   z\end{%s}z<[UNKNOWN LATEX NODE: '%s']>)r   r   r   r   rZ   r   r   r   r   r   rr   r   r   r   r  r   r   r   r   r   r    )r   r  latexns       r   r  r  

  s     & E !J !J9<<'' 	QWE<<'' 	E!++q/A/A88AJCWCWCWXXE<<)** 	q//!*1E1E1EFFE<<()) 	S]1#777E<<'' 	Q\!_'8'D'DDq|TUVVE<<,-- 	Eqyyy((1:2F2F2FGGE&qz222E[19--E<<&& 	Q\!_'8'D'DDq|TUVVE11::<<3HIILr   c                 j    | dk    rd|z  S | dk    rd|z  S | dk    rd|z  S | dk    rd|z  S | |z   | z   S )	Nr   z{%s}r'  z[%s]r   z(%s)rr  z<%s>r
   )
brace_char	thestrings     r   put_in_bracesr  P
  sj    c	""c	""c	""c	""	!J..r   * Fc                    
 d}d}g 

 fd} d}n                      t                    rt           j                  }nŉ                      t                    rd j        z   } |             n                      t                    r j        dz   } |             ne                      t                    rd j	        
                                z   }n-                      t                    r@|r j        D ]}t          |||           d S d}
                    d	 j        d
f           nӉ                      t                     r2d j        z  } |             
                    d	 j        d
f           n                      t$                    rD j        d          j        z   dz    j        d         z   }
                    d	 j        d
f           n)t+          d                                 j        z             t+          d|z  |z   |z   dz   |z              
D ]R\  }}}	t1          |t2                    rt+          d|dz   z  |z   |z              7|D ]}t          ||dz   ||	           Sd S )Nr4   c                  8   j         d S j         j        j         j                            d           d S t	          j         j        j         j                  D ];\  } }| dk    rd}n| dk    rd}n| dk    rd}nd}                    ||gd	f           <d S )
N)z<args> z<cannot be displayed>Nr'  z[.]: r   z{.}: r  z<*>:   z<unknown>: F)r   r  r  ru   rN  )r  r  r   iterchildrenr  s      r   r  zdisp_node.<locals>.add_argse
  s    :FZ'1:+>+F JKKKFaj0!*2EFF 		4 		4JD$s{{!TFE 23333		4 		4r   z<None>r4  z (specials)r;  )indentr<   zGroup: r  Fz
\begin{%s}r   z mathrK   zUNKNOWN NODE TYPE: %s z  r~  )r  r<   
skip_group)r   r   reprr   r   rZ   r   r   r   rr   stripr   rn   	disp_noderu   r   r   r   r   r   r   printr   r    r   _basestring)r  r  r<   r  titlerr   r  nnr   skipr  s   `         @r   r  r  _
  s   EGL4 4 4 4 4 4$ 	y	
n	%	% ?QW	
n	%	% ?Q[ 



	
'	(	( ? =0



	
&	'	' ?aioo'''	
n	%	% ? 	e > >"VW=====FT1:u56666	
*	+	+ ? 12


T1:u56666	
m	$	$ ?Q-g5al1oET1:u56666%qzz||'<=>>>	#f*w

&
-g
5666#/ M M4h,, 	#vax.7*X5666 	M 	MBb7tLLLLL	M	M Mr   c                 @      G  fddt           j                  S )Nc                   4     e Zd ZdZ fdZ fdZ xZS )0make_json_encoder.<locals>.LatexNodesJSONEncoderzx
        A :py:class:`json.JSONEncoder` that can encode :py:class:`LatexNode` objects
        (and subclasses).
        c                 >     t          |           j        |i | d S r	   )r.   r/   )r1   r   r   LatexNodesJSONEncoderr2   s      r   r/   z9make_json_encoder.<locals>.LatexNodesJSONEncoder.__init__
  s,    7E'..7HHHHHHr   c                    t          |t                    r[|}d|j        j        i}|j        D ]}|j        |         ||<   |                                        |j        d                     |S t          |t          j
                  r|                                S t          |                               |          S )NnodetypeTr+  )r   r   r2   r    rt   __dict__updater.  r*   r   r   to_json_objectr.   default)r1   r   r  dfldr  r2   latexwalkers        r   r  z8make_json_encoder.<locals>.LatexNodesJSONEncoder.default
  s    #y)) 
 4 9 - -CZ_AcFF888MMNNN#y899 ,))+++ .55==cBBBr   )r    r!   r"   r#   r/   r  rC   )r2   r  r  s   @r   r  r  
  s|        	 	
	I 	I 	I 	I 	I 	I	C 	C 	C 	C 	C 	C 	C 	C 	C 	C 	Cr   r  )jsonJSONEncoder)r  use_line_numbersr  s   ` @r   make_json_encoderr  
  sS    C C C C C C C C 0 C C C< ! r   )TT)r   r	   )r   NNN)r   r  Fr
  )7r#   
__future__r   r   rG  sysloggingr  
pylatexencr4   r   r   version_infomajorr   strr  _str_from_unicoderx   
basestring	getLoggerr    r  r   	Exceptionr   r%   rF   rV   ra   LazyDictdefault_macro_dictobjectrj   r   r   r   r   r   r   r   r   r   r   r  r[  rk  rp  rl  r  rv  r  r  r  r  r
   r   r   <module>r     s  4> >@ 8 7 7 7 7 7 7 7 				 



                  A&&&K## K<<33		8	$	$  	 	 	 	 	y 	 	 	= = = = =, = = =D' ' ' ' '- ' ' '     P" " "J $U^    0D D D D D D D D^n n n n n n n nb    Y   &! ! ! ! !Y ! ! !F         y      8K K K K KY K K K^K$ K$ K$ K$ K$9 K$ K$ K$Z(! (! (! (! (!	 (! (! (!Z) ) ) ) )I ) ) )^; ; ; ; ; ; ; ;&B B B B B6 B B BVU< U< U< U< U<& U< U< U<z+N N N NG G G	O 	O 	O` ` ` ` ` ` ` ` W[/3   HA A AL/ / /<M <M <M <MB !  !  !  !  !  !r   