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.

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