parse25.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. # Copyright (c) 2016-2018, 2020, 2022, 2024 Rocky Bernstein
  2. """
  3. spark grammar differences over Python2.6 for Python 2.5.
  4. """
  5. from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
  6. from uncompyle6.parser import PythonParserSingle
  7. from uncompyle6.parsers.parse26 import Python26Parser
  8. from uncompyle6.parsers.reducecheck import ifelsestmt
  9. class Python25Parser(Python26Parser):
  10. def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
  11. super(Python25Parser, self).__init__(debug_parser)
  12. self.customized = {}
  13. def p_misc25(self, args):
  14. """
  15. # If "return_if_stmt" is in a loop, a JUMP_BACK can be emitted. In 2.6 the
  16. # JUMP_BACK doesn't appear
  17. return_if_stmt ::= return_expr RETURN_END_IF JUMP_BACK
  18. # Python 2.6 uses ROT_TWO instead of the STORE_xxx
  19. # withas is allowed as a "from future" in 2.5
  20. # 2.6 and 2.7 do something slightly different
  21. setupwithas ::= DUP_TOP LOAD_ATTR store LOAD_ATTR CALL_FUNCTION_0
  22. setup_finally
  23. # opcode SETUP_WITH
  24. setupwith ::= DUP_TOP LOAD_ATTR store LOAD_ATTR CALL_FUNCTION_0 POP_TOP
  25. with ::= expr setupwith SETUP_FINALLY suite_stmts_opt
  26. POP_BLOCK LOAD_CONST COME_FROM with_cleanup
  27. # Semantic actions want store to be at index 2
  28. with_as ::= expr setupwithas store suite_stmts_opt
  29. POP_BLOCK LOAD_CONST COME_FROM with_cleanup
  30. # The last except of a "try: ... except" can do this...
  31. except_suite ::= c_stmts_opt COME_FROM JUMP_ABSOLUTE POP_TOP
  32. store ::= STORE_NAME
  33. store ::= STORE_FAST
  34. # tryelsetmtl doesn't need COME_FROM since the jump might not
  35. # be the the join point at the end of the "try" but instead back to the
  36. # loop. FIXME: should "come_froms" below be a single COME_FROM?
  37. tryelsestmt ::= SETUP_EXCEPT suite_stmts_opt POP_BLOCK
  38. except_handler else_suite come_froms
  39. # Python 2.6 omits the LOAD_FAST DELETE_FAST below
  40. # withas is allowed as a "from future" in 2.5
  41. with_as ::= expr setupwithas store suite_stmts_opt
  42. POP_BLOCK LOAD_CONST COME_FROM
  43. with_cleanup
  44. with_cleanup ::= LOAD_FAST DELETE_FAST WITH_CLEANUP END_FINALLY
  45. with_cleanup ::= LOAD_NAME DELETE_NAME WITH_CLEANUP END_FINALLY
  46. kvlist ::= kvlist kv
  47. kv ::= DUP_TOP expr ROT_TWO expr STORE_SUBSCR
  48. _ifstmts_jump ::= c_stmts_opt COME_FROM JUMP_ABSOLUTE COME_FROM POP_TOP
  49. # "and_then" is a hack around the fact we have THEN detection.
  50. and_then ::= expr JUMP_IF_FALSE THEN POP_TOP expr JUMP_IF_FALSE THEN POP_TOP
  51. testexpr_then ::= and_then
  52. """
  53. def customize_grammar_rules(self, tokens, customize):
  54. # Remove grammar rules inherited from Python 2.6 or Python 2
  55. self.remove_rules(
  56. """
  57. setupwith ::= DUP_TOP LOAD_ATTR ROT_TWO LOAD_ATTR CALL_FUNCTION_0 POP_TOP
  58. with ::= expr setupwith SETUP_FINALLY suite_stmts_opt
  59. POP_BLOCK LOAD_CONST COME_FROM WITH_CLEANUP END_FINALLY
  60. with_as ::= expr setupwithas store suite_stmts_opt
  61. POP_BLOCK LOAD_CONST COME_FROM WITH_CLEANUP END_FINALLY
  62. assert2 ::= assert_expr jmp_true LOAD_ASSERT expr CALL_FUNCTION_1 RAISE_VARARGS_1
  63. classdefdeco ::= classdefdeco1 store
  64. classdefdeco1 ::= expr classdefdeco1 CALL_FUNCTION_1
  65. classdefdeco1 ::= expr classdefdeco2 CALL_FUNCTION_1
  66. classdefdeco2 ::= LOAD_CONST expr mkfunc CALL_FUNCTION_0 BUILD_CLASS
  67. kv3 ::= expr expr STORE_MAP
  68. if_exp_ret ::= expr jmp_false_then expr RETURN_END_IF POP_TOP return_expr_or_cond
  69. return_if_lambda ::= RETURN_END_IF_LAMBDA POP_TOP
  70. return_if_stmt ::= return_expr RETURN_END_IF POP_TOP
  71. return_if_stmts ::= return_if_stmt
  72. return ::= return_expr RETURN_END_IF POP_TOP
  73. return ::= return_expr RETURN_VALUE POP_TOP
  74. return_stmt_lambda ::= return_expr RETURN_VALUE_LAMBDA
  75. setupwithas ::= DUP_TOP LOAD_ATTR ROT_TWO LOAD_ATTR CALL_FUNCTION_0 setup_finally
  76. stmt ::= classdefdeco
  77. stmt ::= if_exp_lambda
  78. stmt ::= if_exp_not_lambda
  79. if_exp_lambda ::= expr jmp_false_then expr return_if_lambda
  80. return_stmt_lambda LAMBDA_MARKER
  81. if_exp_not_lambda ::= expr jmp_true_then expr return_if_lambda
  82. return_stmt_lambda LAMBDA_MARKER
  83. """
  84. )
  85. super(Python25Parser, self).customize_grammar_rules(tokens, customize)
  86. if self.version[:2] == (2, 5):
  87. self.check_reduce["try_except"] = "AST"
  88. self.check_reduce["aug_assign1"] = "AST"
  89. self.check_reduce["ifelsestmt"] = "AST"
  90. def reduce_is_invalid(self, rule, ast, tokens, first, last):
  91. invalid = super(Python25Parser, self).reduce_is_invalid(
  92. rule, ast, tokens, first, last
  93. )
  94. if invalid or tokens is None:
  95. return invalid
  96. if rule == ("aug_assign1", ("expr", "expr", "inplace_op", "store")):
  97. return ast[0][0] == "and"
  98. lhs = rule[0]
  99. n = len(tokens)
  100. if lhs == "ifelsestmt":
  101. return ifelsestmt(self, lhs, n, rule, ast, tokens, first, last)
  102. return False
  103. class Python25ParserSingle(Python26Parser, PythonParserSingle):
  104. pass
  105. if __name__ == "__main__":
  106. # Check grammar
  107. p = Python25Parser()
  108. p.check_grammar()