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.

85 lines
2.4 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. stack = [(None, self.ga.init_state_idx)]
  22. i = 0
  23. res = None
  24. def get_action(key):
  25. state = stack[-1][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):
  37. if rule.expansion:
  38. s = stack[-len(rule.expansion):]
  39. del stack[-len(rule.expansion):]
  40. else:
  41. s = []
  42. res = self.callbacks[rule]([x[0] for x in s])
  43. if rule.origin == self.ga.start_symbol and len(stack) == 1:
  44. return res
  45. _action, new_state = get_action(rule.origin)
  46. assert _action == ACTION_SHIFT
  47. stack.append((res, new_state))
  48. # Main LALR-parser loop
  49. while i < len(seq):
  50. action, arg = get_action(seq[i].type)
  51. if action == ACTION_SHIFT:
  52. stack.append((seq[i], arg))
  53. i+= 1
  54. else:
  55. reduce(arg)
  56. while stack:
  57. _action, rule = get_action('$end')
  58. assert _action == 'reduce'
  59. res = reduce(rule)
  60. if res:
  61. break
  62. assert stack == [(None, self.ga.init_state_idx)], len(stack)
  63. return res