parse14.py 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. # Copyright (c) 2018, 2022 Rocky Bernstein
  2. from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
  3. from uncompyle6.parser import PythonParserSingle, nop_func
  4. from uncompyle6.parsers.parse15 import Python15Parser
  5. class Python14Parser(Python15Parser):
  6. def p_misc14(self, args):
  7. """
  8. # Not much here yet, but will probably need to add UNARY_CALL,
  9. # LOAD_LOCAL, SET_FUNC_ARGS
  10. args ::= RESERVE_FAST UNPACK_ARG args_store
  11. args_store ::= STORE_FAST*
  12. call ::= expr tuple BINARY_CALL
  13. expr ::= call
  14. kv ::= DUP_TOP expr ROT_TWO LOAD_CONST STORE_SUBSCR
  15. mkfunc ::= LOAD_CODE BUILD_FUNCTION
  16. print_expr_stmt ::= expr PRINT_EXPR
  17. raise_stmt2 ::= expr expr RAISE_EXCEPTION
  18. star_args ::= RESERVE_FAST UNPACK_VARARG_1 args_store
  19. stmt ::= args
  20. stmt ::= print_expr_stmt
  21. stmt ::= star_args
  22. stmt ::= varargs
  23. varargs ::= RESERVE_FAST UNPACK_VARARG_0 args_store
  24. # Not strictly needed, but tidies up output
  25. stmt ::= doc_junk
  26. doc_junk ::= LOAD_CONST POP_TOP
  27. # Not sure why later Python's omit the COME_FROM
  28. jb_pop14 ::= JUMP_BACK COME_FROM POP_TOP
  29. whileelsestmt ::= SETUP_LOOP testexpr l_stmts_opt
  30. jb_pop14
  31. POP_BLOCK else_suitel COME_FROM
  32. print_items_nl_stmt ::= expr PRINT_ITEM_CONT print_items_opt PRINT_NEWLINE_CONT
  33. # 1.4 doesn't have linenotab, and although this shouldn't
  34. # be a show stopper, our CONTINUE detection is off here.
  35. continue ::= JUMP_BACK
  36. """
  37. def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
  38. super(Python14Parser, self).__init__(debug_parser)
  39. self.customized = {}
  40. def customize_grammar_rules(self, tokens, customize):
  41. super(Python14Parser, self).customize_grammar_rules(tokens, customize)
  42. self.remove_rules("""
  43. whileelsestmt ::= SETUP_LOOP testexpr l_stmts_opt
  44. jb_pop
  45. POP_BLOCK else_suitel COME_FROM
  46. """)
  47. self.check_reduce["doc_junk"] = "tokens"
  48. for i, token in enumerate(tokens):
  49. opname = token.kind
  50. opname_base = opname[:opname.rfind("_")]
  51. if opname_base == "UNPACK_VARARG":
  52. if token.attr > 1:
  53. self.addRule(f"star_args ::= RESERVE_FAST {opname} args_store", nop_func)
  54. def reduce_is_invalid(self, rule, ast, tokens, first, last):
  55. invalid = super(Python14Parser,
  56. self).reduce_is_invalid(rule, ast,
  57. tokens, first, last)
  58. if invalid or tokens is None:
  59. return invalid
  60. if rule[0] == 'doc_junk':
  61. return not isinstance(tokens[first].pattr, str)
  62. class Python14ParserSingle(Python14Parser, PythonParserSingle):
  63. pass
  64. if __name__ == '__main__':
  65. # Check grammar
  66. p = Python14Parser()
  67. p.check_grammar()
  68. p.dump_grammar()
  69. # local variables:
  70. # tab-width: 4