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.

87 lines
2.5 KiB

  1. from .lalr_analysis import ACTION_SHIFT
  2. from ..common import ParseError
  3. class UnexpectedToken(ParseError):
  4. def __init__(self, token, expected, seq, index):
  5. self.token = token
  6. self.expected = expected
  7. self.line = getattr(token, 'line', '?')
  8. self.column = getattr(token, 'column', '?')
  9. context = ' '.join(['%r(%s)' % (t.value, t.type) for t in seq[index:index+5]])
  10. message = ("Unexpected input %r at line %s, column %s.\n"
  11. "Expected: %s\n"
  12. "Context: %s" % (token.value, self.line, self.column, expected, context))
  13. super(ParseError, self).__init__(message)
  14. class Parser(object):
  15. def __init__(self, ga, callback):
  16. self.ga = ga
  17. self.callbacks = {rule: getattr(callback, rule.alias or rule.origin, None)
  18. for rule in ga.rules}
  19. def parse(self, seq):
  20. states_idx = self.ga.states_idx
  21. state_stack = [self.ga.init_state_idx]
  22. value_stack = []
  23. i = 0
  24. def get_action(key):
  25. state = state_stack[-1]
  26. try:
  27. return states_idx[state][key]
  28. except KeyError:
  29. expected = states_idx[state].keys()
  30. try:
  31. token = seq[i]
  32. except IndexError:
  33. assert key == '$end'
  34. token = seq[-1]
  35. raise UnexpectedToken(token, expected, seq, i)
  36. def reduce(rule, size):
  37. if size:
  38. s = value_stack[-size:]
  39. del state_stack[-size:]
  40. del value_stack[-size:]
  41. else:
  42. s = []
  43. res = self.callbacks[rule](s)
  44. if len(state_stack) == 1 and rule.origin == self.ga.start_symbol:
  45. return res
  46. _action, new_state = get_action(rule.origin)
  47. assert _action == ACTION_SHIFT
  48. state_stack.append(new_state)
  49. value_stack.append(res)
  50. # Main LALR-parser loop
  51. while i < len(seq):
  52. action, arg = get_action(seq[i].type)
  53. if action == ACTION_SHIFT:
  54. state_stack.append(arg)
  55. value_stack.append(seq[i])
  56. i+= 1
  57. else:
  58. reduce(*arg)
  59. while True:
  60. _action, rule = get_action('$end')
  61. assert _action == 'reduce'
  62. res = reduce(*rule)
  63. if res:
  64. assert state_stack == [self.ga.init_state_idx] and not value_stack, len(state_stack)
  65. return res