a Ã`L‹ã@s–dZddlmZddlmZddlmZddlmZddlm Z ddlm Z e gd¢ƒZ e gd ¢ƒZ ejejejejejejd œZGd d „d eƒZd S)z8Parse tokens from the lexer into nodes for the compiler.é)Únodes)Úimap)ÚTemplateAssertionError)ÚTemplateSyntaxError)Údescribe_token©Údescribe_token_expr) ÚforÚifÚblockZextendsÚprintZmacroZincludeÚfromÚimportÚsetÚwithÚ autoescape)ÚeqÚneÚltZlteqÚgtZgteq)ÚaddÚsubÚmulÚdivÚfloordivÚmodc@s¾eZdZdZdidd„Zdefdd„Zdd„Zdjd d „Zdkd d „Z dld d„Z dmdd„Z dd„Z dndd„Z dd„Zdd„Zdd„Zdd„Zdd„Zd d!„Zd"d#„Zd$d%„Zd&d'„Zd(d)„Zd*d+„Zd,d-„Zd.d/„Zd0d1„Zd2d3„Zd4d5„Zdod7d8„Zdpd9d:„Zd;d<„Z d=d>„Z!d?d@„Z"dAdB„Z#dCdD„Z$dEdF„Z%dGdH„Z&dIdJ„Z'dKdL„Z(dqdMdN„Z)dOdP„Z*drdQdR„Z+dSdT„Z,dUdV„Z-dWdX„Z.dYdZ„Z/d[d\„Z0d]d^„Z1d_d`„Z2dsdadb„Z3dcdd„Z4dtdedf„Z5dgdh„Z6dS)uÚParserz…This is the central parsing class Jinja uses. It's passed to extensions and can be used to parse expressions or statements. NcCsl||_| ||||¡|_||_||_d|_i|_| ¡D]}|jD]}|j |j|<qBq8d|_ g|_ g|_ dS)NFé) Ú environmentÚ _tokenizeÚstreamÚnameÚfilenameÚclosedÚ extensionsZiter_extensionsÚtagsÚparseÚ_last_identifierÚ _tag_stackÚ_end_token_stack)ÚselfrÚsourcer!r"ÚstateÚ extensionÚtag©r/ú1/usr/lib/python3.9/site-packages/jinja2/parser.pyÚ__init__+s  zParser.__init__cCs(|dur|jjj}||||j|jƒ‚dS)z Convenience method that raises `exc` with the message, passed line number or last line number as well as the current name and filename. N)r ÚcurrentÚlinenor!r")r*Úmsgr3Úexcr/r/r0Úfail9s z Parser.failcCs¼g}|D]}| tt|ƒ¡q|rGsz&Parser._fail_ut_eof..éÿÿÿÿzUnexpected end of template.zEncountered unknown tag '%s'.z_You probably made a nesting mistake. Jinja is expecting this tag, but currently looking for %s.z-Jinja was looking for the following tags: %s.z4The innermost block that needs to be closed is '%s'.ú )ÚextendrrÚjoinÚappendr(r6)r*r!Zend_token_stackr3ZexpectedZexprsZcurrently_lookingÚmessager/r/r0Ú _fail_ut_eofBs< ÿ  þÿÿÿÿÿzParser._fail_ut_eofcCs| ||j|¡S)z¤Called if the parser encounters an unknown tag. Tries to fail with a human readable error message that could help to identify the problem. )r@r))r*r!r3r/r/r0Úfail_unknown_taggszParser.fail_unknown_tagcCs*t|jƒ}|dur| |¡| d||¡S)z9Like fail_unknown_tag but for end of template situations.N)Úlistr)r>r@)r*Ú end_tokensr3Ústackr/r/r0Úfail_eofns  zParser.fail_eofcCs,|jjjdvrdS|dur(|jj |¡SdS)zAre we at the end of a tuple?)Ú variable_endÚ block_endÚrparenTNF)r r2ÚtypeÚtest_any)r*Úextra_end_rulesr/r/r0Ú is_tuple_endus zParser.is_tuple_endcCs6|jd7_t tj¡}tjj|d|j|d|S)zDReturn a new free identifier as :class:`~jinja2.nodes.InternalName`.rzfi%d©r3)r'ÚobjectÚ__new__rZ InternalNameZNoder1)r*r3Úrvr/r/r0Úfree_identifier}s zParser.free_identifiercCs|jj}|jdkr | d|j¡|j |j¡d}zÔ|jtvrdt |d|jjjƒƒW|rb|j  ¡S|jdkr†|  ¡W|r„|j  ¡S|jdkr¨|  ¡W|r¦|j  ¡S|j  |j¡}|durÖ||ƒW|rÔ|j  ¡S|j  ¡d}| |j|j¡W|r|j  ¡n|r|j  ¡0dS) zParse a single statement.r!ztag name expectedTZparse_ÚcallÚfilterNF)r r2rIr6r3r(r>ÚvalueÚ_statement_keywordsÚgetattrÚpopÚparse_call_blockÚparse_filter_blockr$ÚgetrA)r*ÚtokenZpop_tagÚextr/r/r0Úparse_statement„sD   ï  ñ   ó  ö  ÿzParser.parse_statementFcCsL|j d¡|j d¡| |¡}|jjjdkr:| |¡|rHt|jƒ|S)aRParse multiple statements into a list until one of the end tokens is reached. This is used to parse the body of statements as it also parses template data if appropriate. The parser checks first if the current token is a colon and skips it if there is one. Then it checks for the block end and parses until if one of the `end_tokens` is reached. Per default the active token in the stream at the end of the call is the matched end token. If this is not wanted `drop_needle` can be set to `True` and the end token is removed. ÚcolonrGÚeof)r Úskip_ifÚexpectÚsubparser2rIrEÚnext)r*rCÚ drop_needleÚresultr/r/r0Úparse_statements s     zParser.parse_statementscCsft|jƒj}|jdd}|j d¡r<| ¡}tj|||dS| d¡}|j ddd}tj ||||dS)zParse an assign statement.T)Úwith_namespaceÚassignrMN)z name:endset©rd) rcr r3Úparse_assign_targetr`Ú parse_tuplerZAssignÚ parse_filterrfZ AssignBlock)r*r3Útargetr8Z filter_nodeÚbodyr/r/r0Ú parse_set»s    zParser.parse_setc Csž|j d¡j}|jdd}|j d¡|jddd}d}|j d ¡rL| ¡}|j d ¡}| d ¡}t|jƒj d krxg}n|jd dd}t j |||||||dS)zParse a for loop.zname:for)úname:in)rKrpF)úname:recursive)Ú with_condexprrKNúname:ifrq)ú name:endforú name:elseZendfor)rtTrirM) r rar3rjrkr`Úparse_expressionrfrcrTrZFor)r*r3rmÚiterÚtestÚ recursivernÚelse_r/r/r0Ú parse_forÆs  ÿ   zParser.parse_forcCs˜tj|j d¡jd}}|jdd|_| d¡|_g|_ g|_ t |jƒ}| d¡rvtj|jj jd}|j   |¡qq”| d¡r”|jdd d |_ q”q|S) zParse an if construct.rsrMF©rr)ú name:elifruú name:endifr}ru)r~Tri)rZIfr rar3rkrxrfrnZelif_rzrcr2r>)r*Únoderer[r/r/r0Úparse_ifÙs     zParser.parse_ifcCs’tjt|jƒjd}g}g}|jjjdkrr|r:|j d¡| ¡}|  d¡|  |¡|j d¡|  |  ¡¡q||_ ||_ |jddd|_|S) NrMrGÚcommaÚparamrh)z name:endwithTri)rZWithrcr r3r2rIrarjÚset_ctxr>rvÚtargetsÚvaluesrfrn)r*rr„r…rmr/r/r0Ú parse_withës    zParser.parse_withcCsDtjt|jƒjd}t d| ¡¡g|_|jddd|_ t  |g¡S)NrMr)zname:endautoescapeTri) rZScopedEvalContextModifierrcr r3ÚKeywordrvÚoptionsrfrnZScope©r*rr/r/r0Úparse_autoescapeüszParser.parse_autoescapecCsptjt|jƒjd}|j d¡j|_|j d¡|_ |jj j dkrJ|  d¡|j ddd|_|j d |j¡|S) NrMr!z name:scopedrzpBlock names in Jinja have to be valid Python identifiers and may not contain hyphens, use an underscore instead.)z name:endblockTrizname:)rZBlockrcr r3rarTr!r`Zscopedr2rIr6rfrnr‰r/r/r0Ú parse_blocksÿzParser.parse_blockcCs"tjt|jƒjd}| ¡|_|S)NrM)rZExtendsrcr r3rvÚtemplater‰r/r/r0Ú parse_extendss zParser.parse_extendscCsH|jj dd¡r>|j ¡ d¡r>t|jƒjdk|_|j ¡n||_|S)Nz name:withz name:withoutú name:contextr) r r2rJÚlookrxrcrTÚ with_contextÚskip)r*rÚdefaultr/r/r0Úparse_import_contextsÿþ zParser.parse_import_contextcCsbtjt|jƒjd}| ¡|_|jj d¡rP|j  ¡ d¡rPd|_ |j  d¡nd|_ |  |d¡S)NrMz name:ignorez name:missingTéF) rZIncludercr r3rvrŒr2rxrZignore_missingr‘r“r‰r/r/r0Ú parse_include$s ÿzParser.parse_includecCsFtjt|jƒjd}| ¡|_|j d¡|jddj |_ |  |d¡S)NrMúname:asT©Ú name_onlyF) rZImportrcr r3rvrŒrarjr!rmr“r‰r/r/r0Ú parse_import0s   zParser.parse_importcstjtˆjƒjd‰ˆ ¡ˆ_ˆj d¡gˆ_‡‡fdd„}ˆjrPˆj d¡ˆjj j dkrä|ƒrfqòˆj dd}|j   d ¡rˆjd |jtd ˆj d ¡r¾ˆj dd}ˆj |j |j f¡nˆj |j ¡|ƒsòˆjj j dkrðqòq>ˆj d¡q>tˆd ƒsdˆ_ˆS)NrMz name:importcsBˆjjjdvr>ˆj ¡ d¡r>tˆjƒjdkˆ_ˆj ¡dSdS)N)rZwithoutrŽrTF)r r2rTrrxrcrr‘r/©rr*r/r0Ú parse_context=sý z(Parser.parse_from..parse_contextrr!Tr—Ú_z4names starting with an underline can not be imported)r5r–rF)rZ FromImportrcr r3rvrŒraÚnamesr2rIrjr!Ú startswithr6rr`r>Úhasattrr)r*r›rmÚaliasr/ršr0Ú parse_from7s6      ý   zParser.parse_fromcCsšg|_}g|_}|j d¡|jjjdkrŠ|r>|j d¡|jdd}| d¡|j d¡rp|  |  ¡¡n|r~|  d¡|  |¡q |j d¡dS) NÚlparenrHrTr—r‚rhz-non-default argument follows default argument) ÚargsÚdefaultsr rar2rIrjrƒr`r>rvr6)r*rr£r¤Úargr/r/r0Úparse_signatureas         zParser.parse_signaturecCsttjt|jƒjd}|jjjdkr.| |¡n g|_g|_ |  ¡|_ t |j tj ƒs`| d|j¡|jddd|_|S)NrMr¢z expected call)z name:endcallTri)rZ CallBlockrcr r3r2rIr¦r£r¤rvrRÚ isinstanceÚCallr6rfrnr‰r/r/r0rXqs  zParser.parse_call_blockcCs8tjt|jƒjd}|jddd|_|jddd|_|S)NrMT)Ú start_inline)zname:endfilterri) rZ FilterBlockrcr r3rlrSrfrnr‰r/r/r0rYszParser.parse_filter_blockcCsBtjt|jƒjd}|jddj|_| |¡|jddd|_ |S)NrMTr—)z name:endmacrori) rZMacrorcr r3rjr!r¦rfrnr‰r/r/r0Ú parse_macro…s  zParser.parse_macrocCsPtjt|jƒjd}g|_|jjjdkrL|jr:|j d¡|j |  ¡¡q|S)NrMrGr) rÚOutputrcr r3r2rIrar>rvr‰r/r/r0Ú parse_printŒs zParser.parse_printTcCsÀ|rN|j ¡jdkrN|j d¡}t|jƒ|j d¡}tj|j|j|jd}nL|rt|j d¡}tj |jd|jd}n&|rˆ|j d|d}n|  ¡}|  d¡|  ¡s¼| d|jj ¡|j¡|S)aParse an assignment target. As Jinja allows assignments to tuples, this function can parse all allowed assignment targets. Per default assignments to tuples are parsed, that can be disable however by setting `with_tuple` to `False`. If only assignments to names are wanted `name_only` can be set to `True`. The `extra_end_rules` parameter is forwarded to the tuple parsing function. If `with_namespace` is enabled, a namespace assignment may be parsed. Údotr!rMÚstoreT)Ú simplifiedrKzcan't assign to %r)r rrIrarcrZNSRefrTr3ÚNamerkÚ parse_primaryrƒZ can_assignr6Ú __class__Ú__name__Úlower)r*Z with_tupler˜rKrgr[Úattrrmr/r/r0rj•s&    ÿ ÿzParser.parse_assign_targetcCs|r | ¡S| ¡S)zºParse an expression. Per default all expressions are parsed, if the optional `with_condexpr` parameter is set to `False` conditional expressions are not parsed. )Úparse_condexprÚparse_or)r*rrr/r/r0rvºszParser.parse_expressioncCsb|jjj}| ¡}|j d¡r^| ¡}|j d¡r<| ¡}nd}tj||||d}|jjj}q|S)NrsrurM)r r2r3r·r`r¶rZCondExpr)r*r3Zexpr1Zexpr2Zexpr3r/r/r0r¶Ãs     zParser.parse_condexprcCsF|jjj}| ¡}|j d¡rB| ¡}tj|||d}|jjj}q|S)Núname:orrM)r r2r3Ú parse_andr`rZOr©r*r3ÚleftÚrightr/r/r0r·Ðs   zParser.parse_orcCsF|jjj}| ¡}|j d¡rB| ¡}tj|||d}|jjj}q|S)Núname:andrM)r r2r3Ú parse_notr`rZAndrºr/r/r0r¹Ùs   zParser.parse_andcCs4|jj d¡r,t|jƒj}tj| ¡|dS| ¡S)Núname:notrM) r r2rxrcr3rÚNotr¾Ú parse_compare)r*r3r/r/r0r¾âs zParser.parse_notcCsÖ|jjj}| ¡}g}|jjj}|tvrJt|jƒ| t  || ¡¡¡nh|j  d¡rn| t  d| ¡¡¡nD|jj  d¡r¾|j  ¡  d¡r¾|j  d¡| t  d| ¡¡¡nq¾|jjj}q|sÆ|Stj|||dS)NrpÚinr¿r”ZnotinrM)r r2r3Ú parse_math1rIÚ_compare_operatorsrcr>rZOperandr`rxrr‘ZCompare)r*r3r8ÚopsÚ token_typer/r/r0rÁès&    ÿ  zParser.parse_comparecCs^|jjj}| ¡}|jjjdvrZt|jjj}t|jƒ| ¡}||||d}|jjj}q|S)N)rrrM)r r2r3Ú parse_concatrIÚ _math_nodesrc©r*r3r»Úclsr¼r/r/r0rÃÿs   zParser.parse_math1cCs^|jjj}| ¡g}|jjjdkrÚlenrZConcat)r*r3r£r/r/r0rÇ s    zParser.parse_concatcCs^|jjj}| ¡}|jjjdvrZt|jjj}t|jƒ| ¡}||||d}|jjj}q|S)N)rrrrrM)r r2r3Ú parse_powrIrÈrcrÉr/r/r0rÌs   zParser.parse_math2cCsR|jjj}| ¡}|jjjdkrNt|jƒ| ¡}tj|||d}|jjj}q|S)NÚpowrM)r r2r3Ú parse_unaryrIrcrZPowrºr/r/r0rÎs   zParser.parse_powcCsˆ|jjj}|jjj}|dkrr=rkraÚ parse_listÚ parse_dictr6r)r*r[rÚbufr3r/r/r0r±9s:                zParser.parse_primaryc sºˆjjj}|rˆj}n|r"ˆj}n ‡fdd„}g}d}|rFˆj d¡ˆ |¡rRq€| |ƒ¡ˆjjjdkr€d}nq€ˆjjj}q6|sª|r|dS|sªˆ  dt ˆjjƒ¡t j |d|d S) a©Works like `parse_expression` but if multiple expressions are delimited by a comma a :class:`~jinja2.nodes.Tuple` node is created. This method could also return a regular expression instead of a tuple if no commas where found. The default parsing mode is a full tuple. If `simplified` is `True` only names and literals are parsed. The `no_condexpr` parameter is forwarded to :meth:`parse_expression`. Because tuples do not require delimiters and may end in a bogus comma an extra hint is needed that marks the end of a tuple. For example for loops support tuples between `for` and `in`. In that case the `extra_end_rules` is set to ``['name:in']``. `explicit_parentheses` is true if the parsing was triggered by an expression in parentheses. This is used to figure out if an empty tuple is a valid expression or not. cs ˆjddS)NFr|)rvr/©r*r/r0r&zsz!Parser.parse_tuple..parseFrTrz Expected an expression, got '%s'r×rM) r r2r3r±rvrarLr>rIr6rrÚTuple) r*r¯rrrKrÜr3r&r£Zis_tupler/rãr0rkZs6       ÿÿzParser.parse_tuplecCsj|j d¡}g}|jjjdkrN|r.|j d¡|jjjdkr>qN| | ¡¡q|j d¡tj||jdS)NrÝÚrbracketrrM) r rar2rIr>rvrÚListr3)r*r[Úitemsr/r/r0rà›s   zParser.parse_listcCs|j d¡}g}|jjjdkrt|r.|j d¡|jjjdkr>qt| ¡}|j d¡| ¡}| tj|||jd¡q|j d¡tj ||jdS)NrÞÚrbracerr^rM) r rar2rIrvr>rZPairr3ÚDict)r*r[rçÚkeyrTr/r/r0rá§s    zParser.parse_dictcCsB|jjj}|dks|dkr&| |¡}q|dkr>| |¡}qq>q|S)Nr­rÝr¢)r r2rIÚparse_subscriptÚ parse_call©r*rrÆr/r/r0rѶs   zParser.parse_postfixcCs\|jjj}|dkr| |¡}q|dkr@|jjjdkr@| |¡}q|dkrX| |¡}qqXq|S)NÚpiper!Úisr¢)r r2rIrlrTÚ parse_testrìrír/r/r0rÒÃs    zParser.parse_filter_exprcCst|jƒ}|jdkr„|jj}t|jƒ|jdkrFtj||jd|jdS|jdkr^| d|j¡tj |j|jd}tj ||d|jdS|jdkr g}|jjjdkrÂ|r²|j  d ¡|  |  ¡¡q”|j  d¡t|ƒd krä|d }ntj|d|jd}tj ||d|jdS| d |j¡dS) Nr­r!r×rMrÚzexpected name or numberrÝrårrrzexpected subscript expression)rcr rIr2rZGetattrrTr3r6rßZGetitemrar>Úparse_subscribedrÍrä)r*rr[Z attr_tokenr¥r£r/r/r0rëÒs0     ÿ      zParser.parse_subscriptcCsò|jjj}|jjjdkr*t|jƒdg}n*| ¡}|jjjdkrD|St|jƒ|g}|jjjdkrn| d¡n(|jjjdvrŒ| | ¡¡n | d¡|jjjdkrØt|jƒ|jjjdvrÌ| | ¡¡qâ| d¡n | d¡tj|d|iŽS)Nr^)rårr3) r r2r3rIrcrvr>rZSlice)r*r3r£rr/r/r0rñís*        zParser.parse_subscribedc s–ˆj d¡‰g}g}d}}d}‡‡fdd„}ˆjjjdkr\|r`ˆj d¡ˆjjjdkr`q\ˆjjjdkr–||duo~|duƒtˆjƒˆ ¡}nÀˆjjjdkrÄ||duƒtˆjƒˆ ¡}n’ˆjjjd kr*ˆj ¡jd kr*||duƒˆjjj}ˆj d ¡ˆ ¡} |  t j || | j d ¡n,||duoD|duoD| ƒ|  ˆ ¡¡d }q.ˆj d¡|dur~||||fSt j |||||ˆj d S)Nr¢Fcs|sˆ dˆj¡dS)Nz+invalid syntax for function call expression)r6r3)r8©r*r[r/r0Úensuresz!Parser.parse_call..ensurerHrrrÏr!rhr”rMT)r rar2rIrcrvrrTr‘r>rr‡r3r¨) r*rr£ÚkwargsÚdyn_argsÚ dyn_kwargsZ require_commarórêrTr/ròr0rì sF        ÿþ      zParser.parse_callc Cs¸|jjjdks|r´|s t|jƒ|j d¡}|j}|jjjdkrbt|jƒ|d|j d¡j7}q2|jjjdkr„| d¡\}}}}ng}g}d}}tj|||||||j d}d}q|S)Nrîr!r­Ú.r¢rMF) r r2rIrcrarTrìrZFilterr3) r*rr©r[r!r£rôrõrör/r/r0rl<s$   ÿzParser.parse_filterc Cs"t|jƒ}|jj d¡r(t|jƒd}nd}|j d¡j}|jjjdkrjt|jƒ|d|j d¡j7}q:d}}g}|jjjdkr˜| d¡\}}}}nV|jjjdvrê|jj d d d ¡sê|jj d ¡rÐ|  d ¡|  ¡} |  | ¡} | g}ng}t j |||||||jd}|rt j||jd}|S)Nr¿TFr!r­r÷r¢)r!rØrÚrÛr¢rÝrÞrur¸r½zname:isz'You cannot chain multiple tests with isrM)rcr r2rxrarTrIrìrJr6r±rÑrZTestr3rÀ) r*rr[Znegatedr!rõrörôr£Zarg_noder/r/r0rðQs8   ø   ÿzParser.parse_testcslg‰g‰ˆj}|dur"|j |¡‡‡fdd„}z|jr4|jj}|jdkrv|jrj|tj|j|jdƒt |jƒq4|jdkr¨t |jƒ||j ddƒ|j  d¡q4|jd kr*|ƒt |jƒ|durò|jjj |ŽròˆW|durð|j  ¡S| ¡}t|tƒrˆ |¡n ˆ |¡|j  d ¡q4td ƒ‚q4|ƒW|durh|j  ¡n|durf|j  ¡0ˆS) Ncs8ˆr4ˆdj}ˆ tjˆdd…|d¡ˆdd…=dS)NrrM)r3r>rr«rM©rnZ data_bufferr/r0Ú flush_datas z#Parser.subparse..flush_dataÚdatarMZvariable_beginTr|rFZ block_beginrGzinternal parsing error)r>r)r r2rIrTrZ TemplateDatar3rcrkrarJrWr]r§rBr<ÚAssertionError)r*rCZadd_datarùr[rPr/rør0rbwsN       ÿ  ó      ÿ  zParser.subparsecCs"tj| ¡dd}| |j¡|S)z0Parse the whole template into a `Template` node.rrM)rZTemplaterbZset_environmentr)r*rer/r/r0r&§s z Parser.parse)NNN)N)NN)N)N)F)TFNF)T)T)FTNF)F)N)7r³Ú __module__Ú __qualname__Ú__doc__r1rr6r@rArErLrQr]rfror{r€r†rŠr‹rr“r•r™r¡r¦rXrYrªr¬rjrvr¶r·r¹r¾rÁrÃrÇrÌrÎrÐr±rkràrárÑrÒrërñrìrlrðrbr&r/r/r/r0r&sv  %        * û %        #û A  0 & 0rN)rþrÙrZ_compatrÚ exceptionsrrZlexerrrÚ frozensetrUrÄZAddZSubZMulZDivZFloorDivZModrÈrNrr/r/r/r0Ús$      ÿ ú