This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

94 Zeilen
2.9 KiB

  1. """This module implements a LALR(1) Parser
  2. """
  3. # Author: Erez Shinan (2017)
  4. # Email : erezshin@gmail.com
  5. from ..common import ParseError, UnexpectedToken
  6. from .lalr_analysis import LALR_Analyzer, ACTION_SHIFT
  7. class Parser:
  8. def __init__(self, parser_conf):
  9. assert all(o is None or o.priority is None for n,x,a,o in parser_conf.rules), "LALR doesn't yet support prioritization"
  10. self.analysis = analysis = LALR_Analyzer(parser_conf.rules, parser_conf.start)
  11. analysis.compute_lookahead()
  12. callbacks = {rule: getattr(parser_conf.callback, rule.alias or rule.origin, None)
  13. for rule in analysis.rules}
  14. self.parser = _Parser(analysis.states_idx, analysis.init_state_idx, analysis.start_symbol, callbacks)
  15. self.parse = self.parser.parse
  16. class _Parser:
  17. def __init__(self, states, init_state, start_symbol, callbacks):
  18. self.states = states
  19. self.init_state = init_state
  20. self.start_symbol = start_symbol
  21. self.callbacks = callbacks
  22. def parse(self, seq, set_state=None):
  23. i = 0
  24. token = None
  25. stream = iter(seq)
  26. states = self.states
  27. state_stack = [self.init_state]
  28. value_stack = []
  29. if set_state: set_state(self.init_state)
  30. def get_action(key):
  31. state = state_stack[-1]
  32. try:
  33. return states[state][key]
  34. except KeyError:
  35. expected = states[state].keys()
  36. raise UnexpectedToken(token, expected, seq, i)
  37. def reduce(rule, size, end=False):
  38. if size:
  39. s = value_stack[-size:]
  40. del state_stack[-size:]
  41. del value_stack[-size:]
  42. else:
  43. s = []
  44. res = self.callbacks[rule](s)
  45. if end and len(state_stack) == 1 and rule.origin == self.start_symbol:
  46. return res
  47. _action, new_state = get_action(rule.origin)
  48. assert _action == ACTION_SHIFT
  49. state_stack.append(new_state)
  50. value_stack.append(res)
  51. # Main LALR-parser loop
  52. try:
  53. token = next(stream)
  54. i += 1
  55. while True:
  56. action, arg = get_action(token.type)
  57. if action == ACTION_SHIFT:
  58. state_stack.append(arg)
  59. value_stack.append(token)
  60. if set_state: set_state(arg)
  61. token = next(stream)
  62. i += 1
  63. else:
  64. reduce(*arg)
  65. except StopIteration:
  66. pass
  67. while True:
  68. _action, rule = get_action('$end')
  69. assert _action == 'reduce'
  70. res = reduce(*rule, end=True)
  71. if res:
  72. assert state_stack == [self.init_state] and not value_stack, len(state_stack)
  73. return res