This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

94 lines
2.3 KiB

  1. """
  2. Python 3 to Python 2 converter (tree templates)
  3. ===============================================
  4. This example demonstrates how to translate between two trees using tree templates.
  5. It parses Python 3, translates it to a Python 2 AST, and then outputs the result as Python 2 code.
  6. Uses reconstruct_python.py for generating the final Python 2 code.
  7. """
  8. from lark import Lark
  9. from lark.tree_templates import TemplateConf, TemplateTranslator
  10. from lark.indenter import PythonIndenter
  11. from reconstruct_python import PythonReconstructor
  12. #
  13. # 1. Define a Python parser that also accepts template vars in the code (in the form of $var)
  14. #
  15. TEMPLATED_PYTHON = r"""
  16. %import python (single_input, file_input, eval_input, atom, var, stmt, expr, testlist_star_expr, _NEWLINE, _INDENT, _DEDENT, COMMENT, NAME)
  17. %extend atom: TEMPLATE_NAME -> var
  18. TEMPLATE_NAME: "$" NAME
  19. ?template_start: (stmt | testlist_star_expr _NEWLINE)
  20. %ignore /[\t \f]+/ // WS
  21. %ignore /\\[\t \f]*\r?\n/ // LINE_CONT
  22. %ignore COMMENT
  23. """
  24. parser = Lark(TEMPLATED_PYTHON, parser='lalr', start=['single_input', 'file_input', 'eval_input', 'template_start'], postlex=PythonIndenter(), maybe_placeholders=False)
  25. def parse_template(s):
  26. return parser.parse(s + '\n', start='template_start')
  27. def parse_code(s):
  28. return parser.parse(s + '\n', start='file_input')
  29. #
  30. # 2. Define translations using templates (each template code is parsed to a template tree)
  31. #
  32. pytemplate = TemplateConf(parse=parse_template)
  33. translations_3to2 = {
  34. 'yield from $a':
  35. 'for _tmp in $a: yield _tmp',
  36. 'raise $e from $x':
  37. 'raise $e',
  38. '$a / $b':
  39. 'float($a) / $b',
  40. }
  41. translations_3to2 = {pytemplate(k): pytemplate(v) for k, v in translations_3to2.items()}
  42. #
  43. # 3. Translate and reconstruct Python 3 code into valid Python 2 code
  44. #
  45. python_reconstruct = PythonReconstructor(parser)
  46. def translate_py3to2(code):
  47. tree = parse_code(code)
  48. tree = TemplateTranslator(translations_3to2).translate(tree)
  49. return python_reconstruct.reconstruct(tree)
  50. #
  51. # Test Code
  52. #
  53. _TEST_CODE = '''
  54. if a / 2 > 1:
  55. yield from [1,2,3]
  56. else:
  57. raise ValueError(a) from e
  58. '''
  59. def test():
  60. print(_TEST_CODE)
  61. print(' -----> ')
  62. print(translate_py3to2(_TEST_CODE))
  63. if __name__ == '__main__':
  64. test()