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.

80 lines
2.4 KiB

  1. # This module provide a LALR puppet, which is used to debugging and error handling
  2. from copy import deepcopy
  3. from .lalr_analysis import Shift, Reduce
  4. class ParserPuppet:
  5. def __init__(self, parser, state_stack, value_stack, start, stream, set_state):
  6. self.parser = parser
  7. self._state_stack = state_stack
  8. self._value_stack = value_stack
  9. self._start = start
  10. self._stream = stream
  11. self._set_state = set_state
  12. self.result = None
  13. def feed_token(self, token):
  14. """Advance the parser state, as if it just recieved `token` from the lexer
  15. """
  16. end_state = self.parser.parse_table.end_states[self._start]
  17. state_stack = self._state_stack
  18. value_stack = self._value_stack
  19. state = state_stack[-1]
  20. action, arg = self.parser.parse_table.states[state][token.type]
  21. assert arg != end_state
  22. while action is Reduce:
  23. rule = arg
  24. size = len(rule.expansion)
  25. if size:
  26. s = value_stack[-size:]
  27. del state_stack[-size:]
  28. del value_stack[-size:]
  29. else:
  30. s = []
  31. value = self.parser.callbacks[rule](s)
  32. _action, new_state = self.parser.parse_table.states[state_stack[-1]][rule.origin.name]
  33. assert _action is Shift
  34. state_stack.append(new_state)
  35. value_stack.append(value)
  36. if state_stack[-1] == end_state:
  37. self.result = value_stack[-1]
  38. return self.result
  39. state = state_stack[-1]
  40. action, arg = self.parser.parse_table.states[state][token.type]
  41. assert arg != end_state
  42. assert action is Shift
  43. state_stack.append(arg)
  44. value_stack.append(token)
  45. def copy(self):
  46. return type(self)(
  47. self.parser,
  48. list(self._state_stack),
  49. deepcopy(self._value_stack),
  50. self._start,
  51. self._stream,
  52. self._set_state,
  53. )
  54. def pretty():
  55. print("Puppet choices:")
  56. for k, v in self.choices.items():
  57. print('\t-', k, '->', v)
  58. print('stack size:', len(self._state_stack))
  59. def choices(self):
  60. return self.parser.parse_table.states[self._state_stack[-1]]
  61. def resume_parse(self):
  62. return self.parser.parse(self._stream, self._start, self._set_state, self._value_stack, self._state_stack)