o
    .di                     @  sJ  d Z ddlmZ ddlmZ ddlmZ ddlmZ ddlm	Z	 ddlm
Z
 ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddl m!Z! ddl m"Z" ddl m#Z# ddl m$Z$ ddl m%Z% ddl m&Z& ddl m'Z' ddl m(Z( ddl m)Z) dd l m*Z* dd!l m+Z+ dd"l m,Z, dd#l m-Z- dd$l m.Z. dd%l m/Z/ dd&l m0Z0 dd'l m1Z1 dd(l m2Z2 dd)l m3Z3 dd*l m4Z4 dd+l m5Z5 dd,l m6Z6 dd-l m7Z7 dd.l m8Z8 dd/l m9Z9 dd0l m:Z: dd1l m;Z; dd2l m<Z< dd3l m=Z= dd4l m>Z> dd5l m?Z? dd6l m@Z@ dd7l mAZA dd8l mBZB dd9l mCZC dd:l mDZD dd;l mEZE dd<l mFZF dd=l mGZG dd>l mHZH dd?l mIZI dd@l mJZJ ddAl mKZK ddBl mLZL e	rddClmMZM G dDdE dEZNddLdMZOedNdOddRdSZPddd[d\ZQddd]d^ZRddd_d`ZSddbdcZTG ddde deeZUe1eUjVe,eUjWe;eUjWe0eUjWe<eUjWe7eUjWe6eUjWe/eUjWe'eUjXe!eUjYeAeUjYiZZe[e!eAfZ\e[e1e4e)e5eHfZ]e[e8e@e%eEfZ^e[eBe+fZ_ddgdhZ`ddkdlZaddndoZbddqdrZcddtduZdddwdxZeddzd{Zfdd}d~ZgdddZh	TddddZi	TddddZjeejkejlejmejnejof ZpG dd deZqdddZrdddZsdddZtdddZuG dd dZvev ZwewjxZxewjyZyewjzZzewj{Z{ewj|Z|ewj}Z}ewj~Z~ewjZewjZewjZewjZewjZedNdOdddZdTS )a)  Liquid template parser.

As of Python Liquid 1.2.0 we are transitioning away from the expression parser defined
here. Instead opting for separate, specialized parsers (and lexers) for each of the
three built-in expression types.

The `ExpressionParser` class will become depreciated as we approach version 2.0 and then
removed. At which time this module will be reserved for parsing templates (not
expressions), possibly with some explicit re-exports of the expression parsers found in
`liquid.expressions`.

Developers of custom tags are encouraged to use or follow the example of:

- `liquid.expressions.parse_boolean_expression`
- `liquid.expressions.parse_filtered_expression`
- `liquid.expressions.parse_loop_expression`

And make use of `liquid.expressions.common` and `liquid.expressions.TokenStream`.
    )annotations)IntEnum)auto)	lru_cache)TYPE_CHECKING)	Container)List)
NamedTuple)Optional)Tuple)Union)ast
expression)Error)LiquidSyntaxError)IdentifierPathElement)tokenize_boolean_expression)tokenize_filtered_expression)tokenize_loop_expression)to_int)TokenStream)	TOKEN_AND)TOKEN_ASSIGN)TOKEN_BLANK)TOKEN_COLON)
TOKEN_COLS)TOKEN_COMMA)TOKEN_CONTAINS)TOKEN_CONTINUE)	TOKEN_DOT)TOKEN_EMPTY)	TOKEN_EOF)TOKEN_EQ)TOKEN_FALSE)TOKEN_FLOAT)TOKEN_GE)TOKEN_GT)TOKEN_IDENTIFIER)TOKEN_ILLEGAL)TOKEN_IN)TOKEN_INTEGER)TOKEN_LBRACKET)TOKEN_LE)TOKEN_LG)TOKEN_LIMIT)TOKEN_LITERAL)TOKEN_LPAREN)TOKEN_LT)TOKEN_NE)TOKEN_NEGATIVE)	TOKEN_NIL)
TOKEN_NULL)TOKEN_OFFSET)TOKEN_OR)
TOKEN_PIPE)TOKEN_RANGE)TOKEN_RBRACKET)TOKEN_REVERSED)TOKEN_RPAREN)TOKEN_STATEMENT)TOKEN_STRING)	TOKEN_TAG)
TOKEN_TRUE)Token)reverse_operators)Environmentc                   @  s<   e Zd ZdZdZdddZdddZdddZdddZdS )ParserzFA Liquid template parser. Create a parse tree from a stream of tokens.)tagsillegalliteral	statementenvrJ   rD   c                 C  s6   |j | _ || _| j t | _| j t | _| j t | _d S N)rF   rJ   r)   rG   r0   rH   r>   rI   )selfrJ    rM   D/var/www/Matress/matenv/lib/python3.10/site-packages/liquid/parse.py__init__b   s
   zParser.__init__streamr   returnast.ParseTreec              
   C  s   t  }|j}|jjtkr>z
