3
/*^                @   s   d Z ddlZddlmZ ddlmZmZmZ ddlm	Z	m
Z
mZmZmZmZmZmZmZmZ ddlmZ ddlmZ ddlmZ G d	d
 d
eZG dd deZG dd deeZdd ZedkrddlZeej  dS )ah  
A spark grammar for Python 3.x.

However instead of terminal symbols being the usual ASCII text,
e.g. 5, myvariable, "for", etc.  they are CPython Bytecode tokens,
e.g. "LOAD_CONST 5", "STORE NAME myvariable", "SETUP_LOOP", etc.

If we succeed in creating a parse tree, then we have a Python program
that a later phase can turn into a sequence of ASCII text.
    N)Token)PythonParserPythonParserSinglenop_func)
	and_checkexcept_handler_else
ifelsestmtifstmt
iflaststmtor_checktesttruetryelsestmtl3	tryexcept
while1stmt)
SyntaxTree)DEFAULT_DEBUG)PYTHON3c                   s   e Zd Zef fdd	Zdd Zdd Zdd Zd	d
 Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zedd Zdd Zdd Zdd  Zd!d" Zd#d$ Z  ZS )%Python3Parserc                s*   t  | _tt| jtd|d t  | _d S )NZstmts)debug)setZadded_rulessuperr   __init__r   Z	new_rules)selfZdebug_parser)	__class__ V/home/psgendb/BIRCHDEV/python/lib/python3.6/site-packages/uncompyle6/parsers/parse3.pyr   2   s    zPython3Parser.__init__c             C   s   dS )a  
        # Python3 scanner adds LOAD_LISTCOMP. Python3 does list comprehension like
        # other comprehensions (set, dictionary).

        # Our "continue" heuristic -  in two successive JUMP_BACKS, the first
        # one may be a continue - sometimes classifies a JUMP_BACK
        # as a CONTINUE. The two are kind of the same in a comprehension.

        comp_for ::= expr for_iter store comp_iter CONTINUE
        comp_for ::= expr for_iter store comp_iter JUMP_BACK

        list_comp ::= BUILD_LIST_0 list_iter
        lc_body   ::= expr LIST_APPEND
        list_for ::= expr FOR_ITER store list_iter jb_or_c

        # This is seen in PyPy, but possibly it appears on other Python 3?
        list_if     ::= expr jmp_false list_iter COME_FROM
        list_if_not ::= expr jmp_true list_iter COME_FROM

        jb_or_c ::= JUMP_BACK
        jb_or_c ::= CONTINUE
        jb_cfs  ::= JUMP_BACK _come_froms

        stmt ::= set_comp_func

        set_comp_func ::= BUILD_SET_0 LOAD_FAST FOR_ITER store comp_iter
                          JUMP_BACK RETURN_VALUE RETURN_LAST

        set_comp_func ::= BUILD_SET_0 LOAD_FAST FOR_ITER store comp_iter
                          COME_FROM JUMP_BACK RETURN_VALUE RETURN_LAST

        comp_body ::= dict_comp_body
        comp_body ::= set_comp_body
        dict_comp_body ::= expr expr MAP_ADD
        set_comp_body ::= expr SET_ADD

        # See also common Python p_list_comprehension
        Nr   )r   argsr   r   r   p_comprehension37   s    zPython3Parser.p_comprehension3c             C   s   dS )a&  "
        expr ::= dict_comp
        stmt ::= dict_comp_func
        dict_comp_func ::= BUILD_MAP_0 LOAD_FAST FOR_ITER store
                           comp_iter JUMP_BACK RETURN_VALUE RETURN_LAST

        comp_iter     ::= comp_if_not
        comp_if_not   ::= expr jmp_true comp_iter
        Nr   )r   r   r   r   r   p_dict_comp3_   s    zPython3Parser.p_dict_comp3c             C   s   dS )a  
        sstmt ::= stmt
        stmt  ::= ifelsestmtr
        sstmt ::= return RETURN_LAST

        return_if_stmts ::= return_if_stmt come_from_opt
        return_if_stmts ::= _stmts return_if_stmt _come_froms
        return_if_stmt  ::= ret_expr RETURN_END_IF
        returns         ::= _stmts return_if_stmt

        stmt      ::= break
        break     ::= BREAK_LOOP

        stmt      ::= continue
        continue  ::= CONTINUE
        continues ::= _stmts lastl_stmt continue
        continues ::= lastl_stmt continue
        continues ::= continue


        kwarg      ::= LOAD_STR expr
        kwargs     ::= kwarg+

        classdef ::= build_class store

        # FIXME: we need to add these because don't detect this properly
        # in custom rules. Specifically if one of the exprs is CALL_FUNCTION
        # then we'll mistake that for the final CALL_FUNCTION.
        # We can fix by triggering on the CALL_FUNCTION op
        # Python3 introduced LOAD_BUILD_CLASS
        # Other definitions are in a custom rule
        build_class ::= LOAD_BUILD_CLASS mkfunc expr call CALL_FUNCTION_3
        build_class ::= LOAD_BUILD_CLASS mkfunc expr call expr CALL_FUNCTION_4

        stmt ::= classdefdeco
        classdefdeco ::= classdefdeco1 store

        expr    ::= LOAD_ASSERT
        assert  ::= assert_expr jmp_true LOAD_ASSERT RAISE_VARARGS_1 COME_FROM
        stmt    ::= assert2
        assert2 ::= assert_expr jmp_true LOAD_ASSERT expr
                    CALL_FUNCTION_1 RAISE_VARARGS_1 COME_FROM

        assert_expr ::= expr
        assert_expr ::= assert_expr_or
        assert_expr ::= assert_expr_and
        assert_expr_or ::= assert_expr jmp_true expr
        assert_expr_and ::= assert_expr jmp_false expr

        ifstmt  ::= testexpr _ifstmts_jump

        testexpr ::= testfalse
        testexpr ::= testtrue
        testfalse ::= expr jmp_false
        testtrue ::= expr jmp_true

        _ifstmts_jump   ::= return_if_stmts
        _ifstmts_jump   ::= stmts _come_froms
        _ifstmts_jumpl  ::= c_stmts_opt come_froms

        iflaststmt  ::= testexpr stmts_opt JUMP_ABSOLUTE
        iflaststmt  ::= testexpr _ifstmts_jumpl

        # ifstmts where we are in a loop
        _ifstmts_jumpl     ::= _ifstmts_jump
        iflaststmtl ::= testexpr c_stmts_opt JUMP_BACK
        iflaststmtl ::= testexpr _ifstmts_jumpl

        # These are used to keep parse tree indices the same
        jump_forward_else  ::= JUMP_FORWARD ELSE
        jump_absolute_else ::= JUMP_ABSOLUTE ELSE

        # Note: in if/else kinds of statements, we err on the side
        # of missing "else" clauses. Therefore we include grammar
        # rules with and without ELSE.

        ifelsestmt ::= testexpr stmts_opt JUMP_FORWARD
                       else_suite opt_come_from_except
        ifelsestmt ::= testexpr stmts_opt jump_forward_else
                       else_suite _come_froms

        # ifelsestmt ::= testexpr c_stmts_opt jump_forward_else
        #                pass  _come_froms

        # FIXME: remove this
        stmt         ::= ifelsestmtc

        c_stmts      ::= ifelsestmtc

        ifelsestmtc ::= testexpr c_stmts_opt JUMP_ABSOLUTE else_suitec
        ifelsestmtc ::= testexpr c_stmts_opt jump_absolute_else else_suitec
        ifelsestmtc ::= testexpr c_stmts_opt jump_forward_else else_suitec _come_froms

        # "if"/"else" statement that ends in a RETURN
        ifelsestmtr ::= testexpr return_if_stmts returns

        ifelsestmtl ::= testexpr c_stmts_opt JUMP_BACK else_suitel
        ifelsestmtl ::= testexpr c_stmts_opt cf_jump_back else_suitel
        ifelsestmtl ::= testexpr c_stmts_opt continue else_suitel


        cf_jump_back ::= COME_FROM JUMP_BACK

        # FIXME: this feels like a hack. Is it just 1 or two
        # COME_FROMs?  the parsed tree for this and even with just the
        # one COME_FROM for Python 2.7 seems to associate the
        # COME_FROM targets from the wrong places

        # this is nested inside a try_except
        tryfinallystmt ::= SETUP_FINALLY suite_stmts_opt
                           POP_BLOCK LOAD_CONST
                           COME_FROM_FINALLY suite_stmts_opt END_FINALLY

        except_handler_else ::= except_handler

        except_handler ::= jmp_abs COME_FROM except_stmts
                           END_FINALLY
        except_handler ::= jmp_abs COME_FROM_EXCEPT except_stmts
                           END_FINALLY

        # FIXME: remove this
        except_handler ::= JUMP_FORWARD COME_FROM except_stmts
                           END_FINALLY COME_FROM

        except_handler ::= JUMP_FORWARD COME_FROM except_stmts
                           END_FINALLY COME_FROM_EXCEPT

        except_stmts ::= except_stmt+

        except_stmt ::= except_cond1 except_suite
        except_stmt ::= except_cond2 except_suite
        except_stmt ::= except_cond2 except_suite_finalize
        except_stmt ::= except

        ## FIXME: what's except_pop_except?
        except_stmt ::= except_pop_except

        # Python3 introduced POP_EXCEPT
        except_suite ::= c_stmts_opt POP_EXCEPT jump_except
        jump_except ::= JUMP_ABSOLUTE
        jump_except ::= JUMP_BACK
        jump_except ::= JUMP_FORWARD
        jump_except ::= CONTINUE

        # This is used in Python 3 in
        # "except ... as e" to remove 'e' after the c_stmts_opt finishes
        except_suite_finalize ::= SETUP_FINALLY c_stmts_opt except_var_finalize
                                  END_FINALLY _jump

        except_var_finalize ::= POP_BLOCK POP_EXCEPT LOAD_CONST COME_FROM_FINALLY
                                LOAD_CONST store del_stmt

        except_suite ::= returns

        except_cond1 ::= DUP_TOP expr COMPARE_OP
                         jmp_false POP_TOP POP_TOP POP_TOP

        except_cond2 ::= DUP_TOP expr COMPARE_OP
                         jmp_false POP_TOP store POP_TOP

        except  ::=  POP_TOP POP_TOP POP_TOP c_stmts_opt POP_EXCEPT _jump
        except  ::=  POP_TOP POP_TOP POP_TOP returns

        jmp_abs ::= JUMP_ABSOLUTE
        jmp_abs ::= JUMP_BACK

        with    ::= expr SETUP_WITH POP_TOP suite_stmts_opt
                    POP_BLOCK LOAD_CONST COME_FROM_WITH
                    WITH_CLEANUP END_FINALLY

        withasstmt ::= expr SETUP_WITH store suite_stmts_opt
                POP_BLOCK LOAD_CONST COME_FROM_WITH
                WITH_CLEANUP END_FINALLY

        expr_jt     ::= expr jmp_true
        expr_jitop  ::= expr JUMP_IF_TRUE_OR_POP

        ## FIXME: Right now we have erroneous jump targets
        ## This below is probably not correct when the COME_FROM is put in the right place
        and  ::= expr jmp_false expr COME_FROM
        or   ::= expr_jt  expr COME_FROM
        or   ::= expr_jt expr
        or   ::= expr_jitop expr COME_FROM
        and  ::= expr JUMP_IF_FALSE_OR_POP expr COME_FROM

        # # something like the below is needed when the jump targets are fixed
        ## or  ::= expr JUMP_IF_TRUE_OR_POP COME_FROM expr
        ## and ::= expr JUMP_IF_FALSE_OR_POP COME_FROM expr
        Nr   )r   r   r   r   r   	p_grammarj   s    zPython3Parser.p_grammarc             C   s   dS )a  
        except_handler ::= JUMP_FORWARD COME_FROM_EXCEPT except_stmts
                           END_FINALLY COME_FROM
        except_handler ::= JUMP_FORWARD COME_FROM_EXCEPT except_stmts
                            END_FINALLY COME_FROM_EXCEPT_CLAUSE

        for_block ::= l_stmts_opt COME_FROM_LOOP JUMP_BACK
        for_block ::= l_stmts
        iflaststmtl ::= testexpr c_stmts_opt
        Nr   )r   r   r   r   r   p_misc3)  s    zPython3Parser.p_misc3c             C   s   dS )a7  
        # Annotated functions
        stmt                  ::= function_def_annotate
        function_def_annotate ::= mkfunc_annotate store

        mkfuncdeco0 ::= mkfunc_annotate

        # This has the annotation value.
        # LOAD_NAME is used in an annotation type like
        # int, float, str
        annotate_arg    ::= LOAD_NAME
        # LOAD_CONST is used in an annotation string
        annotate_arg    ::= expr

        # This stores the tuple of parameter names
        # that have been annotated
        annotate_tuple    ::= LOAD_CONST
        Nr   )r   r   r   r   r   p_def_annotations35  s    z Python3Parser.p_def_annotations3c             C   s   dS )z
        opt_come_from_except ::= COME_FROM_EXCEPT
        opt_come_from_except ::= _come_froms
        opt_come_from_except ::= come_from_except_clauses

        come_from_except_clauses ::= COME_FROM_EXCEPT_CLAUSE+
        Nr   )r   r   r   r   r   p_come_from3I  s    zPython3Parser.p_come_from3c             C   s   dS )a  
        jmp_false ::= POP_JUMP_IF_FALSE
        jmp_true  ::= POP_JUMP_IF_TRUE

        # FIXME: Common with 2.7
        ret_and    ::= expr JUMP_IF_FALSE_OR_POP ret_expr_or_cond COME_FROM
        ret_or     ::= expr JUMP_IF_TRUE_OR_POP ret_expr_or_cond COME_FROM
        if_exp_ret ::= expr POP_JUMP_IF_FALSE expr RETURN_END_IF COME_FROM ret_expr_or_cond


        # compare_chained1 is used exclusively in chained_compare
        compare_chained1 ::= expr DUP_TOP ROT_THREE COMPARE_OP JUMP_IF_FALSE_OR_POP
                             compare_chained1 COME_FROM
        compare_chained1 ::= expr DUP_TOP ROT_THREE COMPARE_OP JUMP_IF_FALSE_OR_POP
                             compare_chained2 COME_FROM
        Nr   )r   r   r   r   r   p_jump3R  s    zPython3Parser.p_jump3c             C   s   dS )a7  
        stmt               ::= if_exp_lambda

        stmt               ::= if_exp_not_lambda
        if_exp_lambda      ::= expr jmp_false expr return_if_lambda
                               return_stmt_lambda LAMBDA_MARKER
        if_exp_not_lambda  ::= expr jmp_true expr return_if_lambda
                               return_stmt_lambda LAMBDA_MARKER

        return_stmt_lambda ::= ret_expr RETURN_VALUE_LAMBDA
        return_if_lambda   ::= RETURN_END_IF_LAMBDA

        stmt ::= return_closure
        return_closure ::= LOAD_CLOSURE RETURN_VALUE RETURN_LAST

        stmt ::= whileTruestmt
        ifelsestmt ::= testexpr c_stmts_opt JUMP_FORWARD else_suite _come_froms

        # FIXME: go over this
        _stmts ::= _stmts last_stmt
        stmts ::= last_stmt
        stmts_opt ::= stmts
        last_stmt ::= iflaststmt
        last_stmt ::= forelselaststmt
        iflaststmt ::= testexpr last_stmt JUMP_ABSOLUTE
        iflaststmt ::= testexpr stmts JUMP_ABSOLUTE

        _iflaststmts_jump ::= stmts last_stmt
        _ifstmts_jump ::= stmts_opt JUMP_FORWARD _come_froms

        iflaststmt ::= testexpr _iflaststmts_jump
        ifelsestmt ::= testexpr stmts_opt jump_absolute_else else_suite
        ifelsestmt ::= testexpr stmts_opt jump_forward_else else_suite _come_froms
        else_suite ::= stmts
        else_suitel ::= stmts

        # FIXME: remove this
        _ifstmts_jump ::= c_stmts_opt JUMP_FORWARD _come_froms


        # statements with continue and break
        c_stmts ::= _stmts
        c_stmts ::= _stmts lastc_stmt
        c_stmts ::= lastc_stmt
        c_stmts ::= continues

        lastc_stmt ::= iflaststmtl
        lastc_stmt ::= forelselaststmt
        lastc_stmt ::= ifelsestmtc

        # Statements in a loop
        lstmt              ::= stmt
        l_stmts            ::= lstmt+
        Nr   )r   r   r   r   r   p_stmt3d  s    zPython3Parser.p_stmt3c             C   s   dS )aw	  
        stmt ::= whileelsestmt2

        for               ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK
                              COME_FROM_LOOP

        forelsestmt       ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK else_suite
                              COME_FROM_LOOP

        forelselaststmt   ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK else_suitec
                              COME_FROM_LOOP

        forelselaststmtl  ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK else_suitel
                              COME_FROM_LOOP

        whilestmt         ::= SETUP_LOOP testexpr l_stmts_opt COME_FROM JUMP_BACK POP_BLOCK
                              COME_FROM_LOOP

        whilestmt         ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK JUMP_BACK
                              COME_FROM_LOOP
        whilestmt         ::= SETUP_LOOP testexpr l_stmts_opt JUMP_BACK POP_BLOCK
                              COME_FROM_LOOP

        whilestmt         ::= SETUP_LOOP testexpr returns          POP_BLOCK
                              COME_FROM_LOOP

        while1elsestmt    ::= SETUP_LOOP          l_stmts     JUMP_BACK
                              else_suitel

        whileelsestmt     ::= SETUP_LOOP testexpr l_stmts_opt jb_cfs POP_BLOCK
                              else_suitel COME_FROM_LOOP


        whileelsestmt2    ::= SETUP_LOOP testexpr l_stmts_opt  JUMP_BACK POP_BLOCK
                              else_suitel JUMP_BACK COME_FROM_LOOP

        whileTruestmt     ::= SETUP_LOOP l_stmts_opt          JUMP_BACK POP_BLOCK
                              COME_FROM_LOOP

        # FIXME: Python 3.? starts adding branch optimization? Put this starting there.

        while1stmt        ::= SETUP_LOOP l_stmts COME_FROM_LOOP
        while1stmt        ::= SETUP_LOOP l_stmts COME_FROM JUMP_BACK COME_FROM_LOOP

        while1elsestmt    ::= SETUP_LOOP l_stmts JUMP_BACK
                              else_suite COME_FROM_LOOP

        # FIXME: investigate - can code really produce a NOP?
        whileTruestmt     ::= SETUP_LOOP l_stmts_opt JUMP_BACK NOP
                              COME_FROM_LOOP
        whileTruestmt     ::= SETUP_LOOP l_stmts_opt JUMP_BACK POP_BLOCK NOP
                              COME_FROM_LOOP
        for               ::= SETUP_LOOP expr for_iter store for_block POP_BLOCK NOP
                              COME_FROM_LOOP
        Nr   )r   r   r   r   r   p_loop_stmt3  s    zPython3Parser.p_loop_stmt3c             C   s   dS )zl
        load_genexpr ::= LOAD_GENEXPR
        load_genexpr ::= BUILD_TUPLE_1 LOAD_GENEXPR LOAD_STR
        Nr   )r   r   r   r   r   p_generator_exp3  s    zPython3Parser.p_generator_exp3c             C   s   dS )a  
        expr           ::= LOAD_STR
        expr           ::= if_exp_not
        if_exp_not     ::= expr jmp_true  expr jump_forward_else expr COME_FROM

        # a JUMP_FORWARD to another JUMP_FORWARD can get turned into
        # a JUMP_ABSOLUTE with no COME_FROM
        if_exp         ::= expr jmp_false expr jump_absolute_else expr

        # if_exp_true are for conditions which always evaluate true
        # There is dead or non-optional remnants of the condition code though,
        # and we use that to match on to reconstruct the source more accurately
        expr           ::= if_exp_true
        if_exp_true    ::= expr JUMP_FORWARD expr COME_FROM
        Nr   )r   r   r   r   r   p_expr3  s    zPython3Parser.p_expr3c             C   s(   | j dk	rd| j| j f S d| j S dS )zACustomize CALL_FUNCTION to add the number of positional argumentsNz%s_%iz%s_0)attrkind)tokenr   r   r   call_fn_name  s    
zPython3Parser.call_fn_namec             C   s  x@t |d t|D ]*}|| jjdr,P q|| jjdrP qW |t|k sVtd||d  jdksptdd}x0t |t|D ]}|| jjdr|| }P qW |std	| | jd
k r| j|}| j|\}	}
dd|	d  d|
  |f }n|j}|jdr\| j	dt
 |rD| j|\}	}
dd|	d  d|
 |f }ndd|jd  |f }n | j|}dd|jd  |f }| j	|t
 dS )a  
        # Should the first rule be somehow folded into the 2nd one?
        build_class ::= LOAD_BUILD_CLASS mkfunc
                        LOAD_CLASSNAME {expr}^n-1 CALL_FUNCTION_n
                        LOAD_CONST CALL_FUNCTION_n
        build_class ::= LOAD_BUILD_CLASS mkfunc
                        expr
                        call
                        CALL_FUNCTION_3
            MAKE_FUNCTIONMAKE_CLOSUREz7build_class needs to find MAKE_FUNCTION or MAKE_CLOSURELOAD_STRz<build_class expecting CONST after MAKE_FUNCTION/MAKE_CLOSURENCALL_FUNCTIONz:build_class custom rule for %s needs to find CALL_FUNCTIONg@z,build_class ::= LOAD_BUILD_CLASS mkfunc %s%szexpr zkwarg CALL_FUNCTION_KWz!classdef ::= build_class_kw storez1build_class_kw ::= LOAD_BUILD_CLASS mkfunc %s%s%sz:build_class_kw ::= LOAD_BUILD_CLASS mkfunc %sLOAD_CONST %s)rangelenr)   
startswithAssertionErrorRuntimeErrorversionr+   
get_pos_kwaddRuler   r(   )r   opnameir*   tokens	customizeis_pypyZcall_fn_tokcall_functionargs_posargs_kwruler   r   r   custom_build_class_rule  sT    







z%Python3Parser.custom_build_class_rulec             C   s   | j |\}}t|td d }|| }	|rh| jdkrh|dkrL| j||_dd|  d|  |j }
n.| j||_dd|  d|  d|  |j }
| j|
|j|	| d| jkr|dkr|jd	kr|d	krd
d|d	  ||f }
| j|
|j|	| dS )a!  
        call ::= expr {expr}^n CALL_FUNCTION_n
        call ::= expr {expr}^n CALL_FUNCTION_VAR_n
        call ::= expr {expr}^n CALL_FUNCTION_VAR_KW_n
        call ::= expr {expr}^n CALL_FUNCTION_KW_n

        classdefdeco2 ::= LOAD_BUILD_CLASS mkfunc {expr}^n-1 CALL_FUNCTION_n
        r0      g@zcall ::= expr zpos_arg zkwarg zexpr LOAD_BUILD_CLASSr,   z1classdefdeco2 ::= LOAD_BUILD_CLASS mkfunc %s%s_%dN)r8   r3   r7   r+   r)   add_unique_ruleseen_opsr(   )r   r:   r*   r=   Z
next_tokenr>   r@   rA   nakZ
uniq_paramrB   r   r   r   custom_classfunc_rule<  s"    	"

z#Python3Parser.custom_classfunc_rulec             C   sJ   | j dkr.ts| j rd}nd}||d  }n|d }| j|||| dS )ztPython 3.3 added a an addtional LOAD_STR before MAKE_FUNCTION and
        this has an effect on many rules.
        gffffff
@z	LOAD_STR zLOAD_CONST r,   r   N )r7   r   r>   rF   )r   rB   r:   r(   r=   load_opZnew_ruler   r   r   add_make_function_rulep  s    
z$Python3Parser.add_make_function_rulec       !      C   s>  d| _ tdփ}td׃}tdd |D | _tdd | jD | _d|krZd| _ | jdt t|}d}xBt|D ]6\}}|dkrp||d k rp| j	||d  dkrpd}qpW xxt|D ]j\}}|j
}	|	d|	jd |ks|	|k rq|	d|	jd }
|
dkr(d|j }d||	f }| j|t q|	jd rh|j}d!d| |	f }| j|t d"}| j|t q|
dkrd%|j }|	d&krd'}| j|d(d| d)}d*}| j|d)d+| d,}| j|d)d| d-}n| jd.krb|	jd/s|	jd$r.d0| jkrd1d2|j |	f }| j|t d3d|j |	f }n2d4|d|jd  |	f }| j||	|j| d5| }n0|d6 d7|j  }| j||	|j| d8|	|f }| j||	|j| q|	jd9r|j}d:d| |	f }| j|t q|	jdr|j}d;d| |	f }| j|t q|
dkrP|j}d}|
d>krd}x0t|D ]$}||| d  j
d@kr2d}P q2W |rdAdB| |	f }| j||	|j| | s|d+kr|j}|dC }|dD dD }|d+krdEdFdD  }| j||
|| |d+kr| jdGdHdD  |
|| |
|
jdd d j }dI| dJ|  dK|  d|dD   |	 }| jdL| |g| qqq|
dMkr|jdkrx| jdNdOg| n(|jdPkstdQ| | jdRdSg| q|	tdڃks|	jdYr |	dTkr|jdkrdZ}| j|t | j|	||||d  | j  q|
d[kr`| j|\}}t|
td[ dP }d\d]|  d^|  d|  |	 }| j||	|j| q|	dkr| jd_t |j|	 q|	d`kr| jdat |j|	 q|	dbkr| jdct |j|	 q|	ddkr| jdet |j|	 q|	dfkr
| jdgt |j|	 q|	dkr,| jdht |j|	 q|	dikrT|j}| jdjt |j|	 q|	dkkrv| j|	||||| j  q|	dlkr| jdmt |j|	 q|	dnkr| jdot |j|	 q|	d0kr|rdp}| j||	|j| |j|	 q|	dqkr| jdrt |j|	 q|	dskr6| jdt|	|j| |j|	 q|	dukrt|rh| jdvt dw}| j||	|j| |j|	 q|	dxkr| jdyt |j|	 q|	jdz
r|	d{krd0| jkrd|}| j|t |j\}}}| jd}k rd}nd}| j s||kr0|||  d~kr0dd]| |	f }| j||	|j| |	r,dd]| |	f }| j||	|j| |	r,| j s||kr|||  dskrdd]| |	f }| j||	|j| | j s||kr|||  dukrdd]| |	f }| j||	|j| | j 	s||k	r,|||  d0k	r,| jdd]| |	f |	|j| |d+k	r<d}nd}| jdk	r|d+k	rtd|d]| d|d  |	f }nd|d]| |	f }n| jd}k	r|d+k	rd|d]| d|d  |	f }nd|d]| |	f }nd| jdk
r4t	s| j  	rd}nd}|d+k
r dd]| |d|d  ||	f }ndd]| |||	f }| j||	|j| |d+k
rrdd]| |	f }| j||	|j| | jdk r"dd| |	f }| j||	|j| q|
jdr| jdkr|j\}}}}|| | }|r |
rdd| d| d|	f }ndd| d|	f }| j||	|j| n"dd| |	f }| j||	|j| dd| d| d|	f }| j||	|j| t r| j rdd| d| d|	f }| j||	|j| |r^dd]| |	f }| j||	|j| dd]| |	f }| j||	|j| | j s|dkr^||d  dskr^| jdkr<d|	f }| j||	|j| dd| |	f }| j||	|j| | j s~|dkr||d  d~krdd]| d^| |	f }| j||	|j| q| jdk r|j\}}}n|j\}}}}| jd}k rd}nd}|rTdd]| |	f }| j||	|j| | j s2||krT|||  dskrTdd| |	f }| j||	|j| | j sx||kr|||  d~krdd]| d^| |	f }| j||	|j| |d+krd}| jd|	|j| nd}| jd}k rd|d]| d|	f }| j||	|j| dd]| d|	f }nx| jd}kr.d|d]| d|	f }nV| jd.krPdd]| |d|	f }n4| jd}krrdd]| |d|	f }nd|d]| |	f }| j||	|j| tjd|	r"| jdkrdd]| d|d  |	f }| j||	|j| dd]| d|d  |	f }| jd}kr| jd}kr d| d]| f}nd]| d| f}d|d+ |d d|d  |	f }| j||	|j| d|d+ |d d|d  |	f }nRdd| d]| d|d  |	f }| j||	|j| dd| d]| d|d  |	f }| j|t q|	dkr| jdt |j|	 q|	dkr(| jdt |j|	 q|	dkrJ| jdt |j|	 q|	dkrl| jdt |j|	 q|	dkr| jdt |j|	 q|
dkr|j\}} d|	 d||  d   }| j|t q|
dkrd|	 d|j  }| j|t q|
dkrd|	 d|j  }| j|t |j|	 qW ttttt t!t"t#d| _$| jdkr^t%| j$d< d| j&d< d| j&d< d| j&d< d| j&d< d| j&d< d| j&d< d| j&d< d| j&d< d| j&d< | jdkrt'| j$d< d| j&d< d| j&d< d| j&d< d| j&d< tsd| j&d< | jdk r| j  rd| j&d< d| j&d< d| j&d< d| j&d< dS )a{  The base grammar we start out for a Python version even with the
        subclassing is, well, is pretty base.  And we want it that way: lean and
        mean so that parsing will go faster.

        Here, we add additional grammar rules based on specific instructions
        that are in the instruction/token stream. In classes that
        inherit from from here and other versions, grammar rules may
        also be removed.

        For example if we see a pretty rare DELETE_DEREF instruction we'll
        add the grammar for that.

        More importantly, here we add grammar rules for instructions
        that may access a variable number of stack items. CALL_FUNCTION,
        BUILD_LIST and so on are like this.

        Without custom rules, there can be an super-exponential number of
        derivations. See the deparsing paper for an elaboration of
        this.

        FBUILDCALLCONTINUEDELETEGETJUMPLOADLOOKUPMAKERETURNRAISESETUPUNPACKWITHBUILD_TUPLE_UNPACK_WITH_CALLc             S   s   g | ]
}|j qS r   )r)   ).0tr   r   r   
<listcomp>  s    z9Python3Parser.customize_grammar_rules.<locals>.<listcomp>c             S   s   g | ]}|d |j d qS )N_)rfind)r\   r:   r   r   r   r^     s    PyPyTaW  
              stmt ::= assign3_pypy
              stmt ::= assign2_pypy
              assign3_pypy       ::= expr expr expr store store store
              assign2_pypy       ::= expr expr store store
              stmt               ::= if_exp_lambda
              stmt               ::= if_exp_not_lambda
              if_expr_lambda     ::= expr jmp_false expr return_if_lambda
                                     return_lambda LAMBDA_MARKER
              if_exp_not_lambda  ::= expr jmp_true expr return_if_lambda
                                     return_lambda LAMBDA_MARKER
              GET_ITER   r,   ZCALL_FUNCTION_1Nr_   BUILD_CONST_KEY_MAPzexpr zdict ::= %sLOAD_CONST %sBUILD_LIST_UNPACKzbuild_list_unpack ::= %s%szexpr ::= build_list_unpack	BUILD_MAPBUILD_MAP_UNPACKz	kvlist_%sZBUILD_MAP_nzddict_comp_func ::= BUILD_MAP_n LOAD_FAST FOR_ITER store comp_iter JUMP_BACK RETURN_VALUE RETURN_LASTZdict_comp_funckvlist_nzkvlist_n ::=  kvlist_n kv3r   zkvlist_n ::=zdict ::=  BUILD_MAP_n kvlist_ng      @ZBUILD_MAP_WITH_CALLZLOAD_DICTCOMPzdict ::= %s%sz
dict_comp z
                             expr       ::= unmap_dict
                             unmap_dict ::= %s%s
                             z%s ::= %s %szdict ::=  %sz ::= zexpr expr STORE_MAP zdict ::=  %s %sBUILD_MAP_UNPACK_WITH_CALLz#build_map_unpack_with_call ::= %s%szstarred ::= %s %s
BUILD_LIST	BUILD_SETBUILD_TUPLEBUILD_TUPLE_UNPACKLOAD_CLOSUREzload_closure ::= %s%szLOAD_CLOSURE i       zexpr32 ::=%sz exprzexpr1024 ::=%sz expr32z%s ::= z	expr1024 zexpr32 zexpr ::= %sBUILD_SLICEzexpr ::= build_slice2z(build_slice2 ::= expr expr BUILD_SLICE_2rD   z'BUILD_SLICE value must be 2 or 3; is %szexpr ::= build_slice3z-build_slice3 ::= expr expr expr BUILD_SLICE_3r0   CALL_FUNCTION_EXCALL_FUNCTION_EX_KWCALL_FUNCTION_VARCALL_FUNCTION_VAR_KWr1   a8  
                     dict_comp    ::= LOAD_DICTCOMP LOAD_STR MAKE_FUNCTION_0 expr
                                      GET_ITER CALL_FUNCTION_1
                    classdefdeco1 ::= expr classdefdeco2 CALL_FUNCTION_1
                    classdefdeco1 ::= expr classdefdeco1 CALL_FUNCTION_1
                    ZCALL_METHODzcall ::= expr zpos_arg zkwarg zcontinue ::= CONTINUECONTINUE_LOOPzcontinue ::= CONTINUE_LOOPDELETE_ATTRzdel_stmt ::= expr DELETE_ATTRDELETE_DEREFz|
                   stmt           ::= del_deref_stmt
                   del_deref_stmt ::= DELETE_DEREF
                   DELETE_SUBSCRz
                    del_stmt ::= delete_subscript
                    delete_subscript ::= expr expr DELETE_SUBSCR
                   zo
                    expr      ::= get_iter
                    get_iter ::= expr GET_ITER
                    ZJUMP_IF_NOT_DEBUGa  
                    stmt        ::= assert_pypy
                    stmt        ::= assert_not_pypy
                    stmt        ::= assert2_pypy
                    stmt        ::= assert2_not_pypy
                    assert_pypy ::=  JUMP_IF_NOT_DEBUG assert_expr jmp_true
                                     LOAD_ASSERT RAISE_VARARGS_1 COME_FROM
                    assert_not_pypy ::=  JUMP_IF_NOT_DEBUG assert_expr jmp_false
                                     LOAD_ASSERT RAISE_VARARGS_1 COME_FROM
                    assert2_pypy ::= JUMP_IF_NOT_DEBUG assert_expr jmp_true
                                     LOAD_ASSERT expr CALL_FUNCTION_1
                                     RAISE_VARARGS_1 COME_FROM
                    assert2_pypy ::= JUMP_IF_NOT_DEBUG assert_expr jmp_true
                                     LOAD_ASSERT expr CALL_FUNCTION_1
                                     RAISE_VARARGS_1 COME_FROM
                    assert2_not_pypy ::= JUMP_IF_NOT_DEBUG assert_expr jmp_false
                                     LOAD_ASSERT expr CALL_FUNCTION_1
                                     RAISE_VARARGS_1 COME_FROM
                    rE   LOAD_CLASSDEREFzexpr ::= LOAD_CLASSDEREFZLOAD_CLASSNAMEzexpr ::= LOAD_CLASSNAMEzKdict_comp ::= LOAD_DICTCOMP %sMAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1	LOAD_ATTRzl
                  expr      ::= attribute
                  attribute ::= expr LOAD_ATTR
                  ZLOAD_LISTCOMPzexpr ::= listcompZLOAD_SETCOMPzexpr ::= set_compzIset_comp ::= LOAD_SETCOMP %sMAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1ZLOOKUP_METHODz
                             expr      ::= attribute
                             attribute ::= expr LOOKUP_METHOD
                             r.   ZMAKE_CLOSURE_0z
                        dict_comp ::= load_closure LOAD_DICTCOMP LOAD_STR
                                      MAKE_CLOSURE_0 expr
                                      GET_ITER CALL_FUNCTION_1
                    gffffff
@ZLOAD_LAMBDAz-mklambda ::= %sload_closure LOAD_LAMBDA %%s%szQgenerator_exp ::= %sload_closure load_genexpr %%s%s expr GET_ITER CALL_FUNCTION_1zMlistcomp ::= %sload_closure LOAD_LISTCOMP %%s%s expr GET_ITER CALL_FUNCTION_1zLset_comp ::= %sload_closure LOAD_SETCOMP %%s%s expr GET_ITER CALL_FUNCTION_1zKdict_comp ::= %sload_closure LOAD_DICTCOMP %s expr GET_ITER CALL_FUNCTION_1zkwargs rJ   g	@zBmkfunc_annotate ::= %s%s%sannotate_tuple load_closure LOAD_CODE %szannotate_arg z(mkfunc ::= %s%sload_closure LOAD_CODE %szKmkfunc_annotate ::= %s%s%sannotate_tuple load_closure LOAD_CODE LOAD_STR %sz1mkfunc ::= %s%sload_closure LOAD_CODE LOAD_STR %sg333333@r/   
LOAD_CONSTz;mkfunc_annotate ::= %s%s%sannotate_tuple load_closure %s %sz,mkfunc ::= %s%s load_closure LOAD_CODE %s %sz)mkfunc ::= %sload_closure load_genexpr %sz&mkfunc ::= %sload_closure LOAD_CODE %sr-   g@zmklambda ::= %s%s%s%szload_closure z#BUILD_TUPLE_1 LOAD_LAMBDA LOAD_STR zmklambda ::= %s%s%szLOAD_LAMBDA LOAD_STR z&mklambda ::= %sLOAD_LAMBDA LOAD_STR %szmkfunc ::= %s%s%s%szLOAD_CODE LOAD_STR zLOAD_CODE LOAD_CONST zDgenerator_exp ::= %sload_genexpr %%s%s expr GET_ITER CALL_FUNCTION_1zKlistcomp ::= load_closure LOAD_LISTCOMP %%s%s expr GET_ITER CALL_FUNCTION_1z@listcomp ::= %sLOAD_LISTCOMP %%s%s expr GET_ITER CALL_FUNCTION_1z"mklambda ::= %s%sLOAD_LAMBDA %%s%sZ	no_kwargszno_kwargs ::=kwargszmkfunc ::= %s %s%s%sz
LOAD_CODE zmkfunc ::= %s%s%szmkfunc ::= %s%s %s%szmkfunc ::= %s%sexpr %sz^MAKE_FUNCTION.*_Az<mkfunc_annotate ::= %s%sannotate_tuple LOAD_CODE LOAD_STR %szcall zKmkfunc_annotate ::= %s%s%sannotate_tuple LOAD_CODE LOAD_STR EXTENDED_ARG %szBmkfunc_annotate ::= %s%s%sannotate_tuple LOAD_CODE EXTENDED_ARG %sZRETURN_VALUE_LAMBDAzX
                    return_lambda ::= ret_expr RETURN_VALUE_LAMBDA
                    ZRAISE_VARARGS_0zy
                    stmt        ::= raise_stmt0
                    raise_stmt0 ::= RAISE_VARARGS_0
                    ZRAISE_VARARGS_1z~
                    stmt        ::= raise_stmt1
                    raise_stmt1 ::= expr RAISE_VARARGS_1
                    ZRAISE_VARARGS_2z
                    stmt        ::= raise_stmt2
                    raise_stmt2 ::= expr expr RAISE_VARARGS_2
                    SETUP_EXCEPTa  
                    try_except     ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
                                       except_handler opt_come_from_except
                    try_except     ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
                                       except_handler opt_come_from_except

                    tryelsestmtl   ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
                                       except_handler else_suitel come_from_except_clauses

                    stmt             ::= tryelsestmtl3

                    tryelsestmtl3    ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
                                         except_handler_else COME_FROM else_suitel
                                         opt_come_from_except
                    tryelsestmt      ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
                                         except_handler_else else_suite come_froms
                    	UNPACK_EXzunpack ::= z storeUNPACK_TUPLEUNPACK_SEQUENCEZUNPACK_LISTzunpack_list ::= )r   ifstmtlifelsestmtcr   orr   r   
try_exceptandASTZnoASTannotate_tupleaug_assign1aug_assign2r<   r   r   r   r	   r   iflaststmtlr
   r   r   kwargr   r   r   while1elsestmt)rM   rN   rO   rP   rQ   rR   rS   rT   rU   rV   rW   rX   rY   rZ   )r[   )rf   rg   )rj   rk   rl   rm   )r0   rq   rr   rs   rt   )r~   )r   r   )(r>   	frozensetr   rG   Zseen_op_basenamesr9   r   r3   	enumerater+   r)   findr`   r(   r4   rF   r7   r2   lowerZadd_unique_rulesr5   rI   r8   addrC   rL   r   researchr   r	   r   r   r   r   r   reduce_check_tabler   Zcheck_reducer
   )!r   r<   r=   Zcustomize_instruction_basenamesZcustom_ops_processednZhas_get_iter_call_function1r;   r*   r:   Zopname_baserh   rB   vZis_LOAD_CLOSUREjZbuild_countZ	thousandsZ	thirty32sZ
collectionr@   rA   rH   Zrule_patZannotate_argsZ
kwargs_strrK   closureZstack_countr|   Zpos_kw_tupleZbefore_countZafter_countr   r   r   customize_grammar_rules  s,                







   



(

    

 














$$













 $$










































z%Python3Parser.customize_grammar_rulesc          	   C   s  |d }t |}t||d }| jj|d }|rJ|| |||||||rJdS |d"krf|d d dkrfdS |dkrt|| jt S |dkr|| j}	t|	tpt|	t S |d#kr| j	dkrt
| |||||||S |d%kr| j	dk s|| dk rdS t
| |||||||rdS |d j }
|
jjdr|t|d t |d  }|jjdrl|
|krl|
j|jkS || dkr|| j |
jkrdS |
j|j k S dS |d'krdS |dkr2|d d dkr2t|t |d }|| j d(kr|d8 }|d }|| j |d j  ko,|| j k S   S |dkrt| |||||||rXdS | j	dkrhdS d|  kot |k n  r|| d)kr|d7 }x.|t |k rt|| jtr|d7 }qW |t |k r|| j}|| dkst||| jkrdS dS |dkrt |}||kr4|d8 }|| dkrL|d8 }n||d  dkrf|d8 }|| d*krxdS |d7 }x*||k rt|| jtr|d7 }qW ||krdS | j	dk o|| j|| jkS |d,kr|d- }t|ts|| j|d. jkS dS dS )/Nr   r,   Tr   r   r   r   r   r
   r   g@r	   testexpr_ifstmts_jumpg      @ZRETURN_END_IFFZPOP_JUMP_IFZ	COME_FROM\e__ifstmts_jumpr   rc   jump_forward_elser   COME_FROM_LOOP	JUMP_BACK
SETUP_LOOPr   rO   gffffff@c_stmts_opt
else_suite_come_froms)r   r   )r
   r   r   r   )r	   r   r   r   )r	   r   )r   r   )r   rO   r   r   r   r   r   )r   r   r   r   )r3   minr   get
isinstancer(   tuplestrunicoder7   r	   Z
last_childr)   r4   Zoff2intr   offsetr5   r   )r   rB   astr<   firstlastlhsr   fnargZcondition_jumpZcondition_jump2r   r   Z
come_fromsr   r   r   reduce_is_invalid-  s    

"


& "




      zPython3Parser.reduce_is_invalid)__name__
__module____qualname__PARSER_DEFAULT_DEBUGr   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   staticmethodr+   rC   rI   rL   r   r   __classcell__r   r   )r   r   r   1   s4   ( @	89H4       5r   c               @   s   e Zd Zdd ZdS )Python30Parserc             C   s   dS )z
        jmp_true ::= JUMP_IF_TRUE_OR_POP POP_TOP
        _ifstmts_jump ::= c_stmts_opt JUMP_FORWARD POP_TOP COME_FROM
        Nr   )r   r   r   r   r   p_30  s    zPython30Parser.p_30N)r   r   r   r   r   r   r   r   r     s   r   c               @   s   e Zd ZdS )Python3ParserSingleN)r   r   r   r   r   r   r   r     s   r   c             C   s   t  }t| dkr|| d }|dkr6ddlm} | }nF|dkrRddlm} | }n*|dkrnddlm} | }n|dkr|t }|j	  tt
jd	krt
jd	 d
krtdd  |j  d S )Nr   z3.5)Python35Parserz3.3)Python33Parserz3.2)Python32Parserz3.0r,   dump-2   )r   r3   Zuncompyle6.parser.parse35r   Zuncompyle6.parser.parse33r   Zuncompyle6.parser.parse32r   r   Zcheck_grammarsysargvprintZdump_grammar)r   pr   r   r   r   r   r   r   info  s$    r   __main__)!__doc__r   Zuncompyle6.scanners.tokr   Zuncompyle6.parserr   r   r   Zuncompyle6.parsers.reducecheckr   r   r   r	   r
   r   r   r   r   r   Zuncompyle6.parsers.treenoder   Zspark_parserr   r   Zxdisr   r   r   r   r   r   r   r   r   r   r   r   <module>   s6   0             