o ¦»^ŠJã@spdZddlZddlmZddlmZddlmZddlmZddlmZGdd „d e ƒZ eGd d „d e ƒƒZ dS) a‹Top down operator precedence parser. This is an implementation of Vaughan R. Pratt's "Top Down Operator Precedence" parser. (http://dl.acm.org/citation.cfm?doid=512927.512931). These are some additional resources that help explain the general idea behind a Pratt parser: * http://effbot.org/zone/simple-top-down-parsing.htm * http://javascript.crockford.com/tdop/tdop.html A few notes on the implementation. * All the nud/led tokens are on the Parser class itself, and are dispatched using getattr(). This keeps all the parsing logic contained to a single class. * We use two passes through the data. One to create a list of token, then one pass through the tokens to create the AST. While the lexer actually yields tokens, we convert it to a list so we can easily implement two tokens of lookahead. A previous implementation used a fixed circular buffer, but it was significantly slower. Also, the average jmespath expression typically does not have a large amount of token so this is not an issue. And interestingly enough, creating a token list first is actually faster than consuming from the token iterator one token at a time. éN)Úlexer)Úwith_repr_method)Úast)Ú exceptions)Úvisitorc@sBeZdZidd“dd“dd“dd“dd“dd“dd“d d“d d“d d“d d“d d“dd“dd“dd“dd“dd“dddddddddddddœ ¥Zd ZiZd!Zd‰d"d#„Zd$d%„Zd&d'„Z d(d)„Z dŠd*d+„Z d,d-„Z d.d/„Z d0d1„Zd2d3„Zd4d5„Zd6d7„Zd8d9„Zd:d;„Zdd?„Zd@dA„ZdBdC„ZdDdE„ZdFdG„ZdHdI„ZdJdK„ZdLdM„ZdNdO„ZdPdQ„ZdRdS„ZdTdU„Z dVdW„Z!dXdY„Z"dZd[„Z#d\d]„Z$d^d_„Z%d`da„Z&dbdc„Z'ddde„Z(dfdg„Z)dhdi„Z*djdk„Z+dldm„Z,dndo„Z-dpdq„Z.drds„Z/d‹dudv„Z0dwdx„Z1dydz„Z2d{d|„Z3d}d~„Z4dd€„Z5dd‚„Z6dƒd„„Z7d…d†„Z8e9d‡dˆ„ƒZ:dtS)ŒÚParserÚeofrÚunquoted_identifierÚquoted_identifierÚliteralÚrbracketÚrparenÚcommaÚrbraceÚnumberÚcurrentÚexprefÚcolonÚpipeéÚoréÚandéÚeqéÚgté ééé(é-é2é7é<) ÚltÚgteÚlteÚneÚflattenÚstarÚfilterÚdotÚnotÚlbraceÚlbracketÚlparené é€cCs"d|_dg||_||_d|_dS©Nr)Ú tokenizerÚ_tokensÚ _buffer_sizeÚ_index)ÚselfÚ lookahead©r:ú1/usr/lib/python3/dist-packages/jmespath/parser.pyÚ__init__Ns  zParser.__init__cCsH|j |¡}|dur |S| |¡}||j|<t|jƒ|jkr"| ¡|S©N)Ú_CACHEÚgetÚ _do_parseÚlenÚ _MAX_SIZEÚ_free_cache_entries)r8Ú expressionÚcachedÚ parsed_resultr:r:r;ÚparseTs   z Parser.parsec Cstz| |¡WStjy}z||_‚d}~wtjy)}z| |¡‚d}~wtjy9}z||_‚d}~wwr=)Ú_parserÚ LexerErrorrDÚIncompleteExpressionErrorÚset_expressionÚ ParseError)r8rDÚer:r:r;r@^s € €€þzParser._do_parsecCsrt ¡ |¡|_t|jƒ|_d|_|jdd}| ¡dks4|  d¡}t   |d|d|dd|d¡‚t ||ƒS)Nr)Ú binding_powerrÚstartÚvalueÚtypezUnexpected token: %s) rÚLexerÚtokenizer4Úlistr5r7Ú _expressionÚ_current_tokenÚ_lookahead_tokenrrLÚ ParsedResult)r8rDÚparsedÚtr:r:r;rHks     ÿ z Parser._parsecCsž| d¡}| ¡t|d|d|jƒ}||ƒ}| ¡}||j|krMt|d|dƒ}|dur:| d¡}| |¡n | ¡||ƒ}| ¡}||j|ks#|S)Nrz _token_nud_%srQz _token_led_%s)rWÚ_advanceÚgetattrÚ_error_nud_tokenrVÚ BINDING_POWERÚ_error_led_token)r8rNÚ left_tokenÚ nud_functionÚleftÚ current_tokenÚledÚ error_tokenr:r:r;rUvs$  þ  ø zParser._expressioncCót |d¡S©NrP)rr ©r8Útokenr:r:r;Ú_token_nud_literal‰ózParser._token_nud_literalcCrfrg)rÚfieldrhr:r:r;Ú_token_nud_unquoted_identifierŒrkz%Parser._token_nud_unquoted_identifiercCs@t |d¡}| ¡dkr| d¡}t d|d|dd¡‚|S)NrPr0rrQz1Quoted identifier not allowed for function names.)rrlrVrWrrL)r8rirlrZr:r:r;Ú_token_nud_quoted_identifiers  þz#Parser._token_nud_quoted_identifiercCs:t ¡}| ¡dkrt ¡}n| |jd¡}t ||¡S)Nr r*)rÚidentityrVÚ_parse_projection_rhsr^Úvalue_projection©r8rirbÚrightr:r:r;Ú_token_nud_staršs    zParser._token_nud_starcCs| t ¡¡Sr=)Ú_token_led_filterrrorhr:r:r;Ú_token_nud_filter¢rkzParser._token_nud_filtercCs| ¡Sr=)Ú_parse_multi_select_hashrhr:r:r;Ú_token_nud_lbrace¥ózParser._token_nud_lbracecCs| ¡}| d¡|S)Nr )rUÚ_match©r8rirDr:r:r;Ú_token_nud_lparen¨s zParser._token_nud_lparencCs*t t ¡¡}| |jd¡}t ||¡S©Nr))rr)rorpr^Ú projectionrrr:r:r;Ú_token_nud_flatten­s ÿ zParser._token_nud_flattencCó| |jd¡}t |¡S)Nr-)rUr^rÚnot_expression)r8riÚexprr:r:r;Ú_token_nud_not³ó zParser._token_nud_notcCsv| ¡dvr| ¡}| t ¡|¡S| ¡dkr7| d¡dkr7| ¡| ¡| |jd¡}t  t ¡|¡S|  ¡S)N©rrr*rr ) rVÚ_parse_index_expressionÚ_project_if_slicerroÚ _lookaheadr[rpr^r~Ú_parse_multi_select_list)r8rirsr:r:r;Ú_token_nud_lbracket·s  zParser._token_nud_lbracketcCsN| d¡dks| d¡dkr| ¡St | d¡d¡}| ¡| d¡|S)NrrrrPr )rˆÚ_parse_slice_expressionrÚindexrWr[rz)r8Únoder:r:r;r†Ès zParser._parse_index_expressioncCsºgd¢}d}| ¡}|dksS|dkrS|dkr,|d7}|dkr'| | d¡d¡| ¡n|dkr>| d¡d ||<| ¡n | | d¡d¡| ¡}|dksS|dks| d¡tj|ŽS) N)NNNrr rrrú syntax errorrrP)rVÚ_raise_parse_error_for_tokenrWr[rzrÚslice)r8ÚpartsrŒrcr:r:r;r‹×s* ÿ   ÿó  zParser._parse_slice_expressioncCst ¡Sr=)rÚ current_noderhr:r:r;Ú_token_nud_currentïryzParser._token_nud_currentcCr€)Nr)rUr^rrr{r:r:r;Ú_token_nud_exprefòr„zParser._token_nud_exprefcCsl| ¡dks$| |jd¡}|ddkr|d |¡|St ||g¡S| ¡| |jd¡}t ||¡S)Nr*r,rQÚ subexpressionÚchildren) rVÚ_parse_dot_rhsr^Úappendrr•r[rprq©r8rbrsr:r:r;Ú_token_led_dotös  ÿ zParser._token_led_dotcCó| |jd¡}t ||¡S)Nr)rUr^rrr™r:r:r;Ú_token_led_pipeó zParser._token_led_pipecCr›)Nr)rUr^rÚ or_expressionr™r:r:r;Ú _token_led_or rzParser._token_led_orcCr›)Nr)rUr^rÚand_expressionr™r:r:r;Ú_token_led_and rzParser._token_led_andcCs |ddkr| d¡}t |d|d|dd|d¡‚|d}g}| ¡dksC| ¡}| ¡dkr8| d¡| |¡| ¡dkr)| d¡t ||¡}|S) NrQrléþÿÿÿrOrPzInvalid function name '%s'r r) rWrrLrVrUrzr˜rÚfunction_expression)r8rbÚprev_tÚnameÚargsrDÚ function_noder:r:r;Ú_token_led_lparens"   þ     ü  zParser._token_led_lparencCsH| d¡}| d¡| ¡dkrt ¡}n| |jd¡}t |||¡S)Nrr r)r+)rUrzrVrrorpr^Úfilter_projection)r8rbÚ conditionrsr:r:r;ru%s    zParser._token_led_filtercCó | |d¡S)Nr©Ú_parse_comparator©r8rbr:r:r;Ú _token_led_eq/ó zParser._token_led_eqcCr«)Nr(r¬r®r:r:r;Ú _token_led_ne2r°zParser._token_led_necCr«)Nrr¬r®r:r:r;Ú _token_led_gt5r°zParser._token_led_gtcCr«)Nr&r¬r®r:r:r;Ú_token_led_gte8r°zParser._token_led_gtecCr«)Nr%r¬r®r:r:r;Ú _token_led_lt;r°zParser._token_led_ltcCr«)Nr'r¬r®r:r:r;Ú_token_led_lte>r°zParser._token_led_ltecCs&t |¡}| |jd¡}t ||¡Sr})rr)rpr^r~r™r:r:r;Ú_token_led_flattenAs ÿ zParser._token_led_flattencCsx| d¡}|ddvr$| ¡}|ddkr|d |¡|S| ||¡S| d¡| d¡| |jd¡}t ||¡S)NrrQr…Úindex_expressionr–r*r ) rWr†r˜r‡rzrpr^rr~)r8rbrirsr:r:r;Ú_token_led_lbracketGs       zParser._token_led_lbracketcCs6t ||g¡}|ddkrt || |jd¡¡S|S)NrQrr*)rr·r~rpr^)r8rbrsÚ index_exprr:r:r;r‡Zs þzParser._project_if_slicecCs| |j|¡}t |||¡Sr=)rUr^rÚ comparator)r8rbrºrsr:r:r;r­cszParser._parse_comparatorcCsFg} | ¡}| |¡| ¡dkrn| d¡q| d¡t |¡S)NTr r)rUr˜rVrzrÚmulti_select_list)r8Ú expressionsrDr:r:r;r‰gs   ú  zParser._parse_multi_select_listcCs’g} | d¡}|jddgd|d}| d¡| d¡}tj||d}| |¡| ¡d kr6| d ¡n | ¡d krB| d ¡nqtj|d S) NTrr r )Ú token_typesrPr)Úkey_namerrr)Únodes) rWÚ_match_multiple_tokensrzrUrÚ key_val_pairr˜rVÚmulti_select_dict)r8ÚpairsÚ key_tokenr¾rPrr:r:r;rwss$ ÿ       ñ zParser._parse_multi_select_hashcCsŽ|j| ¡|jkrt ¡}|S| ¡dkr| |¡}|S| ¡dkr*| |¡}|S| ¡dkr<| d¡| |¡}|S| |  d¡d¡|S)Nr/r+r,rrŽ) r^rVÚ_PROJECTION_STOPrrorUrzr—rrW)r8rNrsr:r:r;rp‡s" ö  ø  ú   þÿzParser._parse_projection_rhscCs€| ¡}|dvr | |¡S|dkr| d¡| ¡S|dkr'| d¡| ¡S| d¡}gd¢}d||df}| ||¡dS)N)r r r*r/r.r)r r r/r.úExpecting: %s, got: %srQ)rVrUrzr‰rwrWr)r8rNr9rZÚallowedÚmsgr:r:r;r—˜s     ÿzParser._parse_dot_rhscCs6|ddkrt |d|d|d¡‚| |d¡dS)NrQrrOrPú invalid token)rrJrrhr:r:r;r]´s ÿzParser._error_nud_tokencCs| |d¡dS)NrÉ)rrhr:r:r;r_ºózParser._error_led_tokenNcCs.| ¡|kr | ¡dS| || d¡¡dSr3)rVr[Ú_raise_parse_error_maybe_eofrW)r8Ú token_typer:r:r;rz½s   ÿz Parser._matchcCs*| ¡|vr| || d¡¡| ¡dSr3)rVrËrWr[)r8r½r:r:r;rÀÆs  ÿ zParser._match_multiple_tokenscCs|jd7_dS)Nr)r7©r8r:r:r;r[ÌszParser._advancecCs|j|jdS©NrQ©r5r7rÍr:r:r;rVÏrÊzParser._current_tokencCs|j|j|dSrÎrÏ©r8rr:r:r;rˆÒszParser._lookaheadcCs|j|j|Sr=rÏrÐr:r:r;rWÕrÊzParser._lookahead_tokencCs(|d}|d}|d}t ||||¡‚)NrOrPrQ)rrL)r8riÚreasonÚ lex_positionÚ actual_valueÚ actual_typer:r:r;rØs ÿz#Parser._raise_parse_error_for_tokencCsJ|d}|d}|d}|dkrt |||¡‚d||f}t ||||¡‚)NrOrPrQrrÆ)rrJrL)r8Ú expected_typerirÒrÓrÔÚmessager:r:r;rËßsÿÿÿz#Parser._raise_parse_error_maybe_eofcCs4t |j ¡t|jdƒ¡D] }|j |d¡qdS)Nr)ÚrandomÚsampler>ÚkeysÚintrBÚpop)r8Úkeyr:r:r;rCës ÿzParser._free_cache_entriescCs|j ¡dS)z'Clear the expression compilation cache.N)r>Úclear)Úclsr:r:r;Úpurgeïsz Parser.purge)r)rr=);Ú__name__Ú __module__Ú __qualname__r^rÅr>rBr<rGr@rHrUrjrmrnrtrvrxr|rrƒrŠr†r‹r“r”ršrœrŸr¡r¨rur¯r±r²r³r´rµr¶r¸r‡r­r‰rwrpr—r]r_rzrÀr[rVrˆrWrrËrCÚ classmethodrßr:r:r:r;r%sÐÿþýüûúùø ÷ ö õ ô óòñðïâ"          rc@s.eZdZdd„Zd dd„Zdd„Zdd „ZdS) rXcCs||_||_dSr=)rDrY)r8rDrYr:r:r;r<÷s zParsedResult.__init__NcCst |¡}| |j|¡}|Sr=)rÚTreeInterpreterÚvisitrY)r8rPÚoptionsÚ interpreterÚresultr:r:r;Úsearchûs zParsedResult.searchcCst ¡}| |j¡}|S)afRender the parsed AST as a dot file. Note that this is marked as an internal method because the AST is an implementation detail and is subject to change. This method can be used to help troubleshoot or for development purposes, but is not considered part of the public supported API. Use at your own risk. )rÚGraphvizVisitorrårY)r8ÚrendererÚcontentsr:r:r;Ú_render_dot_files zParsedResult._render_dot_filecCs t|jƒSr=)ÚreprrYrÍr:r:r;Ú__repr__s zParsedResult.__repr__r=)ràrárâr<rérírïr:r:r:r;rXõs   rX) Ú__doc__r×ÚjmespathrÚjmespath.compatrrrrÚobjectrrXr:r:r:r;Ús     S