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.

110 lines
3.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 ..grammar import END
  9. from .lalr_analysis import LALR_Analyzer, Shift, IntParseTable
  10. ###{standalone
  11. class LALR_Parser(object):
  12. def __init__(self, parser_conf, debug=False):
  13. assert all(r.options is None or r.options.priority is None
  14. for r in parser_conf.rules), "LALR doesn't yet support prioritization"
  15. analysis = LALR_Analyzer(parser_conf, debug=debug)
  16. analysis.compute_lookahead()
  17. callbacks = parser_conf.callbacks
  18. self._parse_table = analysis.parse_table
  19. self.parser_conf = parser_conf
  20. self.parser = _Parser(analysis.parse_table, callbacks)
  21. @classmethod
  22. def deserialize(cls, data, memo, callbacks):
  23. inst = cls.__new__(cls)
  24. inst._parse_table = IntParseTable.deserialize(data, memo)
  25. inst.parser = _Parser(inst._parse_table, callbacks)
  26. return inst
  27. def serialize(self, memo):
  28. return self._parse_table.serialize(memo)
  29. def parse(self, *args):
  30. return self.parser.parse(*args)
  31. class _Parser:
  32. def __init__(self, parse_table, callbacks):
  33. self.states = parse_table.states
  34. self.start_states = parse_table.start_states
  35. self.end_states = parse_table.end_states
  36. self.callbacks = callbacks
  37. def parse(self, seq, start, set_state=None):
  38. token = None
  39. stream = iter(seq)
  40. states = self.states
  41. start_state = self.start_states[start]
  42. end_state = self.end_states[start]
  43. state_stack = [start_state]
  44. value_stack = []
  45. if set_state: set_state(start_state)
  46. def get_action(token):
  47. state = state_stack[-1]
  48. try:
  49. return states[state][token.type]
  50. except KeyError:
  51. expected = [s for s in states[state].keys() if s.isupper()]
  52. raise UnexpectedToken(token, expected, state=state)
  53. def reduce(rule):
  54. size = len(rule.expansion)
  55. if size:
  56. s = value_stack[-size:]
  57. del state_stack[-size:]
  58. del value_stack[-size:]
  59. else:
  60. s = []
  61. value = self.callbacks[rule](s)
  62. _action, new_state = states[state_stack[-1]][rule.origin.name]
  63. assert _action is Shift
  64. state_stack.append(new_state)
  65. value_stack.append(value)
  66. # Main LALR-parser loop
  67. for token in stream:
  68. while True:
  69. action, arg = get_action(token)
  70. assert arg != end_state
  71. if action is Shift:
  72. state_stack.append(arg)
  73. value_stack.append(token)
  74. if set_state: set_state(arg)
  75. break # next token
  76. else:
  77. reduce(arg)
  78. token = Token.new_borrow_pos(END, None, token) if token else Token(END, None, 0, 1, 1)
  79. while True:
  80. _action, arg = get_action(token)
  81. if _action is Shift:
  82. if arg == end_state:
  83. val ,= value_stack
  84. return val
  85. state_stack.append(arg)
  86. else:
  87. reduce(arg)
  88. ###}