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.

75 lines
2.2 KiB

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