dbfdg 3 sݨ\# @sdZddlmZddlmZmZddlmZmZddl m Z e dddd d d d d ddddg Z e ddddddgZ ejejejejejejdZGdddeZdS)z jinja2.parser ~~~~~~~~~~~~~ Implements the template parser. :copyright: (c) 2017 by the Jinja Team. :license: BSD, see LICENSE for more details. )nodes)TemplateSyntaxErrorTemplateAssertionError)describe_tokendescribe_token_expr)imapforifblockZextendsprintZmacroincludefromimportsetwith autoescapeeqneltZlteqgtZgteq)addsubmuldivfloordivmodc@seZdZdZdiddZdefddZddZdjd d Zdkd d Z dld dZ dmddZ ddZ dnddZ ddZddZddZddZddZd d!Zd"d#Zd$d%Zd&d'Zd(d)Zd*d+Zd,d-Zd.d/Zd0d1Zd2d3Zd4d5Zdod7d8Zdpd9d:Zd;d<Z d=d>Z!d?d@Z"dAdBZ#dCdDZ$dEdFZ%dGdHZ&dIdJZ'dKdLZ(dqdMdNZ)dOdPZ*drdQdRZ+dSdTZ,dUdVZ-dWdXZ.dYdZZ/d[d\Z0d]d^Z1d_d`Z2dsdadbZ3dcddZ4dtdedfZ5dgdhZ6dS)uParserzThis is the central parsing class Jinja2 uses. It's passed to extensions and can be used to parse expressions or statements. NcCst||_|j|||||_||_||_d|_i|_x,|jD] }x|jD]}|j |j|<qFWq:Wd|_ g|_ g|_ dS)NFr) environment _tokenizestreamnamefilenameclosed extensionsZiter_extensionsZtagsparse_last_identifier _tag_stack_end_token_stack)selfrsourcer r!state extensiontagr-/usr/lib/python3.6/parser.py__init__%s zParser.__init__cCs(|dkr|jjj}||||j|jdS)zConvenience method that raises `exc` with the message, passed line number or last line number as well as the current name and filename. N)rcurrentlinenor r!)r(msgr1excr-r-r.fail4s z Parser.failcCsg}x|D]}|jtt|q W|r@djdd|d D}nd}|dkrTdg}n d|g}|r|dk r||kr|jd|n|jd||jr|jd |jd |jd j||dS) Nz or css|]}dt|VqdS)z'%s'N)r).0exprr-r-r. Csz&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'. r:)extendrrjoinappendr&r4)r(r Zend_token_stackr1ZexpectedZexprsZcurrently_lookingmessager-r-r. _fail_ut_eof=s*   zParser._fail_ut_eofcCs|j||j|S)zCalled 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 r1r-r-r.fail_unknown_tag\szParser.fail_unknown_tagcCs*t|j}|dk r|j||jd||S)z9Like fail_unknown_tag but for end of template situations.N)listr'r=r?)r( end_tokensr1stackr-r-r.fail_eofcs  zParser.fail_eofcCs,|jjjdkrdS|dk r(|jjj|SdS)zAre we at the end of a tuple? variable_end block_endrparenTNF)rErFrG)rr0typetest_any)r(extra_end_rulesr-r-r. is_tuple_endjs zParser.is_tuple_endcCs6|jd7_tjtj}tjj|d|j|d|S)zDReturn a new free identifier as :class:`~jinja2.nodes.InternalName`.r8zfi%d)r1)r%object__new__rZ InternalNameZNoder/)r(r1rvr-r-r.free_identifierrs zParser.free_identifierc Cs|jj}|jdkr |jd|j|jj|jd}z|jtkrTt |d|jjjS|jdkrf|j S|jdkrx|j S|j j |j}|dk r||S|jjd}|j|j|jWd|r|jjXdS) zParse a single statement.r ztag name expectedTZparse_callfilterNF)rr0rHr4r1r&r=value_statement_keywordsgetattrparse_call_blockparse_filter_blockr#getpopr@)r(tokenZpop_tagZextr-r-r.parse_statementys(     zParser.parse_statementFcCsL|jjd|jjd|j|}|jjjdkr:|j||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. colonrFeof)rskip_ifexpectsubparser0rHrDnext)r(rB drop_needleresultr-r-r.parse_statementss     zParser.parse_statementscCsft|jj}|jdd}|jjdr<|j}tj|||dS|jd}|j ddd}tj ||||dS) zParse an assign statement.T)with_namespaceassign)r1N name:endset)ra)rf) r`rr1parse_assign_targetr] parse_tuplerZAssign parse_filterrcZ AssignBlock)r(r1targetr6Z filter_nodebodyr-r-r. parse_sets    zParser.parse_setc Cs|jjdj}|jdd}|jjd|jddd}d}|jjdrL|j}|jjd}|jd}t|jj d krxg}n|jdd d }t j |||||||dS)zParse a for loop.zname:forname:in)rJFname:recursive) with_condexprrJNzname:if name:endfor name:elseZendforT)ra)r1)rm)rn)rprq)rp) rr^r1rgrhr]parse_expressionrcr`rRrZFor)r(r1rjitertest recursiverkelse_r-r-r. parse_fors     zParser.parse_forcCstj|jjdjd}}x||jdd|_|jd |_g|_ g|_ t |j}|jdrxtj|jj jd}|j j |qn|jdr|jd dd |_ PqW|S) zParse an if construct.zname:if)r1F)ro name:elif name:else name:endifT)ra)rxryrz)rz)rZIfrr^r1rhrtrcrkZelif_rvr`r0r=)r(noderbrYr-r-r.parse_ifs"     zParser.parse_ifcCstjt|jjd}g}g}xb|jjjdkr~|jjj}|rF|jjd|j}|j d|j ||jjd|j |j qW||_ ||_ |jd dd|_|S) N)r1rFcommaparamre name:endwithT)ra)r)rZWithr`rr1r0rHr^rgset_ctxr=rrtargetsvaluesrcrk)r(r{rrr1rjr-r-r. parse_withs"      zParser.parse_withcCsDtjt|jjd}tjd|jg|_|jddd|_ tj |gS)N)r1rname:endautoescapeT)ra)r) rZScopedEvalContextModifierr`rr1KeywordrrZoptionsrcrkZScope)r(r{r-r-r.parse_autoescapes  zParser.parse_autoescapecCsptjt|jjd}|jjdj|_|jjd|_ |jj j dkrJ|j d|j d dd|_|jjd |j|S) N)r1r z name:scopedrzpBlock names in Jinja have to be valid Python identifiers and may not contain hyphens, use an underscore instead. name:endblockT)razname:)r)rZBlockr`rr1r^rRr r]Zscopedr0rHr4rcrk)r(r{r-r-r. parse_blocks zParser.parse_blockcCs"tjt|jjd}|j|_|S)N)r1)rZExtendsr`rr1rrtemplate)r(r{r-r-r. parse_extendss zParser.parse_extendscCsH|jjjddr>|jjjdr>t|jjdk|_|jjn||_|S)Nz name:withz name:withoutz name:contextr) rr0rIlookrtr`rR with_contextskip)r(r{defaultr-r-r.parse_import_contexts  zParser.parse_import_contextcCsbtjt|jjd}|j|_|jjjdrP|jj jdrPd|_ |jj dnd|_ |j |dS)N)r1z name:ignorez name:missingTF) rZIncluder`rr1rrrr0rtrZignore_missingrr)r(r{r-r-r. parse_includes zParser.parse_includecCsFtjt|jjd}|j|_|jjd|jddj |_ |j |dS)N)r1zname:asT) name_onlyF) rZImportr`rr1rrrr^rgr rjr)r(r{r-r-r. parse_import)s   zParser.parse_importcs tjtjjdj_jjdg_fdd}xjrRjjdjj j dkr|rhPj dd}|j j d rjd |jtd jjd rj dd}jj|j |j fnjj|j |sjj j dkrPq@jjdq@Wtd sd_S)N)r1z name:importcsBjjjdkr>jjjdr>tjjdk_jjdSdS)Nrwithoutz name:contextTF)rr)rr0rRrrtr`rrr-)r{r(r-r. parse_context6s  z(Parser.parse_from..parse_contextr}r T)r_z4names starting with an underline can not be imported)r3zname:asrF)rZ FromImportr`rr1rrrr^namesr0rHrgr startswithr4rr]r=hasattrr)r(rrjaliasr-)r{r(r. parse_from0s4        zParser.parse_fromcCsg|_}g|_}|jjdxl|jjjdkr|r@|jjd|jdd}|jd|jjdrr|j |j n|r|j d|j |q"W|jjddS) NlparenrGr}T)rr~rez-non-default argument follows default argument) argsdefaultsrr^r0rHrgrr]r=rrr4)r(r{rrargr-r-r.parse_signatureVs        zParser.parse_signaturecCsttjt|jjd}|jjjdkr.|j|n g|_g|_ |j |_ t |j tj s`|jd|j|jddd|_|S)N)r1rz expected call name:endcallT)ra)r)rZ CallBlockr`rr1r0rHrrrrrrP isinstanceCallr4rcrk)r(r{r-r-r.rUfs  zParser.parse_call_blockcCs8tjt|jjd}|jddd|_|jddd|_|S)N)r1T) start_inlinename:endfilter)ra)r) rZ FilterBlockr`rr1rirQrcrk)r(r{r-r-r.rVts  zParser.parse_filter_blockcCsBtjt|jjd}|jddj|_|j||jddd|_ |S)N)r1T)r name:endmacro)ra)r) rZMacror`rr1rgr rrcrk)r(r{r-r-r. parse_macro{s   zParser.parse_macrocCsTtjt|jjd}g|_x4|jjjdkrN|jr<|jjd|jj|j qW|S)N)r1rFr}) rOutputr`rr1r0rHr^r=rr)r(r{r-r-r. parse_prints zParser.parse_printTcCs|rN|jjjdkrN|jjd}t|j|jjd}tj|j|j|jd}nL|rt|jjd}tj |jd|jd}n&|r|j d|d}n|j }|j d|j s|jd|jjj|j|S)aParse an assignment target. As Jinja2 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 )r1ZstoreT) simplifiedrJzcan't assign to %r)rrrHr^r`rZNSRefrRr1Namerh parse_primaryrZ can_assignr4 __class____name__lower)r(Z with_tuplerrJrdrYattrrjr-r-r.rgs"       zParser.parse_assign_targetcCs|r |jS|jS)zParse an expression. Per default all expressions are parsed, if the optional `with_condexpr` parameter is set to `False` conditional expressions are not parsed. )parse_condexprparse_or)r(ror-r-r.rrszParser.parse_expressioncCsf|jjj}|j}xN|jjdr`|j}|jjdr>|j}nd}tj||||d}|jjj}qW|S)Nzname:ifz name:else)r1)rr0r1rr]rrZCondExpr)r(r1Zexpr1Zexpr2Zexpr3r-r-r.rs   zParser.parse_condexprcCsJ|jjj}|j}x2|jjdrD|j}tj|||d}|jjj}qW|S)Nzname:or)r1)rr0r1 parse_andr]rZOr)r(r1leftrightr-r-r.rs zParser.parse_orcCsJ|jjj}|j}x2|jjdrD|j}tj|||d}|jjj}qW|S)Nzname:and)r1)rr0r1 parse_notr]rZAnd)r(r1rrr-r-r.rs zParser.parse_andcCs4|jjjdr,t|jj}tj|j|dS|jS)Nzname:not)r1) rr0rtr`r1rNotr parse_compare)r(r1r-r-r.rs zParser.parse_notcCs|jjj}|j}g}x|jjj}|tkrLt|j|jtj ||jnh|jj drp|jtj d|jnD|jjj dr|jj j dr|jj d|jtj d|jnP|jjj}qW|s|Stj|||dS)Nzname:ininzname:notrZnotin)r1)rr0r1 parse_math1rH_compare_operatorsr`r=rZOperandr]rtrrZCompare)r(r1r6Zops token_typer-r-r.rs&     zParser.parse_comparecCsb|jjj}|j}xJ|jjjdkr\t|jjj}t|j|j}||||d}|jjj}qW|S)Nrr)r1)rr)rr0r1 parse_concatrH _math_nodesr`)r(r1rclsrr-r-r.rs  zParser.parse_math1cCsb|jjj}|jg}x*|jjjdkr>t|j|j|jqWt|dkrT|dStj ||dS)Ntilder8r)r1) rr0r1 parse_math2rHr`r=lenrZConcat)r(r1rr-r-r.rs    zParser.parse_concatcCsb|jjj}|j}xJ|jjjdkr\t|jjj}t|j|j}||||d}|jjj}qW|S)Nrrrr)r1)rrrr)rr0r1 parse_powrHrr`)r(r1rrrr-r-r.rs  zParser.parse_math2cCsV|jjj}|j}x>|jjjdkrPt|j|j}tj|||d}|jjj}qW|S)Npow)r1)rr0r1 parse_unaryrHr`rZPow)r(r1rrr-r-r.rs  zParser.parse_powcCs|jjj}|jjj}|dkrdsz$Parser.parse_tuple..Fr}Trz Expected an expression, got '%s'r)r1) rr0r1rrrr^rKr=rHr4rrTuple) r(rrorJrr1r$rZis_tupler-)r(r.rhJs2     zParser.parse_tuplecCsn|jjd}g}x@|jjjdkrP|r0|jjd|jjjdkr@P|j|jqW|jjdtj||jdS)Nrrbracketr})r1) rr^r0rHr=rrrZListr1)r(rYitemsr-r-r.rs   zParser.parse_listcCs|jjd}g}xf|jjjdkrv|r0|jjd|jjjdkr@P|j}|jjd|j}|jtj|||jdqW|jjdtj ||jdS)NrZrbracer}r[)r1) rr^r0rHrrr=rZPairr1ZDict)r(rYrkeyrRr-r-r.rs    zParser.parse_dictcCsFx@|jjj}|dks|dkr(|j|}q|dkr<|j|}qPqW|S)Nrrr)rr0rHparse_subscript parse_call)r(r{rr-r-r.rs   zParser.parse_postfixcCs`xZ|jjj}|dkr |j|}q|dkrB|jjjdkrB|j|}q|dkrV|j|}qPqW|S)Npiper isr)rr0rHrirR parse_testr)r(r{rr-r-r.rs    zParser.parse_filter_exprcCs t|j}|jdkr|jj}t|j|jdkrFtj||jd|jdS|jdkr^|jd|jtj |j|jd}tj ||d|jdS|jdkrg}x0|jjjdkr|r|jj d |j |j qW|jj dt|d kr|d }ntj|d|jd}tj ||d|jdS|jd |jdS) Nrr r)r1rzexpected name or numberrrr}r8rzexpected subscript expression)r`rrHr0rZGetattrrRr1r4rZGetitemr^r=parse_subscribedrr)r(r{rYZ attr_tokenrrr-r-r.rs.            zParser.parse_subscriptcCs|jjj}|jjjdkr*t|jdg}n*|j}|jjjdkrD|St|j|g}|jjjdkrn|jdn(|jjjdkr|j|jn |jd|jjjdkrt|j|jjjdkr|j|jq|jdn |jdtj|d|iS)Nr[rr}r1)rr})rr}) rr0r1rHr`rrr=rZSlice)r(r1rr{r-r-r.rs*        zParser.parse_subscribedc sjjdg}g}d}}d}fdd}x jjjdkrP|rbjjdjjjdkrbPjjjdkr||dko|dktjj}njjjdkr||dktjj}n||dko|dkjjjd kojjjd kr2jjj}jjd j} |j t j || | j d n|| |j jd }q2Wjjd|dkrt||||fSt j |||||j d S)NrFcs|sjdjdS)Nz+invalid syntax for function call expression)r4r1)r6)r(rYr-r.ensuresz!Parser.parse_call..ensurerGr}rrr rer)r1T)rr^r0rHr`rrrrRrr=rrr1r) r(r{rkwargsdyn_args dyn_kwargsZ require_commarrrRr-)r(rYr.rsF              zParser.parse_callc Csx|jjjdks|r|s"t|j|jjd}|j}x2|jjjdkrft|j|d|jjdj7}q6W|jjjdkr|jd\}}}}ng}g}d}}tj|||||||j d}d}qW|S)Nrr r.r)r1F) rr0rHr`r^rRrrFilterr1) r(r{rrYr rrrrr-r-r.ri s"    zParser.parse_filterc Cst|j}|jjjdr(t|jd}nd}|jjdj}x2|jjjdkrlt|j|d|jjdj7}q|jjXS) Ncs8r4dj}jtjdd|ddd=dS)Nr)r1)r1r=rr)r1)rk data_bufferr-r. flush_data[s z#Parser.subparse..flush_datadata)r1Zvariable_beginT)rorEZ block_beginrFzinternal parsing error)r=r'rr0rHrRrZ TemplateDatar1r`rhr^rIrZrrAr;AssertionErrorrX)r(rBZadd_datarrYrNr-)rkrr.r_SsD                 zParser.subparsecCs"tj|jdd}|j|j|S)z0Parse the whole template into a `Template` node.r8)r1)rZTemplater_Zset_environmentr)r(rbr-r-r.r$s z Parser.parse)NNN)N)NN)N)N)F)TFNF)T)T)FTNF)F)N)7r __module__ __qualname____doc__r/rr4r?r@rDrKrOrZrcrlrwr|rrrrrrrrrrUrVrrrgrrrrrrrrrrrrrrhrrrrrrrrirr_r$r-r-r-r.r sl           &          " 6  /  0rN)rZjinja2rZjinja2.exceptionsrrZ jinja2.lexerrrZjinja2._compatr frozensetrSrZAddZSubZMulZDivZFloorDivZModrrLrr-r-r-r. s