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
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, stream, set_state=False): # XXX no set_state
  10. stream = iter(stream)
  11. states_idx = self.analysis.states_idx
  12. state_stack = [self.analysis.init_state_idx]
  13. value_stack = []
  14. def get_action(key):
  15. state = state_stack[-1]
  16. try:
  17. return states_idx[state][key]
  18. except KeyError:
  19. expected = states_idx[state].keys()
  20. raise UnexpectedToken(token, expected, [], 0)
  21. def reduce(rule, size):
  22. if size:
  23. s = value_stack[-size:]
  24. del state_stack[-size:]
  25. del value_stack[-size:]
  26. else:
  27. s = []
  28. res = self.callbacks[rule](s)
  29. if len(state_stack) == 1 and rule.origin == self.analysis.start_symbol:
  30. return res
  31. _action, new_state = get_action(rule.origin)
  32. assert _action == ACTION_SHIFT
  33. state_stack.append(new_state)
  34. value_stack.append(res)
  35. # Main LALR-parser loop
  36. try:
  37. token = next(stream)
  38. while True:
  39. action, arg = get_action(token.type)
  40. if action == ACTION_SHIFT:
  41. state_stack.append(arg)
  42. value_stack.append(token)
  43. if set_state: self.state = arg
  44. token = next(stream)
  45. else:
  46. reduce(*arg)
  47. except StopIteration:
  48. pass
  49. while True:
  50. _action, rule = get_action('$end')
  51. assert _action == 'reduce'
  52. res = reduce(*rule)
  53. if res:
  54. assert state_stack == [self.analysis.init_state_idx] and not value_stack, len(state_stack)
  55. return res