|| | W n ty3 } z| j	j
||jjd W Y d}~nd}~ww |  |jjtks|S )z-Parse the given stream of tokens into a tree.linenumN)r   	ParseTree
statementscurrenttyper"   appendparse_statementr   rJ   errorrT   
next_token)rL   rP   rootrV   errrM   rM   rN   parsej   s    zParser.parseast.Nodec                 C  s   |j jtkr| j|}|S |j jtkr;| j|j j| j	}||}t
|tjr9td| j d| jd|S | j|}|S )z%Parse a node from a stream of tokens.zunexpected tag ''rS   )rW   rX   r>   rI   get_noder@   rF   getvaluerG   
isinstancer   IllegalNoder   tokenrT   rH   )rL   rP   nodetagrM   rM   rN   rZ   y   s   
zParser.parse_statementendContainer[str]ast.BlockNodec                 C  s   t |j}|j}|jjtkr>|jjtkr|jj|v r	 |S | |}|	| |j
s1t|ddr4d|_|  |jjtks|S )zParse multiple nodes from a stream of tokens.

        Stop parsing nodes when we find a token in `end` or we reach the end of the
        stream.
        forced_outputFT)r   	BlockNoderW   rV   rX   r"   r@   rd   rZ   rY   force_outputgetattrrm   r\   )rL   rP   rj   blockrV   stmtrM   rM   rN   parse_block   s   


zParser.parse_blockN)rJ   rD   )rP   r   rQ   rR   )rP   r   rQ   r`   )rP   r   rj   rk   rQ   rl   )	__name__
__module____qualname____doc__	__slots__rO   r_   rZ   rs   rM   rM   rM   rN   rE   ]   s    


rE   rP   r   rj   rk   rQ   Nonec                 C  sD   | j jtkr | j jtkr| j j|v rdS |   | j jtksdS dS )zAdvance the stream pointer past the next end tag.

    This is used to discard blocks after a syntax error is found, in the hope
    that we can continue to parse more of the stream after the offending block.
    N)rW   rX   r"   r@   rd   r\   )rP   rj   rM   rM   rN   	eat_block   s
   rz      )maxsizerJ   rD   c                 C  s   t | S )z3Return a template parser for the given environment.)rE   )rJ   rM   rM   rN   
get_parser   s   r}   NtokrB   typstrrd   Optional[str]c              	   C  s   | j |ks|d urA| j|krCt| j | j }t||}|d ur1d| d| d| d| j d	}n	d| d| d}t|| jdd S d S )N	expected z with value 'z	', found ra   z
expected 'z
', found 'rS   )rX   rd   rC   rc   r   rT   )r~   r   rd   _typ_expected_typmsgrM   rM   rN   _expect   s   r   c                 C     t | j|| dS )z}Check the current token in the stream matches the given type and value.

    Raises a `LiquidSyntaxError` if they don't.
    N)r   rW   rP   r   rd   rM   rM   rN   expect      r   c                 C  r   )zzCheck the next token in the stream matches the given type and value.

    Raises a `LiquidSyntaxError` if they don't.
    N)r   peekr   rM   rM   rN   expect_peek   r   r   boolc                 C  s   | j dS )z9Return `True` if the current token looks like an end tag.rj   )rd   
startswith)r~   rM   rM   rN   
is_end_tag   s   r   c                   @  s.   e Zd ZdZdZdZdZe Ze Z	e Z
dS )
PrecedencezOperator precedence.   1   2   N)rt   ru   rv   rw   LOWESTLOGICALRIGHTLOGICALr   
RELATIONAL
MEMBERSHIPPREFIXrM   rM   rM   rN   r      s    
r   expression.Booleanc                 C  s   | j jtkr	tjS tjS )z=Read a boolean literal (true or false) from the token stream.)rW   rX   rA   r   TRUEFALSErP   rM   rM   rN   parse_boolean  s   r   _expression.Nilc                 C     t jS )z+Read a 'nil' keyword from the token stream.)r   NILr   rM   rM   rN   	parse_nil     r   expression.Emptyc                 C  r   )z-Read a 'empty' keyword from the token stream.)r   EMPTYr   rM   rM   rN   parse_empty  r   r   expression.Blankc                 C  r   )z-Read a 'blank' keyword from the token stream.)r   BLANKr   rM   rM   rN   parse_blank  r   r   expression.StringLiteralc                 C  s   t j| jjdS )z$Read a string from the token stream.rd   )r   StringLiteralrW   rd   r   rM   rM   rN   parse_string_literal     r   expression.IntegerLiteralc                 C     t jt| jjdS )z&Read an integer from the token stream.r   )r   IntegerLiteralr   rW   rd   r   rM   rM   rN   parse_integer_literal#     r   expression.FloatLiteralc                 C  r   )z#Read a float from the token stream.r   )r   FloatLiteralfloatrW   rd   r   rM   rM   rN   parse_float_literal(  r   r   expression.RangeLiteralc                 C  s   t | t |   t| }t| t |   |   t| }t| t t|tj	tj
tjfs0J t|tj	tj
tjfs=J t||}|   |S )z+Read a range literal from the token stream.)r   r1   r\   parse_range_argumentr   r:   r=   re   r   
Identifierr   r   RangeLiteral)rP   startstopexprrM   rM   rN   parse_range_literal-  s&   


r   expression.Identifierc                 C  sp  g }| j jtv r| j jtkr|t| j j n| j jtkr*|tt| j j ny| j jt	kr| 
  | j jtkrD|t| j j nE| j jtkr`t| t | 
  |tt| j j  n)| j jtkrr|tt| j j n| j jtkr|t|  n	td| j j t| t | 
  n| j jtkrn	td| j j | 
  | j jtv s| | j  t|S )zRead an identifier from the token stream.

    <ident>.<ident>
    <ident>["<ident>"]
    <ident>["<ident>"].<ident>
    <ident>[<ident --> int/str>]
    <ident>[<ident>.<ident --> int/str>]
    <ident>[<int>]
    <ident>[<int>].<ident>
    zinvalid identifier, found )rW   rX   IDENTIFIER_TOKENSr(   rY   r   rd   r+   r   r,   r\   r?   r4   r   parse_identifierr   r;   r    pushr   r   )rP   pathrM   rM   rN   r   I  s<   


