Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/lark/parsers/lalr_parser_state.py: 97%
75 statements
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-14 06:19 +0000
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-14 06:19 +0000
1from copy import deepcopy, copy
2from typing import Dict, Any, Generic, List
3from ..lexer import Token, LexerThread
4from ..common import ParserCallbacks
6from .lalr_analysis import Shift, ParseTableBase, StateT
7from lark.exceptions import UnexpectedToken
9###{standalone
11class ParseConf(Generic[StateT]):
12 __slots__ = 'parse_table', 'callbacks', 'start', 'start_state', 'end_state', 'states'
14 parse_table: ParseTableBase[StateT]
15 callbacks: ParserCallbacks
16 start: str
18 start_state: StateT
19 end_state: StateT
20 states: Dict[StateT, Dict[str, tuple]]
22 def __init__(self, parse_table: ParseTableBase[StateT], callbacks: ParserCallbacks, start: str):
23 self.parse_table = parse_table
25 self.start_state = self.parse_table.start_states[start]
26 self.end_state = self.parse_table.end_states[start]
27 self.states = self.parse_table.states
29 self.callbacks = callbacks
30 self.start = start
32class ParserState(Generic[StateT]):
33 __slots__ = 'parse_conf', 'lexer', 'state_stack', 'value_stack'
35 parse_conf: ParseConf[StateT]
36 lexer: LexerThread
37 state_stack: List[StateT]
38 value_stack: list
40 def __init__(self, parse_conf: ParseConf[StateT], lexer: LexerThread, state_stack=None, value_stack=None):
41 self.parse_conf = parse_conf
42 self.lexer = lexer
43 self.state_stack = state_stack or [self.parse_conf.start_state]
44 self.value_stack = value_stack or []
46 @property
47 def position(self) -> StateT:
48 return self.state_stack[-1]
50 # Necessary for match_examples() to work
51 def __eq__(self, other) -> bool:
52 if not isinstance(other, ParserState):
53 return NotImplemented
54 return len(self.state_stack) == len(other.state_stack) and self.position == other.position
56 def __copy__(self):
57 return type(self)(
58 self.parse_conf,
59 self.lexer, # XXX copy
60 copy(self.state_stack),
61 deepcopy(self.value_stack),
62 )
64 def copy(self) -> 'ParserState[StateT]':
65 return copy(self)
67 def feed_token(self, token: Token, is_end=False) -> Any:
68 state_stack = self.state_stack
69 value_stack = self.value_stack
70 states = self.parse_conf.states
71 end_state = self.parse_conf.end_state
72 callbacks = self.parse_conf.callbacks
74 while True:
75 state = state_stack[-1]
76 try:
77 action, arg = states[state][token.type]
78 except KeyError:
79 expected = {s for s in states[state].keys() if s.isupper()}
80 raise UnexpectedToken(token, expected, state=self, interactive_parser=None)
82 assert arg != end_state
84 if action is Shift:
85 # shift once and return
86 assert not is_end
87 state_stack.append(arg)
88 value_stack.append(token if token.type not in callbacks else callbacks[token.type](token))
89 return
90 else:
91 # reduce+shift as many times as necessary
92 rule = arg
93 size = len(rule.expansion)
94 if size:
95 s = value_stack[-size:]
96 del state_stack[-size:]
97 del value_stack[-size:]
98 else:
99 s = []
101 value = callbacks[rule](s) if callbacks else s
103 _action, new_state = states[state_stack[-1]][rule.origin.name]
104 assert _action is Shift
105 state_stack.append(new_state)
106 value_stack.append(value)
108 if is_end and state_stack[-1] == end_state:
109 return value_stack[-1]
110###}