This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

129 rindas
4.4 KiB

  1. from .common import is_terminal, GrammarError
  2. from .utils import suppress
  3. from .lexer import Token
  4. class Callback(object):
  5. pass
  6. def create_expand1_tree_builder_function(tree_builder):
  7. def expand1(children):
  8. if len(children) == 1:
  9. return children[0]
  10. else:
  11. return tree_builder(children)
  12. return expand1
  13. def create_token_wrapper(tree_builder, name):
  14. def join_children(children):
  15. children = [Token(name, ''.join(children))]
  16. return tree_builder(children)
  17. return join_children
  18. def create_rule_handler(expansion, usermethod, keep_all_tokens, filter_out):
  19. # if not keep_all_tokens:
  20. to_include = [(i, not is_terminal(sym) and sym.startswith('_'))
  21. for i, sym in enumerate(expansion)
  22. if keep_all_tokens
  23. or not ((is_terminal(sym) and sym.startswith('_')) or sym in filter_out)
  24. ]
  25. if len(to_include) < len(expansion) or any(to_expand for i, to_expand in to_include):
  26. def _build_ast(match):
  27. children = []
  28. for i, to_expand in to_include:
  29. if to_expand:
  30. children += match[i].children
  31. else:
  32. children.append(match[i])
  33. return usermethod(children)
  34. return _build_ast
  35. # else, if no filtering required..
  36. return usermethod
  37. def propagate_positions_wrapper(f):
  38. def _f(args):
  39. res = f(args)
  40. if args:
  41. for a in args:
  42. with suppress(AttributeError):
  43. res.line = a.line
  44. res.column = a.column
  45. break
  46. for a in reversed(args):
  47. with suppress(AttributeError):
  48. res.end_line = a.end_line
  49. res.end_col = a.end_col
  50. break
  51. return res
  52. return _f
  53. class ParseTreeBuilder:
  54. def __init__(self, tree_class, propagate_positions=False, keep_all_tokens=False):
  55. self.tree_class = tree_class
  56. self.propagate_positions = propagate_positions
  57. self.always_keep_all_tokens = keep_all_tokens
  58. def _create_tree_builder_function(self, name):
  59. tree_class = self.tree_class
  60. def tree_builder_f(children):
  61. return tree_class(name, children)
  62. return tree_builder_f
  63. def create_tree_builder(self, rules, transformer):
  64. callback = Callback()
  65. new_rules = []
  66. filter_out = set()
  67. for origin, (expansions, options) in rules.items():
  68. if options and options.filter_out:
  69. assert origin.startswith('_') # Just to make sure
  70. filter_out.add(origin)
  71. for origin, (expansions, options) in rules.items():
  72. keep_all_tokens = self.always_keep_all_tokens or (options.keep_all_tokens if options else False)
  73. expand1 = options.expand1 if options else False
  74. create_token = options.create_token if options else False
  75. _origin = origin
  76. for expansion, alias in expansions:
  77. if alias and origin.startswith('_'):
  78. raise Exception("Rule %s is marked for expansion (it starts with an underscore) and isn't allowed to have aliases (alias=%s)" % (origin, alias))
  79. try:
  80. f = transformer._get_func(alias or _origin)
  81. except AttributeError:
  82. if alias:
  83. f = self._create_tree_builder_function(alias)
  84. else:
  85. f = self._create_tree_builder_function(_origin)
  86. if expand1:
  87. f = create_expand1_tree_builder_function(f)
  88. if create_token:
  89. f = create_token_wrapper(f, create_token)
  90. alias_handler = create_rule_handler(expansion, f, keep_all_tokens, filter_out)
  91. if self.propagate_positions:
  92. alias_handler = propagate_positions_wrapper(alias_handler)
  93. callback_name = 'autoalias_%s_%s' % (_origin, '_'.join(expansion))
  94. if hasattr(callback, callback_name):
  95. raise GrammarError("Rule expansion '%s' already exists in rule %s" % (' '.join(expansion), origin))
  96. setattr(callback, callback_name, alias_handler)
  97. new_rules.append(( _origin, expansion, callback_name, options ))
  98. return new_rules, callback