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.1 KiB

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