Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/lark/parsers/lalr_parser.py: 60%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

87 statements  

1"""This module implements a LALR(1) Parser 

2""" 

3# Author: Erez Shinan (2017) 

4# Email : erezshin@gmail.com 

5from typing import Dict, Any, Optional 

6from ..lexer import Token, LexerThread 

7from ..utils import Serialize 

8from ..common import ParserConf, ParserCallbacks 

9 

10from .lalr_analysis import LALR_Analyzer, IntParseTable, ParseTableBase 

11from .lalr_interactive_parser import InteractiveParser 

12from lark.exceptions import UnexpectedCharacters, UnexpectedInput, UnexpectedToken 

13from .lalr_parser_state import ParserState, ParseConf 

14 

15###{standalone 

16 

17class LALR_Parser(Serialize): 

18 def __init__(self, parser_conf: ParserConf, debug: bool=False, strict: bool=False): 

19 analysis = LALR_Analyzer(parser_conf, debug=debug, strict=strict) 

20 analysis.compute_lalr() 

21 callbacks = parser_conf.callbacks 

22 

23 self._parse_table = analysis.parse_table 

24 self.parser_conf = parser_conf 

25 self.parser = _Parser(analysis.parse_table, callbacks, debug) 

26 

27 @classmethod 

28 def deserialize(cls, data, memo, callbacks, debug=False): 

29 inst = cls.__new__(cls) 

30 inst._parse_table = IntParseTable.deserialize(data, memo) 

31 inst.parser = _Parser(inst._parse_table, callbacks, debug) 

32 return inst 

33 

34 def serialize(self, memo: Any = None) -> Dict[str, Any]: 

35 return self._parse_table.serialize(memo) 

36 

37 def parse_interactive(self, lexer: LexerThread, start: str): 

38 return self.parser.parse(lexer, start, start_interactive=True) 

39 

40 def parse(self, lexer, start, on_error=None): 

41 try: 

42 return self.parser.parse(lexer, start) 

43 except UnexpectedInput as e: 

44 if on_error is None: 

45 raise 

46 

47 while True: 

48 if isinstance(e, UnexpectedCharacters): 

49 s = e.interactive_parser.lexer_thread.state 

50 p = s.line_ctr.char_pos 

51 

52 if not on_error(e): 

53 raise e 

54 

55 if isinstance(e, UnexpectedCharacters): 

56 # If user didn't change the character position, then we should 

57 if p == s.line_ctr.char_pos: 

58 s.line_ctr.feed(s.text.text[p:p+1]) 

59 

60 try: 

61 return e.interactive_parser.resume_parse() 

62 except UnexpectedToken as e2: 

63 if (isinstance(e, UnexpectedToken) 

64 and e.token.type == e2.token.type == '$END' 

65 and e.interactive_parser == e2.interactive_parser): 

66 # Prevent infinite loop 

67 raise e2 

68 e = e2 

69 except UnexpectedCharacters as e2: 

70 e = e2 

71 

72 

73class _Parser: 

74 parse_table: ParseTableBase 

75 callbacks: ParserCallbacks 

76 debug: bool 

77 

78 def __init__(self, parse_table: ParseTableBase, callbacks: ParserCallbacks, debug: bool=False): 

79 self.parse_table = parse_table 

80 self.callbacks = callbacks 

81 self.debug = debug 

82 

83 def parse(self, lexer: LexerThread, start: str, value_stack=None, state_stack=None, start_interactive=False): 

84 parse_conf = ParseConf(self.parse_table, self.callbacks, start) 

85 parser_state = ParserState(parse_conf, lexer, state_stack, value_stack) 

86 if start_interactive: 

87 return InteractiveParser(self, parser_state, parser_state.lexer) 

88 return self.parse_from_state(parser_state) 

89 

90 

91 def parse_from_state(self, state: ParserState, last_token: Optional[Token]=None): 

92 """Run the main LALR parser loop 

93 

94 Parameters: 

95 state - the initial state. Changed in-place. 

96 last_token - Used only for line information in case of an empty lexer. 

97 """ 

98 try: 

99 token = last_token 

100 for token in state.lexer.lex(state): 

101 assert token is not None 

102 state.feed_token(token) 

103 

104 end_token = Token.new_borrow_pos('$END', '', token) if token else Token('$END', '', 0, 1, 1) 

105 return state.feed_token(end_token, True) 

106 except UnexpectedInput as e: 

107 try: 

108 e.interactive_parser = InteractiveParser(self, state, state.lexer) 

109 except NameError: 

110 pass 

111 raise e 

112 except Exception as e: 

113 if self.debug: 

114 print("") 

115 print("STATE STACK DUMP") 

116 print("----------------") 

117 for i, s in enumerate(state.state_stack): 

118 print('%d)' % i , s) 

119 print("") 

120 

121 raise 

122###}