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.

72 lines
1.9 KiB

  1. """
  2. Reconstruct Python
  3. ==================
  4. Demonstrates how Lark's experimental text-reconstruction feature can recreate
  5. functional Python code from its parse-tree, using just the correct grammar and
  6. a small formatter.
  7. """
  8. from lark import Token
  9. from lark.reconstruct import Reconstructor
  10. from python_parser import python_parser3
  11. SPACE_AFTER = set(',+-*/~@<>="|:')
  12. SPACE_BEFORE = (SPACE_AFTER - set(',:')) | set('\'')
  13. def special(sym):
  14. return Token('SPECIAL', sym.name)
  15. def postproc(items):
  16. stack = ['\n']
  17. actions = []
  18. last_was_whitespace = True
  19. for item in items:
  20. if isinstance(item, Token) and item.type == 'SPECIAL':
  21. actions.append(item.value)
  22. else:
  23. if actions:
  24. assert actions[0] == '_NEWLINE' and '_NEWLINE' not in actions[1:], actions
  25. for a in actions[1:]:
  26. if a == '_INDENT':
  27. stack.append(stack[-1] + ' ' * 4)
  28. else:
  29. assert a == '_DEDENT'
  30. stack.pop()
  31. actions.clear()
  32. yield stack[-1]
  33. last_was_whitespace = True
  34. if not last_was_whitespace:
  35. if item[0] in SPACE_BEFORE:
  36. yield ' '
  37. yield item
  38. last_was_whitespace = item[-1].isspace()
  39. if not last_was_whitespace:
  40. if item[-1] in SPACE_AFTER:
  41. yield ' '
  42. last_was_whitespace = True
  43. yield "\n"
  44. python_reconstruct = Reconstructor(python_parser3, {'_NEWLINE': special, '_DEDENT': special, '_INDENT': special})
  45. def test():
  46. self_contents = open(__file__).read()
  47. tree = python_parser3.parse(self_contents+'\n')
  48. output = python_reconstruct.reconstruct(tree, postproc)
  49. tree_new = python_parser3.parse(output)
  50. assert tree == tree_new
  51. print(output)
  52. if __name__ == '__main__':
  53. test()