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.
 
 

94 line
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