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.
 
 

62 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, temp=False):
  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. s = stack[-len(rule.expansion):]
  24. del stack[-len(rule.expansion):]
  25. res = self.callbacks[rule]([x[0] for x in s])
  26. if rule.origin == 'start':
  27. return res
  28. _action, new_state = get_action(rule.origin)
  29. assert _action == ACTION_SHIFT
  30. stack.append((res, new_state))
  31. # Main LALR-parser loop
  32. while i < len(seq):
  33. action, arg = get_action(seq[i].type)
  34. if action == ACTION_SHIFT:
  35. stack.append((seq[i], arg))
  36. i+= 1
  37. else:
  38. reduce(arg)
  39. while len(stack) > 1:
  40. _action, rule = get_action('$end')
  41. assert _action == 'reduce'
  42. res = reduce(rule)
  43. if res:
  44. break
  45. assert stack == [(None, self.ga.init_state_idx)], len(stack)
  46. return res