'
r   rT   Optional[int]expression.Expressionc                 C  sn   | j jtkrt| }|S | j jtkrt| }|S t| j j| j j}dt dt d| }t||p4| j j	d)zParse an expression from a stream of tokens.

    If the stream is not at a string or identifier expression, raise a syntax error.
    r   z or z, found rS   )
rW   rX   r(   r   r?   r   rC   rc   r   rT   )rP   rT   r   r   r   rM   rM   rN   parse_string_or_identifier  s   r   c                 C  sD   t | t | j}t| }t|jdkr td| d|p|jd|S )zParse an identifier from a stream of tokens.

    If the stream is not at an identifier or the identifier is chained, raise a
    syntax error
    r   zinvalid identifier 'ra   rS   )r   r(   rW   r   lenr   r   rT   )rP   rT   r~   identrM   rM   rN   parse_unchained_identifier  s   
	r   c                   @  s"   e Zd ZU dZded< ded< dS )RangeOptionzGA token and value representing a keyword argument in a loop expression.rB   r~   RangeArgargN)rt   ru   rv   rw   __annotations__rM   rM   rM   rN   r     s   
 r   r   c                 C  sp   | j jtkrt| }|S | j jtkrt| }|S | j jtkr$t| }|S | j jtkr/t	j
}|S td| j j )zParse a loop argument value from a stream of tokens.

    If the stream is not at a valid token for a loop argument value, raise a syntax
    error.
    z7invalid range expression, expected an integer, found a )rW   rX   r(   r   r+   r   r%   r   r   r   CONTINUEr   )rP   r   rM   rM   rN   r     s"   
r   c                 C  sv   | j }| j jtttfv r)t| t |   |   t| }|   t	||d}|S t
| t |   t	|tjd}|S )zParse a loop keyword argument from a stream of tokens.

    If the stream is not at a valid loop keyword argument, raise a syntax error.
    )r~   r   )rW   rX   r/   r7   r   r   r   r\   r   r   r   r<   r   r   )rP   r~   r   optrM   rM   rN   parse_range_option  s   

