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.

169 lines
5.4 KiB

  1. """This module implements a LALR(1) Parser
  2. """
  3. # Author: Erez Shinan (2017)
  4. # Email : erezshin@gmail.com
  5. from ..exceptions import UnexpectedToken
  6. from ..lexer import Token
  7. from ..utils import Enumerator, Serialize
  8. from .lalr_analysis import LALR_Analyzer, Shift, Reduce, IntParseTable
  9. ###{standalone
  10. class LALR_Parser(object):
  11. def __init__(self, parser_conf, debug=False):
  12. assert all(r.options.priority is None for r in parser_conf.rules), "LALR doesn't yet support prioritization"
  13. analysis = LALR_Analyzer(parser_conf, debug=debug)
  14. analysis.compute_lalr()
  15. callbacks = parser_conf.callbacks
  16. self._parse_table = analysis.parse_table
  17. self.parser_conf = parser_conf
  18. self.parser = _Parser(analysis.parse_table, callbacks, debug)
  19. @classmethod
  20. def deserialize(cls, data, memo, callbacks):
  21. inst = cls.__new__(cls)
  22. inst._parse_table = IntParseTable.deserialize(data, memo)
  23. inst.parser = _Parser(inst._parse_table, callbacks)
  24. return inst
  25. def serialize(self, memo):
  26. return self._parse_table.serialize(memo)
  27. def parse(self, *args):
  28. return self.parser.parse(*args)
  29. class _Parser:
  30. def __init__(self, parse_table, callbacks, debug=False):
  31. self.parse_table = parse_table
  32. self.callbacks = callbacks
  33. self.debug = debug
  34. def parse(self, seq, start, set_state=None, value_stack=None, state_stack=None):
  35. token = None
  36. stream = iter(seq)
  37. states = self.parse_table.states
  38. start_state = self.parse_table.start_states[start]
  39. end_state = self.parse_table.end_states[start]
  40. state_stack = state_stack or [start_state]
  41. value_stack = value_stack or []
  42. if set_state: set_state(start_state)
  43. def get_action(token):
  44. state = state_stack[-1]
  45. try:
  46. return states[state][token.type]
  47. except KeyError:
  48. expected = [s for s in states[state].keys() if s.isupper()]
  49. raise UnexpectedToken(token, expected, state=state, puppet=_ParserPuppet(self, state_stack, value_stack, start, stream, set_state))
  50. def reduce(rule):
  51. size = len(rule.expansion)
  52. if size:
  53. s = value_stack[-size:]
  54. del state_stack[-size:]
  55. del value_stack[-size:]
  56. else:
  57. s = []
  58. value = self.callbacks[rule](s)
  59. _action, new_state = states[state_stack[-1]][rule.origin.name]
  60. assert _action is Shift
  61. state_stack.append(new_state)
  62. value_stack.append(value)
  63. # Main LALR-parser loop
  64. try:
  65. for token in stream:
  66. while True:
  67. action, arg = get_action(token)
  68. assert arg != end_state
  69. if action is Shift:
  70. state_stack.append(arg)
  71. value_stack.append(token)
  72. if set_state: set_state(arg)
  73. break # next token
  74. else:
  75. reduce(arg)
  76. except Exception as e:
  77. if self.debug:
  78. print("")
  79. print("STATE STACK DUMP")
  80. print("----------------")
  81. for i, s in enumerate(state_stack):
  82. print('%d)' % i , s)
  83. print("")
  84. raise
  85. token = Token.new_borrow_pos('$END', '', token) if token else Token('$END', '', 0, 1, 1)
  86. while True:
  87. _action, arg = get_action(token)
  88. assert(_action is Reduce)
  89. reduce(arg)
  90. if state_stack[-1] == end_state:
  91. return value_stack[-1]
  92. ###}
  93. class _ParserPuppet:
  94. def __init__(self, parser, state_stack, value_stack, start, stream, set_state):
  95. self.parser = parser
  96. self._state_stack = state_stack
  97. self._value_stack = value_stack
  98. self._start = start
  99. self._stream = stream
  100. self._set_state = set_state
  101. def feed_token(self, token):
  102. end_state = self.parser.parse_table.end_states[self._start]
  103. state_stack = self._state_stack
  104. value_stack = self._value_stack
  105. state = state_stack[-1]
  106. action, arg = self.parser.parse_table.states[state][token.type]
  107. assert arg != end_state
  108. while action is Reduce:
  109. rule = arg
  110. size = len(rule.expansion)
  111. if size:
  112. s = value_stack[-size:]
  113. del state_stack[-size:]
  114. del value_stack[-size:]
  115. else:
  116. s = []
  117. value = self.parser.callbacks[rule](s)
  118. _action, new_state = self.parser.parse_table.states[state_stack[-1]][rule.origin.name]
  119. assert _action is Shift
  120. state_stack.append(new_state)
  121. value_stack.append(value)
  122. if state_stack[-1] == end_state:
  123. return value_stack[-1]
  124. state = state_stack[-1]
  125. action, arg = self.parser.parse_table.states[state][token.type]
  126. assert arg != end_state
  127. assert action is Shift
  128. state_stack.append(arg)
  129. value_stack.append(token)
  130. def choices(self):
  131. return self.parser.parse_table.states[self._state_stack[-1]]
  132. def resume_parse(self):
  133. return self.parser.parse(self._stream, self._start, self._set_state, self._value_stack, self._state_stack)