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.
 
 

65 lines
1.8 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(['%s(%r)' % (t.type, t.value) for t in seq[i:i+5]])
  21. raise ParseError("Unexpected input %r.\nExpected: %s\nContext: %s" % (key, expected, context))
  22. def reduce(rule):
  23. if rule.expansion:
  24. s = stack[-len(rule.expansion):]
  25. del stack[-len(rule.expansion):]
  26. else:
  27. s = []
  28. res = self.callbacks[rule]([x[0] for x in s])
  29. if rule.origin == 'start':
  30. return res
  31. _action, new_state = get_action(rule.origin)
  32. assert _action == ACTION_SHIFT
  33. stack.append((res, new_state))
  34. # Main LALR-parser loop
  35. while i < len(seq):
  36. action, arg = get_action(seq[i].type)
  37. if action == ACTION_SHIFT:
  38. stack.append((seq[i], arg))
  39. i+= 1
  40. else:
  41. reduce(arg)
  42. while len(stack) > 1:
  43. _action, rule = get_action('$end')
  44. assert _action == 'reduce'
  45. res = reduce(rule)
  46. if res:
  47. break
  48. assert stack == [(None, self.ga.init_state_idx)], len(stack)
  49. return res