r   expression.LoopExpressionc                 C  s   t tt| S )z,Parse the given string as a loop expression.)parse_loop_expressionr   r   r   rM   rM   rN   parse_loop_expression_value  r   r   c                 C  s   t | t t| t | jj}|   |   | jjtkr%t| }|   n| jjt	kr4t
| }|   ntdtj||d}| jjtv ryt| }|jjtkrSd|_n |jjtkr^|j|_n|jjtkri|j|_n
|jjtkrs|j|_| jjtv sE|S )zParse a liquid loop expression, as one might find in a `for` tag.

    If any of the optional parameters are duplicated, the last (right most) is
    used.
    zinvalid loop expression)nameiterableT)r   r(   r   r*   rW   rd   r\   rX   r   r1   r   r   r   LoopExpressionLOOP_TOKENSr   r~   r<   reversedr/   r   limitr7   offsetr   cols)rP   r   r   r   r   rM   rM   rN   r     s2   





r   c                   @  s   e Zd ZU dZeeefZded< d/ddZ	d0ddZ
d0ddZd1ddZd2ddZd3ddZd4ddZejfd5ddZd6d#d$Zd7d%d&Zd8d'd(Zd9d)d*Zd:d,d-Zd.S );ExpressionParserzThe standard expression parser.

    Custom, non "standard" tags can subclass `ExpressionParser` to change expression
    parsing behavior. Such as adding a logical `NOT` operator.
    zTuple[str, ...]END_EXPRESSIONrQ   ry   c                 C  s   t  | _t | _tttttt	t
t	ttttt| jtttttttttti| _t| jt| jt| jt | jt!| jt"| jt#| jt$| jt%| jt&| ji
| _'d S rK   )(PRECEDENCEScopyprecedencesRIGHT_ASSOCIATIVEright_associativer$   r   rA   r5   r   r6   r!   r   r   r   r4   parse_prefix_expressionr?   r   r+   r   r%   r   r(   r   r1   r   prefix_funcsr#   parse_infix_expressionr8   r   r2   r'   r3   r.   r-   r&   r   infix_funcs)rL   rM   rM   rN   rO   %  s4   


zExpressionParser.__init__rP   r   r   c              
   C  sD   z
| j |jj }W |S  ty! } ztd|jj d|d}~ww )z6Return the precedence of the next token in the stream.zunknown operator 'ra   N)r   r   rX   KeyErrorr   rd   )rL   rP   
precedencer^   rM   rM   rN   peek_precedenceE  s   z ExpressionParser.peek_precedencec                 C  s6   | j |jjtj}|jj| jv rt|d }t|S )z9Return the precedence of the current token in the stream.r   )r   rc   rW   rX   r   r   r   )rL   rP   r   rM   rM   rN   current_precedenceM  s   z#ExpressionParser.current_precedenceList[expression.Filter]c                 C  s0   g }|j jtkr|| | |j jtks|S )zCKeep reading filters from the token stream until end of expression.)rW   rX   r"   rY   parse_filter)rL   rP   filtersrM   rM   rN   parse_filtersT  s
   zExpressionParser.parse_filtersexpression.Filterc                 C  s   t |t |  t |t |jj}|  g }i }|jjtkrb|  |jjtvrb|j	jtkrF|jj}|  |  | 
|}|||< n|| 
| |  |jjtkr\|  |jjtvs*t|||S )zCRead a single filter with optional arguments from the token stream.)r   r9   r\   r(   rW   rd   rX   r   FILTER_END_TOKENSr   parse_expressionrY   r   r   Filter)rL   rP   filter_nameargskwargs
param_nameparam_valuerM   rM   rN   r   [  s,   



zExpressionParser.parse_filterexpression.PrefixExpressionc                 C  s*   |j }|  tj|j| j|tjddS )z2Parse a prefix expression from a stream of tokens.)r   )right)rW   r\   r   PrefixExpressionrd   r   r   r   )rL   rP   r~   rM   rM   rN   r     s   z(ExpressionParser.parse_prefix_expressionleftr   expression.InfixExpressionc                 C  s2   |j }| |}|  tj||j| ||dS )z2Parse an infix expression from a stream of tokens.)r   operatorr   )rW   r   r\   r   InfixExpressionrd   r   )rL   rP   r   r~   r   rM   rM   rN   r     s   

