3
/*^g                 @   st  d Z ddlmZ ddlmZmZ ddlmZ ddl	m
Z
 G dd de
Zdd	 ZG d
d deeZedkrpe Zej  ddlmZmZ edkrpej \ZZZZZddlmZ eeeZeejjj edj! Z"eee" Z#ddl$Z$edd e#D Z#edd e#D Z#ee#e" Z#e%e# ddl&Z&e'e&j(dkrpddl)m*Z* x(e+ej,j- D ]Z.e%e*e.d  qVW dS )z;
Python 3.7 grammar for the spark Earley-algorithm parser.
    )print_function)PythonParserSinglenop_func)DEFAULT_DEBUG)Python37BaseParserc                   sT  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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/d0 Zd1d2 Zd3d4 Zd5d6 Zd7d8 Zd9d: Z d;d< Z!d=d> Z"d?d@ Z#dAdB Z$dCdD Z%dEdF Z& fdGdHZ' fdIdJZ( fdKdLZ)  Z*S )MPython37Parserc                s   t t| j| i | _d S )N)superr   __init__Z
customized)selfZdebug_parser)	__class__ W/home/psgendb/BIRCHDEV/python/lib/python3.6/site-packages/uncompyle6/parsers/parse37.pyr	      s    zPython37Parser.__init__c             C   s   dS )zE
        # The start or goal symbol
        stmts ::= sstmt+
        Nr   )r
   argsr   r   r   p_start    s    zPython37Parser.p_startc             C   s   dS )z
        # eval-mode compilation.  Single-mode interactive compilation
        # adds another rule.
        call_stmt ::= expr POP_TOP
        Nr   )r
   r   r   r   r   p_call_stmt&   s    zPython37Parser.p_call_stmtc             C   s   dS )a  
        pass ::=

        _stmts ::= stmt+

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

        lastc_stmt ::= iflaststmt
        lastc_stmt ::= forelselaststmt
        lastc_stmt ::= ifelsestmtc

        # Statements in a loop
        lstmt              ::= stmt
        l_stmts            ::= lstmt+

        c_stmts_opt ::= c_stmts
        c_stmts_opt ::= pass

        # statements inside a loop
        l_stmts ::= _stmts
        l_stmts ::= returns
        l_stmts ::= continues
        l_stmts ::= _stmts lastl_stmt
        l_stmts ::= lastl_stmt

        lastl_stmt ::= iflaststmtl
        lastl_stmt ::= ifelsestmtl
        lastl_stmt ::= forelselaststmtl
        lastl_stmt ::= tryelsestmtl

        l_stmts_opt ::= l_stmts
        l_stmts_opt ::= pass

        suite_stmts ::= _stmts
        suite_stmts ::= returns
        suite_stmts ::= continues

        suite_stmts_opt ::= suite_stmts

        # passtmt is needed for semantic actions to add "pass"
        suite_stmts_opt ::= pass

        else_suite ::= suite_stmts
        else_suitel ::= l_stmts
        else_suitec ::= c_stmts
        else_suitec ::= returns

        else_suite_opt ::= else_suite
        else_suite_opt ::= pass

        stmt ::= classdef
        stmt ::= call_stmt

        stmt ::= ifstmt
        stmt ::= ifelsestmt

        stmt ::= whilestmt
        stmt ::= while1stmt
        stmt ::= whileelsestmt
        stmt ::= while1elsestmt
        stmt ::= for
        stmt ::= forelsestmt
        stmt ::= try_except
        stmt ::= tryelsestmt
        stmt ::= tryfinallystmt

        stmt ::= del_stmt
        del_stmt ::= DELETE_FAST
        del_stmt ::= DELETE_NAME
        del_stmt ::= DELETE_GLOBAL

        stmt   ::= return
        return ::= ret_expr RETURN_VALUE

        # "returns" nonterminal is a sequence of statements that ends in a RETURN statement.
        # In later Python versions with jump optimization, this can cause JUMPs
        # that would normally appear to be omitted.

        returns ::= return
        returns ::= _stmts return

        stmt ::= genexpr_func
        genexpr_func ::= LOAD_FAST _come_froms FOR_ITER store comp_iter JUMP_BACK
        Nr   )r
   r   r   r   r   p_stmt-   s    YzPython37Parser.p_stmtc             C   s   dS )a	  
        expr ::= LOAD_CODE
        expr ::= LOAD_CONST
        expr ::= LOAD_DEREF
        expr ::= LOAD_FAST
        expr ::= LOAD_GLOBAL
        expr ::= LOAD_NAME
        expr ::= LOAD_STR
        expr ::= _mklambda
        expr ::= and
        expr ::= bin_op
        expr ::= call
        expr ::= compare
        expr ::= dict
        expr ::= generator_exp
        expr ::= list
        expr ::= or
        expr ::= subscript
        expr ::= subscript2
        expr ::= unary_not
        expr ::= unary_op
        expr ::= yield

        # bin_op (formerly "binary_expr") is the Python AST BinOp
        bin_op      ::= expr expr binary_operator

        binary_operator   ::= BINARY_ADD
        binary_operator   ::= BINARY_MULTIPLY
        binary_operator   ::= BINARY_AND
        binary_operator   ::= BINARY_OR
        binary_operator   ::= BINARY_XOR
        binary_operator   ::= BINARY_SUBTRACT
        binary_operator   ::= BINARY_TRUE_DIVIDE
        binary_operator   ::= BINARY_FLOOR_DIVIDE
        binary_operator   ::= BINARY_MODULO
        binary_operator   ::= BINARY_LSHIFT
        binary_operator   ::= BINARY_RSHIFT
        binary_operator   ::= BINARY_POWER

        # unary_op (formerly "unary_expr") is the Python AST UnaryOp
        unary_op          ::= expr unary_operator
        unary_operator    ::= UNARY_POSITIVE
        unary_operator    ::= UNARY_NEGATIVE
        unary_operator    ::= UNARY_INVERT

        unary_not ::= expr UNARY_NOT

        subscript ::= expr expr BINARY_SUBSCR

        get_iter  ::= expr GET_ITER

        yield ::= expr YIELD_VALUE

        _mklambda ::= mklambda

        expr      ::= if_exp

        ret_expr  ::= expr
        ret_expr  ::= ret_and
        ret_expr  ::= ret_or

        ret_expr_or_cond ::= ret_expr
        ret_expr_or_cond ::= if_exp_ret

        stmt ::= return_lambda

        return_lambda ::= ret_expr RETURN_VALUE_LAMBDA LAMBDA_MARKER
        return_lambda ::= ret_expr RETURN_VALUE_LAMBDA

        compare        ::= compare_chained
        compare        ::= compare_single
        compare_single ::= expr expr COMPARE_OP

        # A compare_chained is two comparisions like x <= y <= z
        compare_chained  ::= expr compare_chained1 ROT_TWO POP_TOP _come_froms
        compare_chained2 ::= expr COMPARE_OP JUMP_FORWARD

        # Non-null kvlist items are broken out in the indiviual grammars
        kvlist ::=

        # Positional arguments in make_function
        pos_arg ::= expr
        Nr   )r
   r   r   r   r   p_expr   s    zPython37Parser.p_exprc             C   s   dS )a  
        stmt               ::= function_def
        function_def       ::= mkfunc store
        stmt               ::= function_def_deco
        function_def_deco  ::= mkfuncdeco store
        mkfuncdeco         ::= expr mkfuncdeco CALL_FUNCTION_1
        mkfuncdeco         ::= expr mkfuncdeco0 CALL_FUNCTION_1
        mkfuncdeco0        ::= mkfunc
        load_closure       ::= load_closure LOAD_CLOSURE
        load_closure       ::= LOAD_CLOSURE
        Nr   )r
   r   r   r   r   p_function_def   s    zPython37Parser.p_function_defc             C   s   dS )z	
        Nr   )r
   r   r   r   r   p_generator_exp   s    zPython37Parser.p_generator_expc             C   s   dS )a  
        _jump ::= JUMP_ABSOLUTE
        _jump ::= JUMP_FORWARD
        _jump ::= JUMP_BACK

        # Zero or more COME_FROMs - loops can have this
        _come_froms ::= COME_FROM*
        _come_froms ::= _come_froms COME_FROM_LOOP

        # One or more COME_FROMs - joins of tryelse's have this
        come_froms ::= COME_FROM+

        # Zero or one COME_FROM
        # And/or expressions have this
        come_from_opt ::= COME_FROM?
        Nr   )r
   r   r   r   r   p_jump   s    zPython37Parser.p_jumpc             C   s   dS )a  
        stmt ::= aug_assign1
        stmt ::= aug_assign2

        # This is odd in that other aug_assign1's have only 3 slots
        # The store isn't used as that's supposed to be also
        # indicated in the first expr
        aug_assign1 ::= expr expr
                        inplace_op store
        aug_assign1 ::= expr expr
                        inplace_op ROT_THREE STORE_SUBSCR
        aug_assign2 ::= expr DUP_TOP LOAD_ATTR expr
                        inplace_op ROT_TWO STORE_ATTR

        inplace_op ::= INPLACE_ADD
        inplace_op ::= INPLACE_SUBTRACT
        inplace_op ::= INPLACE_MULTIPLY
        inplace_op ::= INPLACE_TRUE_DIVIDE
        inplace_op ::= INPLACE_FLOOR_DIVIDE
        inplace_op ::= INPLACE_MODULO
        inplace_op ::= INPLACE_POWER
        inplace_op ::= INPLACE_LSHIFT
        inplace_op ::= INPLACE_RSHIFT
        inplace_op ::= INPLACE_AND
        inplace_op ::= INPLACE_XOR
        inplace_op ::= INPLACE_OR
        Nr   )r
   r   r   r   r   p_augmented_assign   s    z!Python37Parser.p_augmented_assignc             C   s   dS )a  
        stmt ::= assign
        assign ::= expr DUP_TOP designList
        assign ::= expr store

        stmt ::= assign2
        stmt ::= assign3
        assign2 ::= expr expr ROT_TWO store store
        assign3 ::= expr expr expr ROT_THREE ROT_TWO store store store
        Nr   )r
   r   r   r   r   p_assign  s    zPython37Parser.p_assignc             C   s   dS )a  
        get_for_iter ::= GET_ITER _come_froms FOR_ITER

        for_block ::= l_stmts_opt _come_froms JUMP_BACK

        forelsestmt ::= SETUP_LOOP expr get_for_iter store
                        for_block POP_BLOCK else_suite _come_froms

        forelselaststmt ::= SETUP_LOOP expr get_for_iter store
                for_block POP_BLOCK else_suitec _come_froms

        forelselaststmtl ::= SETUP_LOOP expr get_for_iter store
                for_block POP_BLOCK else_suitel _come_froms
        Nr   )r
   r   r   r   r   	p_forstmt)  s    zPython37Parser.p_forstmtc             C   s   dS )a:  
        stmt ::= import
        stmt ::= import_from
        stmt ::= import_from_star
        stmt ::= importmultiple

        importlist ::= importlist alias
        importlist ::= alias
        alias      ::= IMPORT_NAME store
        alias      ::= IMPORT_FROM store
        alias      ::= IMPORT_NAME attributes store

        import           ::= LOAD_CONST LOAD_CONST alias
        import_from_star ::= LOAD_CONST LOAD_CONST IMPORT_NAME IMPORT_STAR
        import_from_star ::= LOAD_CONST LOAD_CONST IMPORT_NAME_ATTR IMPORT_STAR
        import_from      ::= LOAD_CONST LOAD_CONST IMPORT_NAME importlist POP_TOP
        importmultiple   ::= LOAD_CONST LOAD_CONST alias imports_cont

        imports_cont ::= import_cont+
        import_cont  ::= LOAD_CONST LOAD_CONST alias

        attributes   ::= LOAD_ATTR+
        Nr   )r
   r   r   r   r   
p_import209  s    zPython37Parser.p_import20c             C   s   dS )a  
        stmt          ::= import_as37
        import_as37   ::= LOAD_CONST LOAD_CONST importlist37 store POP_TOP

        importlist37  ::= importlist37 ROT_TWO IMPORT_FROM
        importlist37  ::= importlist37 ROT_TWO POP_TOP IMPORT_FROM
        importlist37  ::= importattr37
        importattr37  ::= IMPORT_NAME_ATTR IMPORT_FROM

        # The 3.7base scanner adds IMPORT_NAME_ATTR
        alias         ::= IMPORT_NAME_ATTR attributes store
        alias         ::= IMPORT_NAME_ATTR store
        import_from   ::= LOAD_CONST LOAD_CONST importlist POP_TOP

        expr          ::= attribute37
        attribute37   ::= expr LOAD_METHOD

        stmt          ::= import_from37
        importlist37  ::= importlist37 alias37
        importlist37  ::= alias37
        alias37       ::= IMPORT_NAME store
        alias37       ::= IMPORT_FROM store
        import_from37 ::= LOAD_CONST LOAD_CONST IMPORT_NAME_ATTR importlist37 POP_TOP

        Nr   )r
   r   r   r   r   
p_import37R  s    zPython37Parser.p_import37c             C   s   dS )a   
        expr ::= list_comp

        list_iter ::= list_for
        list_iter ::= list_if
        list_iter ::= list_if_not
        list_iter ::= lc_body

        list_if ::= expr jmp_false list_iter
        list_if_not ::= expr jmp_true list_iter
        Nr   )r
   r   r   r   r   p_list_comprehensionm  s    z#Python37Parser.p_list_comprehensionc             C   s   dS )z
        comp_iter ::= comp_for
        comp_body ::= gen_comp_body
        gen_comp_body ::= expr YIELD_VALUE POP_TOP

        comp_if  ::= expr jmp_false comp_iter
        Nr   )r
   r   r   r   r   
p_set_compz  s    zPython37Parser.p_set_compc             C   s   dS )a  
        # Note. The below is right-recursive:
        designList ::= store store
        designList ::= store DUP_TOP designList

        ## Can we replace with left-recursive, and redo with:
        ##
        ##   designList  ::= designLists store store
        ##   designLists ::= designLists store DUP_TOP
        ##   designLists ::=
        ## Will need to redo semantic actiion

        store           ::= STORE_FAST
        store           ::= STORE_NAME
        store           ::= STORE_GLOBAL
        store           ::= STORE_DEREF
        store           ::= expr STORE_ATTR
        store           ::= store_subscript
        store_subscript ::= expr expr STORE_SUBSCR
        store           ::= unpack
        Nr   )r
   r   r   r   r   p_store  s    zPython37Parser.p_storec             C   s   dS )a  
        if_exp::= expr jmp_false expr jump_forward_else expr COME_FROM

        # compare_chained2 is used in a "chained_compare": x <= y <= z
        # used exclusively in compare_chained
        compare_chained2 ::= expr COMPARE_OP RETURN_VALUE
        compare_chained2 ::= expr COMPARE_OP RETURN_VALUE_LAMBDA

        # Python < 3.5 no POP BLOCK
        whileTruestmt  ::= SETUP_LOOP l_stmts_opt JUMP_BACK COME_FROM_LOOP

        # Python 3.5+ has jump optimization to remove the redundant
        # jump_excepts. But in 3.3 we need them added

        except_handler ::= JUMP_FORWARD COME_FROM_EXCEPT except_stmts
                           END_FINALLY

        tryelsestmt    ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
                           except_handler else_suite
                           jump_excepts come_from_except_clauses

        jump_excepts   ::= jump_except+

        subscript2 ::= expr expr DUP_TOP_TWO BINARY_SUBSCR

        # FIXME: The below rule was in uncompyle6.
        # In decompyle6 though "_ifstmts_jump" is part of an "ifstmt"
        # where as the below rule is appropriate for an "ifelsesmt"
        # Investigate and reconcile
        # _ifstmts_jump ::= c_stmts_opt JUMP_FORWARD _come_froms

        kv3       ::= expr expr STORE_MAP
        Nr   )r
   r   r   r   r   p_32on  s    "zPython37Parser.p_32onc             C   s   dS )a*  
        # Python 3.3+ adds yield from.
        expr          ::= yield_from
        yield_from    ::= expr GET_YIELD_FROM_ITER LOAD_CONST YIELD_FROM

        # We do the grammar hackery below for semantics
        # actions that want c_stmts_opt at index 1

        # Python 3.5+ has jump optimization to remove the redundant
        # jump_excepts. But in 3.3 we need them added

        try_except  ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
                        except_handler
                        jump_excepts come_from_except_clauses
        Nr   )r
   r   r   r   r   p_33on  s    zPython37Parser.p_33onc             C   s   dS )a  
        whilestmt     ::= setup_loop testexpr returns come_froms POP_BLOCK COME_FROM_LOOP

        # Seems to be needed starting 3.4.4 or so
        while1stmt    ::= setup_loop l_stmts
                          COME_FROM JUMP_BACK POP_BLOCK COME_FROM_LOOP
        while1stmt    ::= setup_loop l_stmts
                          POP_BLOCK COME_FROM_LOOP

        # FIXME the below masks a bug in not detecting COME_FROM_LOOP
        # grammar rules with COME_FROM -> COME_FROM_LOOP already exist
        whileelsestmt     ::= setup_loop testexpr l_stmts_opt JUMP_BACK POP_BLOCK
                              else_suitel COME_FROM

        while1elsestmt    ::= setup_loop l_stmts JUMP_BACK _come_froms POP_BLOCK else_suitel
                              COME_FROM_LOOP

        # Python 3.4+ optimizes the trailing two JUMPS away

        _ifstmts_jump ::= c_stmts_opt JUMP_ABSOLUTE JUMP_FORWARD _come_froms
        Nr   )r
   r   r   r   r   p_34on  s    zPython37Parser.p_34onc             C   s   dS )a\  

        while1elsestmt ::= setup_loop l_stmts JUMP_BACK
                           POP_BLOCK else_suite COME_FROM_LOOP

        # The following rule is for Python 3.5+ where we can have stuff like
        # while ..
        #     if
        #     ...
        # the end of the if will jump back to the loop and there will be a COME_FROM
        # after the jump
        l_stmts ::= lastl_stmt come_froms l_stmts

        # Python 3.5+ Await statement
        expr       ::= await_expr
        await_expr ::= expr GET_AWAITABLE LOAD_CONST YIELD_FROM

        stmt       ::= await_stmt
        await_stmt ::= await_expr POP_TOP

        # Python 3.5+ async additions

        inplace_op ::= INPLACE_MATRIX_MULTIPLY
        binary_operator  ::= BINARY_MATRIX_MULTIPLY

        # Python 3.5+ does jump optimization
        # In <.3.5 the below is a JUMP_FORWARD to a JUMP_ABSOLUTE.

        return_if_stmt ::= ret_expr RETURN_END_IF POP_BLOCK
        return_if_lambda   ::= RETURN_END_IF_LAMBDA COME_FROM

        jb_else     ::= JUMP_BACK ELSE
        jb_else     ::= JUMP_BACK COME_FROM
        ifelsestmtc ::= testexpr c_stmts_opt JUMP_FORWARD else_suitec
        ifelsestmtl ::= testexpr c_stmts_opt jb_else else_suitel

        # We want to keep the positions of the "then" and
        # "else" statements in "ifelstmtl" similar to others of this ilk.
        testexpr_cf ::= testexpr come_froms
        ifelsestmtl ::= testexpr_cf c_stmts_opt jb_else else_suitel

        # 3.5 Has jump optimization which can route the end of an
        # "if/then" back to to a loop just before an else.
        jump_absolute_else ::= jb_else
        jump_absolute_else ::= CONTINUE ELSE

        # Our hacky "ELSE" determination doesn't do a good job and really
        # determine the start of an "else". It could also be the end of an
        # "if-then" which ends in a "continue". Perhaps with real control-flow
        # analysis we'll sort this out. Or call "ELSE" something more appropriate.
        _ifstmts_jump ::= c_stmts_opt ELSE

        # ifstmt ::= testexpr c_stmts_opt

        iflaststmt ::= testexpr c_stmts_opt JUMP_FORWARD
        Nr   )r
   r   r   r   r   p_35on  s    zPython37Parser.p_35onc             C   s   dS )aE  
        stmt     ::= async_for_stmt37
        stmt     ::= async_for_stmt
        stmt     ::= async_forelse_stmt

        async_for_stmt     ::= setup_loop expr
                               GET_AITER
                               SETUP_EXCEPT GET_ANEXT LOAD_CONST
                               YIELD_FROM
                               store
                               POP_BLOCK JUMP_FORWARD COME_FROM_EXCEPT DUP_TOP
                               LOAD_GLOBAL COMPARE_OP POP_JUMP_IF_TRUE
                               END_FINALLY COME_FROM
                               for_block
                               COME_FROM
                               POP_TOP POP_TOP POP_TOP POP_EXCEPT POP_TOP POP_BLOCK
                               COME_FROM_LOOP

        # Order of LOAD_CONST YIELD_FROM is switched from 3.6 to save a LOAD_CONST
        async_for_stmt37   ::= setup_loop expr
                               GET_AITER
                               SETUP_EXCEPT GET_ANEXT
                               LOAD_CONST YIELD_FROM
                               store
                               POP_BLOCK JUMP_BACK COME_FROM_EXCEPT DUP_TOP
                               LOAD_GLOBAL COMPARE_OP POP_JUMP_IF_TRUE
                               END_FINALLY for_block COME_FROM
                               POP_TOP POP_TOP POP_TOP POP_EXCEPT
                               POP_TOP POP_BLOCK
                               COME_FROM_LOOP

        async_forelse_stmt ::= setup_loop expr
                               GET_AITER
                               SETUP_EXCEPT GET_ANEXT LOAD_CONST
                               YIELD_FROM
                               store
                               POP_BLOCK JUMP_FORWARD COME_FROM_EXCEPT DUP_TOP
                               LOAD_GLOBAL COMPARE_OP POP_JUMP_IF_TRUE
                               END_FINALLY COME_FROM
                               for_block
                               COME_FROM
                               POP_TOP POP_TOP POP_TOP POP_EXCEPT POP_TOP POP_BLOCK
                               else_suite COME_FROM_LOOP
        Nr   )r
   r   r   r   r   	p_37async   s    zPython37Parser.p_37asyncc             C   s   dS )a	  
        testtrue         ::= compare_chained37
        testfalse        ::= compare_chained37_false

        compare_chained     ::= compare_chained37
        compare_chained     ::= compare_chained37_false

        compare_chained37   ::= expr compare_chained1a_37
        compare_chained37   ::= expr compare_chained1c_37

        compare_chained37_false  ::= expr compare_chained1_false_37
        compare_chained37_false  ::= expr compare_chained1b_false_37
        compare_chained37_false  ::= expr compare_chained2_false_37

        compare_chained1a_37      ::= expr DUP_TOP ROT_THREE COMPARE_OP POP_JUMP_IF_FALSE
        compare_chained1a_37      ::= expr DUP_TOP ROT_THREE COMPARE_OP POP_JUMP_IF_FALSE
                                      compare_chained2a_37 COME_FROM POP_TOP COME_FROM
        compare_chained1b_false_37 ::= expr DUP_TOP ROT_THREE COMPARE_OP POP_JUMP_IF_FALSE
                                      compare_chained2b_false_37 POP_TOP _jump COME_FROM

        compare_chained1c_37      ::= expr DUP_TOP ROT_THREE COMPARE_OP POP_JUMP_IF_FALSE
                                      compare_chained2a_37 POP_TOP

        compare_chained1_false_37 ::= expr DUP_TOP ROT_THREE COMPARE_OP POP_JUMP_IF_FALSE
                                      compare_chained2c_37 POP_TOP JUMP_FORWARD COME_FROM
        compare_chained1_false_37 ::= expr DUP_TOP ROT_THREE COMPARE_OP POP_JUMP_IF_FALSE
                                      compare_chained2b_false_37 POP_TOP _jump COME_FROM

        compare_chained2_false_37 ::= expr DUP_TOP ROT_THREE COMPARE_OP POP_JUMP_IF_FALSE
                                      compare_chained2a_false_37 POP_TOP JUMP_BACK COME_FROM

        compare_chained2a_37       ::= expr COMPARE_OP come_from_opt POP_JUMP_IF_TRUE JUMP_FORWARD
        compare_chained2a_37       ::= expr COMPARE_OP come_from_opt POP_JUMP_IF_TRUE JUMP_BACK
        compare_chained2a_false_37 ::= expr COMPARE_OP come_from_opt POP_JUMP_IF_FALSE jf_cfs

        compare_chained2b_false_37 ::= expr COMPARE_OP come_from_opt POP_JUMP_IF_FALSE JUMP_FORWARD COME_FROM
        compare_chained2b_false_37 ::= expr COMPARE_OP come_from_opt POP_JUMP_IF_FALSE JUMP_FORWARD

        compare_chained2c_37       ::= expr DUP_TOP ROT_THREE COMPARE_OP come_from_opt POP_JUMP_IF_FALSE
                                       compare_chained2a_false_37 ELSE
        compare_chained2c_37       ::= expr DUP_TOP ROT_THREE COMPARE_OP come_from_opt POP_JUMP_IF_FALSE
                                       compare_chained2a_false_37
        Nr   )r
   r   r   r   r   p_37chainedN  s    zPython37Parser.p_37chainedc             C   s   dS )a  
        expr                       ::= if_exp37
        if_exp37                   ::= expr expr jf_cfs expr COME_FROM
        jf_cfs                     ::= JUMP_FORWARD _come_froms
        ifelsestmt                 ::= testexpr c_stmts_opt jf_cfs else_suite opt_come_from_except

        # This is probably more realistically an "ifstmt" (with a null else)
        # see _cmp() of python3.8/distutils/__pycache__/version.cpython-38.opt-1.pyc
        ifelsestmt                 ::= testexpr stmts jf_cfs else_suite_opt opt_come_from_except


        expr_pjit                  ::= expr POP_JUMP_IF_TRUE
        expr_jit                   ::= expr JUMP_IF_TRUE
        expr_jt                    ::= expr jmp_true

        jmp_false37                ::= POP_JUMP_IF_FALSE COME_FROM
        list_if                    ::= expr jmp_false37 list_iter
        list_iter                  ::= list_if37
        list_iter                  ::= list_if37_not
        list_if37                  ::= compare_chained37_false list_iter
        list_if37_not              ::= compare_chained37 list_iter

        _ifstmts_jump              ::= c_stmts_opt come_froms
        _ifstmts_jump              ::= COME_FROM c_stmts come_froms

        and_not                    ::= expr jmp_false expr POP_JUMP_IF_TRUE
        testfalse                  ::= and_not

        expr                       ::= if_exp_37a
        expr                       ::= if_exp_37b
        if_exp_37a                 ::= and_not expr JUMP_FORWARD come_froms expr COME_FROM
        if_exp_37b                 ::= expr jmp_false expr POP_JUMP_IF_FALSE jump_forward_else expr
        jmp_false_cf               ::= POP_JUMP_IF_FALSE COME_FROM
        comp_if                    ::= or jmp_false_cf comp_iter
        Nr   )r
   r   r   r   r   p_37conditionals{  s    zPython37Parser.p_37conditionalsc             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 get_for_iter store comp_iter CONTINUE
        comp_for ::= expr get_for_iter store comp_iter JUMP_BACK

        for_iter ::= _come_froms FOR_ITER

        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

        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
   r   r   r   r   p_comprehension3  s    zPython37Parser.p_comprehension3c             C   s   dS )al  "
        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
        comp_iter     ::= comp_if_not
        comp_if_not   ::= expr jmp_true comp_iter
        comp_iter     ::= comp_body
        Nr   )r
   r   r   r   r   p_dict_comp3  s    zPython37Parser.p_dict_comp3c             C   s   dS )a  
        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Python37Parser.p_expr3c             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Python37Parser.p_generator_exp3c             C   s   dS )aX  
        sstmt ::= stmt
        sstmt ::= 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

        # In 3.7 there are some LOAD_GLOBALs we don't convert to LOAD_ASSERT
        stmt    ::= assert2
        assert2 ::= expr jmp_true LOAD_GLOBAL expr CALL_FUNCTION_1 RAISE_VARARGS_1

        # "assert_invert" tests on the negative of the condition given
        stmt          ::= assert_invert
        assert_invert ::= testtrue LOAD_GLOBAL RAISE_VARARGS_1

        expr    ::= LOAD_ASSERT

        # FIXME: add this:
        # expr    ::= assert_expr_or

        ifstmt ::= testexpr _ifstmts_jump

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

        _ifstmts_jump ::= return_if_stmts
        _ifstmts_jump ::= c_stmts_opt COME_FROM

        iflaststmt  ::= testexpr c_stmts
        iflaststmt  ::= testexpr c_stmts JUMP_ABSOLUTE

        iflaststmtl ::= testexpr c_stmts JUMP_BACK
        iflaststmtl ::= testexpr c_stmts JUMP_BACK COME_FROM_LOOP
        iflaststmtl ::= testexpr c_stmts JUMP_BACK POP_BLOCK

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

        # 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 c_stmts_opt JUMP_FORWARD
                       else_suite opt_come_from_except
        ifelsestmt ::= testexpr c_stmts_opt jump_forward_else
                       else_suite _come_froms

        # This handles the case where a "JUMP_ABSOLUTE" is part
        # of an inner if in c_stmts_opt
        ifelsestmt ::= testexpr c_stmts come_froms
                       else_suite come_froms

        # ifelsestmt ::= testexpr c_stmts_opt jump_forward_else
        #                pass  _come_froms

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

        ifelsestmtr ::= testexpr return_if_stmts returns

        ifelsestmtl ::= testexpr c_stmts_opt cf_jump_back 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 ::= jmp_abs COME_FROM except_stmts
                           _come_froms END_FINALLY
        except_handler ::= jmp_abs COME_FROM_EXCEPT except_stmts
                           _come_froms END_FINALLY

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

        except_stmts   ::= except_stmt+

        except_stmt    ::= except_cond1 except_suite come_from_opt
        except_stmt    ::= except_cond2 except_suite come_from_opt
        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 come_from_opt

        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

        Nr   )r
   r   r   r   r   	p_grammar  s    zPython37Parser.p_grammarc             C   s   dS )a,  
        except_handler ::= JUMP_FORWARD COME_FROM_EXCEPT except_stmts
                           come_froms END_FINALLY

        for_block ::= l_stmts_opt COME_FROM_LOOP JUMP_BACK
        for_block ::= l_stmts
        for_block ::= l_stmts JUMP_BACK
        iflaststmtl ::= testexpr c_stmts
        Nr   )r
   r   r   r   r   p_misc3  s    zPython37Parser.p_misc3c             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_from3  s    zPython37Parser.p_come_from3c             C   s   dS )a9  
        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

        jitop_come_from_expr ::= JUMP_IF_TRUE_OR_POP come_froms expr
        jifop_come_from ::= JUMP_IF_FALSE_OR_POP come_froms
        expr_jitop      ::= expr JUMP_IF_TRUE_OR_POP

        or        ::= and jitop_come_from_expr COME_FROM
        or        ::= expr_jitop  expr COME_FROM
        or        ::= expr_jit expr COME_FROM
        or        ::= expr_pjit expr POP_JUMP_IF_FALSE COME_FROM

        testfalse_not_or   ::= expr jmp_false expr jmp_false COME_FROM
        testfalse_not_and ::= and jmp_true come_froms

        testfalse_not_and ::= expr jmp_false expr jmp_true  COME_FROM
        testfalse ::= testfalse_not_or
        testfalse ::= testfalse_not_and
        testfalse ::= or jmp_false COME_FROM

        iflaststmtl ::= testexprl c_stmts JUMP_BACK
        iflaststmtl ::= testexprl c_stmts JUMP_BACK COME_FROM_LOOP
        iflaststmtl ::= testexprl c_stmts JUMP_BACK POP_BLOCK
        testexprl   ::= testfalsel
        testfalsel  ::= expr jmp_true

        or          ::= expr_jt expr

        and  ::= expr JUMP_IF_FALSE_OR_POP expr come_from_opt
        and  ::= expr jifop_come_from expr

        expr_pjit_come_from ::= expr POP_JUMP_IF_TRUE COME_FROM
        or  ::= expr_pjit_come_from expr

        ## Note that "jmp_false" is what we check on in the "and" reduce rule.
        and ::= expr jmp_false expr COME_FROM
        or  ::= expr_jt  expr COME_FROM

        # 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_jump3  s    zPython37Parser.p_jump3c             C   s   dS )ar  
        stmt               ::= if_exp_lambda
        stmt               ::= if_exp_not_lambda

        # If statement inside a loop:
        stmt               ::= ifstmtl

        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
        ifelsestmtl        ::= testexpr c_stmts_opt jump_forward_else else_suitec

        ifstmtl            ::= testexpr _ifstmts_jumpl

        _ifstmts_jumpl     ::= c_stmts JUMP_BACK
        _ifstmts_jumpl     ::= _ifstmts_jump

        # The following can happen when the jump offset is large and
        # Python is looking to do a small jump to a larger jump to get
        # around the problem that the offset can't be represented in
        # the size allowed for the jump offset. This is more likely to
        # happen in wordcode Python since the offset range has been
        # reduced.  FIXME: We should add a reduction check that the
        # final jump goes to another jump.

        _ifstmts_jumpl     ::= COME_FROM c_stmts JUMP_BACK
        _ifstmts_jumpl     ::= COME_FROM c_stmts JUMP_FORWARD

        Nr   )r
   r   r   r   r   p_stmt3  s    zPython37Parser.p_stmt3c             C   s   dS )a	  
        setup_loop        ::= SETUP_LOOP _come_froms
        for               ::= setup_loop expr get_for_iter store for_block POP_BLOCK
        for               ::= setup_loop expr get_for_iter store for_block POP_BLOCK
                              COME_FROM_LOOP


        forelsestmt       ::= setup_loop expr get_for_iter store for_block POP_BLOCK else_suite
                              COME_FROM_LOOP

        forelselaststmt   ::= setup_loop expr get_for_iter store for_block POP_BLOCK else_suitec
                              COME_FROM_LOOP

        forelselaststmtl  ::= setup_loop expr get_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
                              COME_FROM_LOOP

        whilestmt         ::= setup_loop testexpr returns          POP_BLOCK
                              COME_FROM_LOOP

        # We can be missing a COME_FROM_LOOP if the "while" statement is nested inside an if/else
        # so after the POP_BLOCK we have a JUMP_FORWARD which forms the "else" portion of the "if"
        # This is undoubtedly some sort of JUMP optimization going on.

        whilestmt         ::= setup_loop testexpr l_stmts_opt JUMP_BACK come_froms
                              POP_BLOCK

        while1elsestmt    ::= setup_loop          l_stmts     JUMP_BACK
                              else_suitel

        whileelsestmt     ::= setup_loop testexpr l_stmts_opt JUMP_BACK POP_BLOCK
                              else_suitel COME_FROM_LOOP

        whileTruestmt     ::= setup_loop l_stmts_opt          JUMP_BACK POP_BLOCK
                              _come_froms

        # 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_LOOP JUMP_BACK POP_BLOCK 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?
        for               ::= setup_loop expr get_for_iter store for_block POP_BLOCK NOP
                              COME_FROM_LOOP
        Nr   )r
   r   r   r   r   p_loop_stmt3   s    zPython37Parser.p_loop_stmt3c             C   s   dS )as  
        sstmt ::= sstmt RETURN_LAST

        # 3.6 redoes how return_closure works. FIXME: Isolate to LOAD_CLOSURE
        return_closure   ::= LOAD_CLOSURE DUP_TOP STORE_NAME RETURN_VALUE RETURN_LAST

        for_block       ::= l_stmts_opt come_from_loops JUMP_BACK
        come_from_loops ::= COME_FROM_LOOP*

        whilestmt       ::= setup_loop testexpr l_stmts_opt
                            JUMP_BACK come_froms POP_BLOCK COME_FROM_LOOP
        whilestmt       ::= setup_loop testexpr l_stmts_opt
                            come_froms JUMP_BACK come_froms POP_BLOCK COME_FROM_LOOP

        # 3.6 due to jump optimization, we sometimes add RETURN_END_IF where
        # RETURN_VALUE is meant. Specifcally this can happen in
        # ifelsestmt -> ...else_suite _. suite_stmts... (last) stmt
        return ::= ret_expr RETURN_END_IF
        return ::= ret_expr RETURN_VALUE COME_FROM
        return_stmt_lambda ::= ret_expr RETURN_VALUE_LAMBDA COME_FROM

        # A COME_FROM is dropped off because of JUMP-to-JUMP optimization
        and  ::= expr jmp_false expr
        and  ::= expr jmp_false expr jmp_false

        jf_cf       ::= JUMP_FORWARD COME_FROM
        cf_jf_else  ::= come_froms JUMP_FORWARD ELSE

        if_exp ::= expr jmp_false expr jf_cf expr COME_FROM

        async_for_stmt     ::= setup_loop expr
                               GET_AITER
                               LOAD_CONST YIELD_FROM SETUP_EXCEPT GET_ANEXT LOAD_CONST
                               YIELD_FROM
                               store
                               POP_BLOCK JUMP_FORWARD COME_FROM_EXCEPT DUP_TOP
                               LOAD_GLOBAL COMPARE_OP POP_JUMP_IF_FALSE
                               POP_TOP POP_TOP POP_TOP POP_EXCEPT POP_BLOCK
                               JUMP_ABSOLUTE END_FINALLY COME_FROM
                               for_block POP_BLOCK
                               COME_FROM_LOOP

        # Adds a COME_FROM_ASYNC_WITH over 3.5
        # FIXME: remove corresponding rule for 3.5?

        except_suite ::= c_stmts_opt COME_FROM POP_EXCEPT jump_except COME_FROM

        jb_cfs      ::= come_from_opt JUMP_BACK come_froms
        ifelsestmtl ::= testexpr c_stmts_opt jb_cfs else_suitel
        ifelsestmtl ::= testexpr c_stmts_opt cf_jf_else else_suitel

        # In 3.6+, A sequence of statements ending in a RETURN can cause
        # JUMP_FORWARD END_FINALLY to be omitted from try middle

        except_return    ::= POP_TOP POP_TOP POP_TOP returns
        except_handler   ::= JUMP_FORWARD COME_FROM_EXCEPT except_return

        # Try middle following a returns
        except_handler36 ::= COME_FROM_EXCEPT except_stmts END_FINALLY

        stmt             ::= try_except36
        try_except36     ::= SETUP_EXCEPT returns except_handler36
                             opt_come_from_except
        try_except36     ::= SETUP_EXCEPT suite_stmts
        try_except36     ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
                             except_handler36 come_from_opt

        # 3.6 omits END_FINALLY sometimes
        except_handler36 ::= COME_FROM_EXCEPT except_stmts
        except_handler36 ::= JUMP_FORWARD COME_FROM_EXCEPT except_stmts
        except_handler   ::= jmp_abs COME_FROM_EXCEPT except_stmts

        stmt             ::= tryfinally36
        tryfinally36     ::= SETUP_FINALLY returns
                             COME_FROM_FINALLY suite_stmts
        tryfinally36     ::= SETUP_FINALLY returns
                             COME_FROM_FINALLY suite_stmts_opt END_FINALLY
        except_suite_finalize ::= SETUP_FINALLY returns
                                  COME_FROM_FINALLY suite_stmts_opt END_FINALLY _jump

        stmt ::= tryfinally_return_stmt
        tryfinally_return_stmt ::= SETUP_FINALLY suite_stmts_opt POP_BLOCK LOAD_CONST
                                   COME_FROM_FINALLY

        compare_chained2 ::= expr COMPARE_OP come_froms JUMP_FORWARD
        Nr   )r
   r   r   r   r   p_36misc9  s    zPython37Parser.p_36miscc             C   s   dS )a&  
        # long except clauses in a loop can sometimes cause a JUMP_BACK to turn into a
        # JUMP_FORWARD to a JUMP_BACK. And when this happens there is an additional
        # ELSE added to the except_suite. With better flow control perhaps we can
        # sort this out better.
        except_suite ::= c_stmts_opt POP_EXCEPT jump_except ELSE

        # FIXME: the below is to work around test_grammar expecting a "call" to be
        # on the LHS because it is also somewhere on in a rule.
        call        ::= expr CALL_METHOD_0
        Nr   )r
   r   r   r   r   p_37misc  s    zPython37Parser.p_37miscc       	         s  t t| j|| d| jd< xt|D ]\}}|j}|dkrZd|krXd}| j|| q(|dkrtd}| j|| q(|dkrd	}| j|| q(|d
krd| jkrd}| j|t	 nd| jkrd}| j|t	 q(|dkrd}| j|t	 q(|j
dr4|j}dd| |f }| j|| d| jkrd}| j|| q(|j
drd|j}dd| |f }| j|t	 q(|j
dr|j}ddt|d   dt|d d   d|d   | }| j|t	 dd| |f }| j|t	 q(|dkr(d}| jd k r|d!7 }n|d"7 }| j|t	 q(W d S )#NASTcall_kwZLOAD_ASSERTPyPyzT
                    stmt ::= JUMP_IF_NOT_DEBUG stmts COME_FROM
                    FORMAT_VALUEz
                    expr              ::= formatted_value1
                    formatted_value1  ::= expr FORMAT_VALUE
                ZFORMAT_VALUE_ATTRz
                expr              ::= formatted_value2
                formatted_value2  ::= expr expr FORMAT_VALUE_ATTR
                ZMAKE_FUNCTION_8ZLOAD_DICTCOMPz
                       dict_comp ::= load_closure LOAD_DICTCOMP LOAD_STR
                                     MAKE_FUNCTION_8 expr
                                     GET_ITER CALL_FUNCTION_1
                       ZLOAD_SETCOMPz
                       set_comp ::= load_closure LOAD_SETCOMP LOAD_STR
                                    MAKE_FUNCTION_8 expr
                                    GET_ITER CALL_FUNCTION_1
                       BEFORE_ASYNC_WITHa  
                  stmt               ::= async_with_stmt SETUP_ASYNC_WITH
                  async_with_pre     ::= BEFORE_ASYNC_WITH GET_AWAITABLE LOAD_CONST YIELD_FROM SETUP_ASYNC_WITH
                  async_with_post    ::= COME_FROM_ASYNC_WITH
                                         WITH_CLEANUP_START GET_AWAITABLE LOAD_CONST YIELD_FROM
                                         WITH_CLEANUP_FINISH END_FINALLY

                  stmt               ::= async_with_as_stmt
                  async_with_as_stmt ::= expr
                                         async_with_pre
                                         store
                                         suite_stmts_opt
                                         POP_BLOCK LOAD_CONST
                                         async_with_post

                 async_with_stmt     ::= expr
                                         async_with_pre
                                         POP_TOP
                                         suite_stmts_opt
                                         POP_BLOCK LOAD_CONST
                                         async_with_post
                 async_with_stmt     ::= expr
                                         async_with_pre
                                         POP_TOP
                                         suite_stmts_opt
                                         async_with_post
                BUILD_STRINGz
                    expr                 ::= joined_str
                    joined_str           ::= %sBUILD_STRING_%d
                zexpr z
                      formatted_value_attr ::= expr expr FORMAT_VALUE_ATTR expr BUILD_STRING
                      expr                 ::= formatted_value_attr
                    BUILD_MAP_UNPACK_WITH_CALLz#build_map_unpack_with_call ::= %s%sBUILD_TUPLE_UNPACK_WITH_CALLz!build_tuple_unpack_with_call ::= z	expr1024 i   zexpr32     zstarred ::= %s %s
SETUP_WITHa  
                with       ::= expr SETUP_WITH POP_TOP suite_stmts_opt COME_FROM_WITH
                               WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY

                # Removes POP_BLOCK LOAD_CONST from 3.6-
                withasstmt ::= expr SETUP_WITH store suite_stmts_opt COME_FROM_WITH
                               WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
                gffffff@z
                    with       ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK
                                   LOAD_CONST
                                   WITH_CLEANUP_START WITH_CLEANUP_FINISH END_FINALLY
                    a#  
                    with       ::= expr SETUP_WITH POP_TOP suite_stmts_opt POP_BLOCK
                                   BEGIN_FINALLY COME_FROM_WITH
                                   WITH_CLEANUP_START WITH_CLEANUP_FINISH
                                   END_FINALLY
                    )r   r   customize_grammar_rulesZcheck_reduce	enumeratekindZadd_unique_doc_rulesseen_opsaddRuler   
startswithattrintversion)	r
   tokens	customizeitokenopnameZ	rules_strrulev)r   r   r   r;     sh    


8z&Python37Parser.customize_grammar_rulesc                s  | j |\}}t|td d }|| }tdj| jrdd|  d|  d|  |j d	 }	| j|	|j|| | jd
|j|| |jdr| jdt	 d|j
 }
djf t }	| j|	|j|j
| n|dkr&| jdt	 d| jkr| jdt	 d| jkr| jdt	 d| jkr| jdt	 nt|dkr| jdt	 d| jkrT| jdt	 d| jkrv| jdd |j
 t	 | jdt	 ntt| j|||| d S )NCALL_FUNCTION   GET_AWAITABLE
YIELD_FROMzasync_call ::= expr zpos_arg zkwarg zexpr z$ GET_AWAITABLE LOAD_CONST YIELD_FROMzexpr ::= async_callCALL_FUNCTION_KWzexpr ::= call_kw36z/call_kw36 ::= expr {values} LOAD_CONST {opname}ZCALL_FUNCTION_EX_KWa  expr        ::= call_ex_kw4
                            call_ex_kw4 ::= expr
                                            expr
                                            expr
                                            CALL_FUNCTION_EX_KW
                         r7   zexpr        ::= call_ex_kw
                                call_ex_kw  ::= expr expr build_map_unpack_with_call
                                                CALL_FUNCTION_EX_KW
                             r8   a4  expr        ::= call_ex_kw3
                                call_ex_kw3 ::= expr
                                                build_tuple_unpack_with_call
                                                expr
                                                CALL_FUNCTION_EX_KW
                             aZ  expr        ::= call_ex_kw2
                                    call_ex_kw2 ::= expr
                                                    build_tuple_unpack_with_call
                                                    build_map_unpack_with_call
                                                    CALL_FUNCTION_EX_KW
                             CALL_FUNCTION_EXz
                         expr        ::= call_ex
                         starred     ::= expr
                         call_ex     ::= expr starred CALL_FUNCTION_EX
                         z
                        expr        ::= call_ex_kw
                        call_ex_kw  ::= expr expr
                                        build_map_unpack_with_call CALL_FUNCTION_EX
                        a#  
                        expr        ::= call_ex_kw3
                        call_ex_kw3 ::= expr
                                        build_tuple_unpack_with_call
                                        %s
                                        CALL_FUNCTION_EX
                        a  
                        expr        ::= call_ex_kw4
                        call_ex_kw4 ::= expr
                                        expr
                                        expr
                                        CALL_FUNCTION_EX
                        )rM   rN   )Z
get_pos_kwlen	frozensetissubsetr>   r=   Zadd_unique_ruler@   r?   r   rA   formatlocalsZseen_op_basenamesr   r   custom_classfunc_rule)r
   rH   rG   rE   Z
next_tokenZargs_posZargs_kwZnakZ
uniq_paramrI   values)r   r   r   rV      s^    &




	
z$Python37Parser.custom_classfunc_rulec                s`   t t| j|||||}|r |S |d dkr\|d }x&t|tsZ|d dkrPdS |d }q6W dS )Nr   r2   TF)r   r   reduce_is_invalid
isinstanceToken)r
   rI   astrD   firstlastinvalidnt)r   r   r   rX     s    
z Python37Parser.reduce_is_invalid)+__name__
__module____qualname__PARSER_DEFAULT_DEBUGr	   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r;   rV   rX   __classcell__r   r   )r   r   r      sP   [U	$:.-%) #	4*9X {r   c             C   s   | }t | dkrZ| d }|dkr6ddlm} | }n$|dkrRddlm} | }ntd|j  t tjdkrtjd dkrt	d	d
  |j
  d S )Nr   z3.7)r   z3.8)Python38ParserzOnly 3.7 and 3.8 supported   dump-2   )rQ   Zuncompyle6.parser.parse37r   Zuncompyle6.parser.parse38re   RuntimeErrorcheck_grammarsysargvprintZdump_grammar)r   r   pargre   r   r   r   info  s    rq   c               @   s   e Zd ZdS )Python37ParserSingleN)r`   ra   rb   r   r   r   r   rr     s   rr   __main__)PYTHON_VERSIONIS_PYPYg@)get_scannerzJUMP_BACK CONTINUE RETURN_END_IF COME_FROM
               LOAD_GENEXPR LOAD_ASSERT LOAD_SETCOMP LOAD_DICTCOMP LOAD_CLASSNAME
               LAMBDA_MARKER RETURN_LAST
            Nc             C   s   g | ]}t jd d|qS )z_\d+$ )resub).0tr   r   r   
<listcomp>  s    r|   c             C   s   g | ]}t jd d|qS )z_CONT$rw   )rx   ry   )rz   r{   r   r   r   r|     s    rf   )rule2str)/__doc__
__future__r   Zuncompyle6.parserr   r   Zspark_parserr   rc   Zuncompyle6.parsers.parse37baser   r   rq   rr   r`   ro   rk   
uncompyle6rt   ru   Z
check_setslhsrhsrD   Zright_recursiveZdup_rhsZuncompyle6.scannerrv   ssetZopcrH   unionsplitZ
opcode_setZremain_tokensrx   rn   rl   rQ   rm   Zspark_parser.sparkr}   sortedZ	rule2nameitemsrI   r   r   r   r   <module>   sP              


