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.

77 lines
2.3 KiB

  1. from ..common import ParseError, UnexpectedToken
  2. from .lalr_analysis import LALR_Analyzer, ACTION_SHIFT
  3. class Parser(object):
  4. def __init__(self, parser_conf):
  5. self.analysis = LALR_Analyzer(parser_conf.rules, parser_conf.start)
  6. self.analysis.compute_lookahead()
  7. self.callbacks = {rule: getattr(parser_conf.callback, rule.alias or rule.origin, None)
  8. for rule in self.analysis.rules}
  9. def parse(self, seq, set_state=None):
  10. i = 0
  11. stream = iter(seq)
  12. states_idx = self.analysis.states_idx
  13. state_stack = [self.analysis.init_state_idx]
  14. value_stack = []
  15. if set_state: set_state(self.analysis.init_state_idx)
  16. def get_action(key):
  17. state = state_stack[-1]
  18. try:
  19. return states_idx[state][key]
  20. except KeyError:
  21. expected = states_idx[state].keys()
  22. raise UnexpectedToken(token, expected, seq, i)
  23. def reduce(rule, size):
  24. if size:
  25. s = value_stack[-size:]
  26. del state_stack[-size:]
  27. del value_stack[-size:]
  28. else:
  29. s = []
  30. res = self.callbacks[rule](s)
  31. if len(state_stack) == 1 and rule.origin == self.analysis.start_symbol:
  32. return res
  33. _action, new_state = get_action(rule.origin)
  34. assert _action == ACTION_SHIFT
  35. state_stack.append(new_state)
  36. value_stack.append(res)
  37. # Main LALR-parser loop
  38. try:
  39. token = next(stream)
  40. i += 1
  41. while True:
  42. action, arg = get_action(token.type)
  43. if action == ACTION_SHIFT:
  44. state_stack.append(arg)
  45. value_stack.append(token)
  46. if set_state: set_state(arg)
  47. token = next(stream)
  48. i += 1
  49. else:
  50. reduce(*arg)
  51. except StopIteration:
  52. pass
  53. while True:
  54. _action, rule = get_action('$end')
  55. assert _action == 'reduce'
  56. res = reduce(*rule)
  57. if res:
  58. assert state_stack == [self.analysis.init_state_idx] and not value_stack, len(state_stack)
  59. return res