lalr_parser_state.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. from copy import deepcopy, copy
  2. from typing import Dict, Any, Generic, List
  3. from ..lexer import Token, LexerThread
  4. from ..common import ParserCallbacks
  5. from .lalr_analysis import Shift, ParseTableBase, StateT
  6. from lark.exceptions import UnexpectedToken
  7. ###{standalone
  8. class ParseConf(Generic[StateT]):
  9. __slots__ = 'parse_table', 'callbacks', 'start', 'start_state', 'end_state', 'states'
  10. parse_table: ParseTableBase[StateT]
  11. callbacks: ParserCallbacks
  12. start: str
  13. start_state: StateT
  14. end_state: StateT
  15. states: Dict[StateT, Dict[str, tuple]]
  16. def __init__(self, parse_table: ParseTableBase[StateT], callbacks: ParserCallbacks, start: str):
  17. self.parse_table = parse_table
  18. self.start_state = self.parse_table.start_states[start]
  19. self.end_state = self.parse_table.end_states[start]
  20. self.states = self.parse_table.states
  21. self.callbacks = callbacks
  22. self.start = start
  23. class ParserState(Generic[StateT]):
  24. __slots__ = 'parse_conf', 'lexer', 'state_stack', 'value_stack'
  25. parse_conf: ParseConf[StateT]
  26. lexer: LexerThread
  27. state_stack: List[StateT]
  28. value_stack: list
  29. def __init__(self, parse_conf: ParseConf[StateT], lexer: LexerThread, state_stack=None, value_stack=None):
  30. self.parse_conf = parse_conf
  31. self.lexer = lexer
  32. self.state_stack = state_stack or [self.parse_conf.start_state]
  33. self.value_stack = value_stack or []
  34. @property
  35. def position(self) -> StateT:
  36. return self.state_stack[-1]
  37. # Necessary for match_examples() to work
  38. def __eq__(self, other) -> bool:
  39. if not isinstance(other, ParserState):
  40. return NotImplemented
  41. return len(self.state_stack) == len(other.state_stack) and self.position == other.position
  42. def __copy__(self):
  43. return self.copy()
  44. def copy(self, deepcopy_values=True) -> 'ParserState[StateT]':
  45. return type(self)(
  46. self.parse_conf,
  47. self.lexer, # XXX copy
  48. copy(self.state_stack),
  49. deepcopy(self.value_stack) if deepcopy_values else copy(self.value_stack),
  50. )
  51. def feed_token(self, token: Token, is_end=False) -> Any:
  52. state_stack = self.state_stack
  53. value_stack = self.value_stack
  54. states = self.parse_conf.states
  55. end_state = self.parse_conf.end_state
  56. callbacks = self.parse_conf.callbacks
  57. while True:
  58. state = state_stack[-1]
  59. try:
  60. action, arg = states[state][token.type]
  61. except KeyError:
  62. expected = {s for s in states[state].keys() if s.isupper()}
  63. raise UnexpectedToken(token, expected, state=self, interactive_parser=None)
  64. assert arg != end_state
  65. if action is Shift:
  66. # shift once and return
  67. assert not is_end
  68. state_stack.append(arg)
  69. value_stack.append(token if token.type not in callbacks else callbacks[token.type](token))
  70. return
  71. else:
  72. # reduce+shift as many times as necessary
  73. rule = arg
  74. size = len(rule.expansion)
  75. if size:
  76. s = value_stack[-size:]
  77. del state_stack[-size:]
  78. del value_stack[-size:]
  79. else:
  80. s = []
  81. value = callbacks[rule](s) if callbacks else s
  82. _action, new_state = states[state_stack[-1]][rule.origin.name]
  83. assert _action is Shift
  84. state_stack.append(new_state)
  85. value_stack.append(value)
  86. if is_end and state_stack[-1] == end_state:
  87. return value_stack[-1]
  88. ###}