z'ExpressionParser.parse_infix_expressionr   c           	      C  s   | j }| j}| j|jj}|du r$t|jj|jj}td| d||}|j	j|vrX|| 
|k rX||j	j}|du rB|S |  |||}|j	j|vrX|| 
|k s5|S )z&Parse a literal or logical expression.Nzunknown prefix operator 'ra   )r   r   r   rc   rW   rX   rC   rd   r   r   r   r\   )	rL   rP   r   end_expressionr   prefixr   r   infixrM   rM   rN   r     s"   
	z!ExpressionParser.parse_expressionrd   r   expression.FilteredExpressionc                 C     |  tt|S )z/Parse the given value as a filtered expression.)parse_filtered_expressionr   r   rL   rd   rM   rM   rN   parse_filtered_expression_value     
z0ExpressionParser.parse_filtered_expression_valuec                 C  s(   |  |}|  | |}t||S )zParse a statement (output) expression with optional filters.

        A statement expression is assumed to start with exactly one identifier, followed
        by zero or more filters.
        )r   r\   r   r   FilteredExpression)rL   rP   r   r   rM   rM   rN   r    s   

z*ExpressionParser.parse_filtered_expressionc                 C  r  )z/Parse the given string as a boolean expression.)parse_boolean_expressionr   r   r  rM   rM   rN   parse_boolean_expression_value  r
  z/ExpressionParser.parse_boolean_expression_valuec                 C  s$   |j jtkr	tjS tj| |dS )aj  Parse a liquid expression that evaluates to a Boolean value.

        This is primarily used by control flow tags like `if`, `unless` and `case`/
        `when`.

        Logical operators (`and` and `or`) are right associative. They are evaluated
        from right to left. The use of parentheses to control operator precedence is
        not allowed.
        r   )rW   rX   r"   r   r   BooleanExpressionr   )rL   rP   rM   rM   rN   r    s   
z)ExpressionParser.parse_boolean_expressionexpression.AssignmentExpressionc                 C  sH   t |t t|t t|}|  |  | |}tjt	||dS )zParse a liquid assignment expression, as one might find in an `assign` tag.

        This is essentially the same as a parse_filtered_expression, but with
        an additional name to bind the expression result to.
        )r   r   )
r   r(   r   r   r   r\   r  r   AssignmentExpressionr   )rL   rP   r   r   rM   rM   rN   parse_assignment_expression  s   


z,ExpressionParser.parse_assignment_expressionN)rQ   ry   )rP   r   rQ   r   )rP   r   rQ   r   )rP   r   rQ   r   )rP   r   rQ   r   )rP   r   r   r   rQ   r   )rP   r   r   r   rQ   r   )rd   r   rQ   r  )rP   r   rQ   r  )rd   r   rQ   r   )rP   r   rQ   r   )rP   r   rQ   r  )rt   ru   rv   rw   r9   r   r"   r   r   rO   r   r   r   r   r   r   r   r   r   r	  r  r  r  r  rM   rM   rM   rN   r     s(   
 

 



'




r   c                 C  s   t S )z6Return an expression parser for the given environment.)STANDARD_EXPRESSION_PARSERr   rM   rM   rN   get_expression_parser  s   r  )rP   r   rj   rk   rQ   ry   )rJ   rD   rQ   rE   rK   )r~   rB   r   r   rd   r   rQ   ry   )rP   r   r   r   rd   r   rQ   ry   )r~   rB   rQ   r   )rP   r   rQ   r   )r   r   rQ   r   )r   r   rQ   r   )r   r   rQ   r   )rP   r   rQ   r   )rP   r   rQ   r   )rP   r   rQ   r   )rP   r   rQ   r   )rP   r   rQ   r   )rP   r   rT   r   rQ   r   )rP   r   rT   r   rQ   r   )rP   r   rQ   r   )rP   r   rQ   r   )rd   r   rQ   r   )rP   r   rQ   r   )r   rD   rQ   r   )rw   
__future__r   enumr   r   	functoolsr   typingr   r   r   r	   r
   r   r   liquidr   r   liquid.exceptionsr   r   liquid.expressionr   
liquid.lexr   r   r   liquid.limitsr   liquid.streamr   liquid.tokenr   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   rz   r}   r   r   r   r   r   r   r   r   r   r   	frozensetr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   ContinueNilr   r   r   r   r   r   r   r  r   r   r   r   r   r   r   r  r	  r  r  r  r  rM   rM   rM   rN   <module>   s$   
G	
	








:	



+ f