This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

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