omlish 0.0.0.dev104__py3-none-any.whl → 0.0.0.dev106__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,13 +5,18 @@ import json
5
5
  import typing as ta
6
6
 
7
7
  from ... import lang
8
+ from . import consts
8
9
 
9
10
 
10
11
  I = ta.TypeVar('I')
12
+ Scalar: ta.TypeAlias = bool | int | float | str | None
11
13
 
14
+ SCALAR_TYPES: tuple[type, ...] = (bool, int, float, str, type(None))
12
15
 
13
- class JsonRendererOut(ta.Protocol):
14
- def write(self, s: str) -> ta.Any: ...
16
+ MULTILINE_SEPARATORS = consts.Separators(',', ': ')
17
+
18
+
19
+ ##
15
20
 
16
21
 
17
22
  class AbstractJsonRenderer(lang.Abstract, ta.Generic[I]):
@@ -21,33 +26,33 @@ class AbstractJsonRenderer(lang.Abstract, ta.Generic[I]):
21
26
 
22
27
  def __init__(
23
28
  self,
24
- out: JsonRendererOut,
25
- *,
26
29
  indent: int | str | None = None,
27
30
  separators: tuple[str, str] | None = None,
28
31
  sort_keys: bool = False,
29
32
  style: ta.Callable[[ta.Any, State], tuple[str, str]] | None = None,
33
+ ensure_ascii: bool = True,
30
34
  ) -> None:
31
35
  super().__init__()
32
36
 
33
- self._out = out
34
37
  self._sort_keys = sort_keys
35
38
  self._style = style
39
+ self._ensure_ascii = ensure_ascii
36
40
 
37
41
  if isinstance(indent, (str, int)):
38
42
  self._indent = (' ' * indent) if isinstance(indent, int) else indent
39
43
  self._endl = '\n'
40
44
  if separators is None:
41
- separators = (',', ': ')
45
+ separators = MULTILINE_SEPARATORS
42
46
  elif indent is None:
43
47
  self._indent = self._endl = ''
44
48
  if separators is None:
45
- separators = (', ', ': ')
49
+ separators = consts.PRETTY_SEPARATORS
46
50
  else:
47
51
  raise TypeError(indent)
48
52
  self._comma, self._colon = separators
49
53
 
50
54
  self._level = 0
55
+ self._indent_cache: dict[int, str] = {}
51
56
 
52
57
  _literals: ta.ClassVar[ta.Mapping[ta.Any, str]] = {
53
58
  True: 'true',
@@ -55,28 +60,62 @@ class AbstractJsonRenderer(lang.Abstract, ta.Generic[I]):
55
60
  None: 'null',
56
61
  }
57
62
 
58
- def _write(self, s: str) -> None:
59
- if s:
60
- self._out.write(s)
63
+ def _get_indent(self) -> str:
64
+ if not self._indent:
65
+ return ''
61
66
 
62
- def _write_indent(self) -> None:
63
- if self._indent:
64
- self._write(self._endl)
65
- if self._level:
66
- self._write(self._indent * self._level)
67
+ if not self._level:
68
+ return self._endl
67
69
 
70
+ try:
71
+ return self._indent_cache[self._level]
72
+ except KeyError:
73
+ pass
74
+
75
+ ret = self._endl + (self._indent * self._level)
76
+ self._indent_cache[self._level] = ret
77
+ return ret
78
+
79
+ def _format_scalar(self, o: Scalar) -> str:
80
+ if o is None or isinstance(o, bool):
81
+ return self._literals[o]
82
+
83
+ elif isinstance(o, (str, int, float)):
84
+ return json.dumps(o, ensure_ascii=self._ensure_ascii)
85
+
86
+ else:
87
+ raise TypeError(o)
88
+
89
+ @classmethod
68
90
  @abc.abstractmethod
69
- def render(self, i: I) -> None:
91
+ def render_str(cls, i: I, /, **kwargs: ta.Any) -> str:
70
92
  raise NotImplementedError
71
93
 
72
- @classmethod
73
- def render_str(cls, i: I, **kwargs: ta.Any) -> str:
74
- out = io.StringIO()
75
- cls(out, **kwargs).render(i)
76
- return out.getvalue()
94
+
95
+ ##
96
+
97
+
98
+ class JsonRendererOut(ta.Protocol):
99
+ def write(self, s: str) -> ta.Any: ...
77
100
 
78
101
 
79
102
  class JsonRenderer(AbstractJsonRenderer[ta.Any]):
103
+ def __init__(
104
+ self,
105
+ out: JsonRendererOut,
106
+ **kwargs: ta.Any,
107
+ ) -> None:
108
+ super().__init__(**kwargs)
109
+
110
+ self._out = out
111
+
112
+ def _write(self, s: str) -> None:
113
+ if s:
114
+ self._out.write(s)
115
+
116
+ def _write_indent(self) -> None:
117
+ self._write(self._get_indent())
118
+
80
119
  def _render(
81
120
  self,
82
121
  o: ta.Any,
@@ -88,11 +127,8 @@ class JsonRenderer(AbstractJsonRenderer[ta.Any]):
88
127
  else:
89
128
  post = None
90
129
 
91
- if o is None or isinstance(o, bool):
92
- self._write(self._literals[o])
93
-
94
- elif isinstance(o, (str, int, float)):
95
- self._write(json.dumps(o))
130
+ if isinstance(o, SCALAR_TYPES):
131
+ self._write(self._format_scalar(o)) # type: ignore
96
132
 
97
133
  elif isinstance(o, ta.Mapping):
98
134
  self._write('{')
@@ -133,3 +169,9 @@ class JsonRenderer(AbstractJsonRenderer[ta.Any]):
133
169
 
134
170
  def render(self, o: ta.Any) -> None:
135
171
  self._render(o)
172
+
173
+ @classmethod
174
+ def render_str(cls, i: ta.Any, /, **kwargs: ta.Any) -> str:
175
+ out = io.StringIO()
176
+ cls(out, **kwargs).render(i)
177
+ return out.getvalue()
@@ -36,7 +36,7 @@ class JsonObjectBuilder:
36
36
  if self._stack:
37
37
  raise self.StateError
38
38
 
39
- def _emit_value(self, v):
39
+ def _emit_value(self, v: ta.Any) -> ta.Iterable[ta.Any]:
40
40
  if not (stk := self._stack):
41
41
  return (v,)
42
42
 
@@ -60,7 +60,7 @@ class JsonObjectBuilder:
60
60
  else:
61
61
  raise self.StateError
62
62
 
63
- def __call__(self, e: JsonStreamParserEvent) -> ta.Any:
63
+ def __call__(self, e: JsonStreamParserEvent) -> ta.Iterable[ta.Any]:
64
64
  stk = self._stack
65
65
 
66
66
  #
@@ -1,8 +1,8 @@
1
- import json
1
+ import io
2
2
  import typing as ta
3
3
 
4
+ from ..render import SCALAR_TYPES
4
5
  from ..render import AbstractJsonRenderer
5
- from ..render import JsonRendererOut
6
6
  from .parse import BeginArray
7
7
  from .parse import BeginObject
8
8
  from .parse import EndArray
@@ -17,7 +17,6 @@ from .parse import Key
17
17
  class StreamJsonRenderer(AbstractJsonRenderer[ta.Iterable[JsonStreamParserEvent]]):
18
18
  def __init__(
19
19
  self,
20
- out: JsonRendererOut,
21
20
  *,
22
21
  delimiter: str = '',
23
22
  sort_keys: bool = False,
@@ -28,7 +27,7 @@ class StreamJsonRenderer(AbstractJsonRenderer[ta.Iterable[JsonStreamParserEvent]
28
27
 
29
28
  self._delimiter = delimiter
30
29
 
31
- super().__init__(out, **kwargs)
30
+ super().__init__(**kwargs)
32
31
 
33
32
  self._stack: list[tuple[ta.Literal['OBJECT', 'ARRAY'], int]] = []
34
33
  self._need_delimit = False
@@ -37,41 +36,38 @@ class StreamJsonRenderer(AbstractJsonRenderer[ta.Iterable[JsonStreamParserEvent]
37
36
  self,
38
37
  o: ta.Any,
39
38
  state: AbstractJsonRenderer.State = AbstractJsonRenderer.State.VALUE,
40
- ) -> None:
39
+ ) -> ta.Generator[str, None, None]:
41
40
  if self._style is not None:
42
41
  pre, post = self._style(o, state)
43
- self._write(pre)
42
+ yield pre
44
43
  else:
45
44
  post = None
46
45
 
47
- if o is None or isinstance(o, bool):
48
- self._write(self._literals[o])
49
-
50
- elif isinstance(o, (str, int, float)):
51
- self._write(json.dumps(o))
46
+ if isinstance(o, SCALAR_TYPES):
47
+ yield self._format_scalar(o) # type: ignore
52
48
 
53
49
  else:
54
50
  raise TypeError(o)
55
51
 
56
52
  if post:
57
- self._write(post)
53
+ yield post
58
54
 
59
- def _render(self, e: JsonStreamParserEvent) -> None:
55
+ def _render(self, e: JsonStreamParserEvent) -> ta.Generator[str, None, None]:
60
56
  if self._need_delimit:
61
- self._write(self._delimiter)
57
+ yield self._delimiter
62
58
  self._need_delimit = False
63
59
 
64
60
  if e != EndArray and self._stack and (tt := self._stack[-1])[0] == 'ARRAY':
65
61
  if tt[1]:
66
- self._write(self._comma)
67
- self._write_indent()
62
+ yield self._comma
63
+ yield self._get_indent()
68
64
 
69
65
  self._stack[-1] = ('ARRAY', tt[1] + 1)
70
66
 
71
67
  #
72
68
 
73
69
  if e is None or isinstance(e, (str, int, float, bool)):
74
- self._render_value(e)
70
+ yield from self._render_value(e)
75
71
  if not self._stack:
76
72
  self._need_delimit = True
77
73
 
@@ -79,7 +75,7 @@ class StreamJsonRenderer(AbstractJsonRenderer[ta.Iterable[JsonStreamParserEvent]
79
75
 
80
76
  elif e is BeginObject:
81
77
  self._stack.append(('OBJECT', 0))
82
- self._write('{')
78
+ yield '{'
83
79
  self._level += 1
84
80
 
85
81
  elif isinstance(e, Key):
@@ -87,10 +83,10 @@ class StreamJsonRenderer(AbstractJsonRenderer[ta.Iterable[JsonStreamParserEvent]
87
83
  raise Exception
88
84
 
89
85
  if tt[1]:
90
- self._write(self._comma)
91
- self._write_indent()
92
- self._render_value(e.key, AbstractJsonRenderer.State.KEY)
93
- self._write(self._colon)
86
+ yield self._comma
87
+ yield self._get_indent()
88
+ yield from self._render_value(e.key, AbstractJsonRenderer.State.KEY)
89
+ yield self._colon
94
90
 
95
91
  self._stack.append(('OBJECT', tt[1] + 1))
96
92
 
@@ -100,8 +96,8 @@ class StreamJsonRenderer(AbstractJsonRenderer[ta.Iterable[JsonStreamParserEvent]
100
96
 
101
97
  self._level -= 1
102
98
  if tt[1]:
103
- self._write_indent()
104
- self._write('}')
99
+ yield self._get_indent()
100
+ yield '}'
105
101
  if not self._stack:
106
102
  self._need_delimit = True
107
103
 
@@ -109,7 +105,7 @@ class StreamJsonRenderer(AbstractJsonRenderer[ta.Iterable[JsonStreamParserEvent]
109
105
 
110
106
  elif e is BeginArray:
111
107
  self._stack.append(('ARRAY', 0))
112
- self._write('[')
108
+ yield '['
113
109
  self._level += 1
114
110
 
115
111
  elif e is EndArray:
@@ -118,8 +114,8 @@ class StreamJsonRenderer(AbstractJsonRenderer[ta.Iterable[JsonStreamParserEvent]
118
114
 
119
115
  self._level -= 1
120
116
  if tt[1]:
121
- self._write_indent()
122
- self._write(']')
117
+ yield self._get_indent()
118
+ yield ']'
123
119
  if not self._stack:
124
120
  self._need_delimit = True
125
121
 
@@ -128,6 +124,13 @@ class StreamJsonRenderer(AbstractJsonRenderer[ta.Iterable[JsonStreamParserEvent]
128
124
  else:
129
125
  raise TypeError(e)
130
126
 
131
- def render(self, events: ta.Iterable[JsonStreamParserEvent]) -> None:
127
+ def render(self, events: ta.Iterable[JsonStreamParserEvent]) -> ta.Generator[str, None, None]:
132
128
  for e in events:
133
- self._render(e)
129
+ yield from self._render(e)
130
+
131
+ @classmethod
132
+ def render_str(cls, i: ta.Iterable[JsonStreamParserEvent], /, **kwargs: ta.Any) -> str:
133
+ out = io.StringIO()
134
+ for s in cls(**kwargs).render(i):
135
+ out.write(s)
136
+ return out.getvalue()
omlish/io/trampoline.py CHANGED
@@ -1,7 +1,3 @@
1
- """
2
- TODO:
3
- - https://docs.python.org/3/library/zlib.html#zlib.compressobj
4
- """
5
1
  import abc
6
2
  import contextlib
7
3
  import io
@@ -1,114 +1,119 @@
1
- # AST nodes have this structure:
2
- # {'type': <node type>', children: [], 'value': ''}
1
+ import typing as ta
3
2
 
4
3
 
5
- def arithmetic_unary(operator, expression):
4
+ class Node(ta.TypedDict):
5
+ type: str
6
+ children: list['Node']
7
+ value: ta.NotRequired[ta.Any]
8
+
9
+
10
+ def arithmetic_unary(operator, expression) -> Node:
6
11
  return {'type': 'arithmetic_unary', 'children': [expression], 'value': operator}
7
12
 
8
13
 
9
- def arithmetic(operator, left, right):
14
+ def arithmetic(operator, left, right) -> Node:
10
15
  return {'type': 'arithmetic', 'children': [left, right], 'value': operator}
11
16
 
12
17
 
13
- def assign(name, expr):
18
+ def assign(name, expr) -> Node:
14
19
  return {'type': 'assign', 'children': [expr], 'value': name}
15
20
 
16
21
 
17
- def comparator(name, first, second):
22
+ def comparator(name, first, second) -> Node:
18
23
  return {'type': 'comparator', 'children': [first, second], 'value': name}
19
24
 
20
25
 
21
- def current_node():
26
+ def current_node() -> Node:
22
27
  return {'type': 'current', 'children': []}
23
28
 
24
29
 
25
- def root_node():
30
+ def root_node() -> Node:
26
31
  return {'type': 'root', 'children': []}
27
32
 
28
33
 
29
- def expref(expression):
34
+ def expref(expression) -> Node:
30
35
  return {'type': 'expref', 'children': [expression]}
31
36
 
32
37
 
33
- def function_expression(name, args):
38
+ def function_expression(name, args) -> Node:
34
39
  return {'type': 'function_expression', 'children': args, 'value': name}
35
40
 
36
41
 
37
- def field(name):
42
+ def field(name) -> Node:
38
43
  return {'type': 'field', 'children': [], 'value': name}
39
44
 
40
45
 
41
- def filter_projection(left, right, comparator):
46
+ def filter_projection(left, right, comparator) -> Node:
42
47
  return {'type': 'filter_projection', 'children': [left, right, comparator]}
43
48
 
44
49
 
45
- def flatten(node):
50
+ def flatten(node) -> Node:
46
51
  return {'type': 'flatten', 'children': [node]}
47
52
 
48
53
 
49
- def identity():
54
+ def identity() -> Node:
50
55
  return {'type': 'identity', 'children': []}
51
56
 
52
57
 
53
- def index(index):
58
+ def index(index) -> Node:
54
59
  return {'type': 'index', 'value': index, 'children': []}
55
60
 
56
61
 
57
- def index_expression(children):
62
+ def index_expression(children) -> Node:
58
63
  return {'type': 'index_expression', 'children': children}
59
64
 
60
65
 
61
- def key_val_pair(key_name, node):
66
+ def key_val_pair(key_name, node) -> Node:
62
67
  return {'type': 'key_val_pair', 'children': [node], 'value': key_name}
63
68
 
64
69
 
65
- def let_expression(bindings, expr):
70
+ def let_expression(bindings, expr) -> Node:
66
71
  return {'type': 'let_expression', 'children': [*bindings, expr]}
67
72
 
68
73
 
69
- def literal(literal_value):
74
+ def literal(literal_value) -> Node:
70
75
  return {'type': 'literal', 'value': literal_value, 'children': []}
71
76
 
72
77
 
73
- def multi_select_dict(nodes):
78
+ def multi_select_dict(nodes) -> Node:
74
79
  return {'type': 'multi_select_dict', 'children': nodes}
75
80
 
76
81
 
77
- def multi_select_list(nodes):
82
+ def multi_select_list(nodes) -> Node:
78
83
  return {'type': 'multi_select_list', 'children': nodes}
79
84
 
80
85
 
81
- def or_expression(left, right):
86
+ def or_expression(left, right) -> Node:
82
87
  return {'type': 'or_expression', 'children': [left, right]}
83
88
 
84
89
 
85
- def and_expression(left, right):
90
+ def and_expression(left, right) -> Node:
86
91
  return {'type': 'and_expression', 'children': [left, right]}
87
92
 
88
93
 
89
- def not_expression(expr):
94
+ def not_expression(expr) -> Node:
90
95
  return {'type': 'not_expression', 'children': [expr]}
91
96
 
92
97
 
93
- def pipe(left, right):
98
+ def pipe(left: Node, right: Node) -> Node:
94
99
  return {'type': 'pipe', 'children': [left, right]}
95
100
 
96
101
 
97
- def projection(left, right):
102
+ def projection(left: Node, right: Node) -> Node:
98
103
  return {'type': 'projection', 'children': [left, right]}
99
104
 
100
105
 
101
- def subexpression(children):
106
+ def subexpression(children) -> Node:
102
107
  return {'type': 'subexpression', 'children': children}
103
108
 
104
109
 
105
- def slice(start, end, step): # noqa
110
+ def slice(start, end, step) -> Node: # noqa
106
111
  return {'type': 'slice', 'children': [start, end, step]}
107
112
 
108
113
 
109
- def value_projection(left, right):
114
+ def value_projection(left: Node, right: Node) -> Node:
110
115
  return {'type': 'value_projection', 'children': [left, right]}
111
116
 
112
117
 
113
- def variable_ref(name):
118
+ def variable_ref(name: str) -> Node:
114
119
  return {'type': 'variable_ref', 'children': [], 'value': name}
@@ -1,3 +1,6 @@
1
+ import typing as ta
2
+
3
+
1
4
  class JmespathError(ValueError):
2
5
  pass
3
6
 
@@ -10,15 +13,15 @@ class ParseError(JmespathError):
10
13
  lex_position,
11
14
  token_value,
12
15
  token_type,
13
- msg=_ERROR_MESSAGE,
14
- ):
16
+ msg: str = _ERROR_MESSAGE,
17
+ ) -> None:
15
18
  super().__init__(lex_position, token_value, token_type)
16
19
  self.lex_position = lex_position
17
20
  self.token_value = token_value
18
21
  self.token_type = token_type.upper()
19
22
  self.msg = msg
20
23
  # Whatever catches the ParseError can fill in the full expression
21
- self.expression = None
24
+ self.expression: ta.Any = None
22
25
 
23
26
  def __str__(self):
24
27
  # self.lex_position +1 to account for the starting double quote char.
@@ -46,7 +49,7 @@ class IncompleteExpressionError(ParseError):
46
49
 
47
50
 
48
51
  class LexerError(ParseError):
49
- def __init__(self, lexer_position, lexer_value, message, expression=None):
52
+ def __init__(self, lexer_position, lexer_value, message, expression: ta.Any | None = None):
50
53
  self.lexer_position = lexer_position
51
54
  self.lexer_value = lexer_value
52
55
  self.message = message
@@ -44,6 +44,7 @@ def signature(*arguments):
44
44
  class FunctionRegistry(type):
45
45
  def __init__(cls, name, bases, attrs):
46
46
  cls._populate_function_table()
47
+
47
48
  super().__init__(name, bases, attrs)
48
49
 
49
50
  def _populate_function_table(cls):
@@ -3,8 +3,17 @@ import string
3
3
  import typing as ta
4
4
  import warnings
5
5
 
6
+ from ... import check
6
7
  from .exceptions import EmptyExpressionError
7
8
  from .exceptions import LexerError
9
+ from .visitor import Options
10
+
11
+
12
+ class Token(ta.TypedDict):
13
+ type: str
14
+ value: ta.Any
15
+ start: int
16
+ end: int
8
17
 
9
18
 
10
19
  class Lexer:
@@ -33,10 +42,13 @@ class Lexer:
33
42
  '\u00f7': 'divide',
34
43
  }
35
44
 
36
- def __init__(self):
45
+ def __init__(self) -> None:
46
+ super().__init__()
47
+
37
48
  self._enable_legacy_literals = False
49
+ self._current: str | None = None
38
50
 
39
- def tokenize(self, expression, options=None):
51
+ def tokenize(self, expression: str, options: Options | None = None) -> ta.Generator[Token, None, None]:
40
52
  if options is not None:
41
53
  self._enable_legacy_literals = options.enable_legacy_literals
42
54
 
@@ -205,18 +217,18 @@ class Lexer:
205
217
  'end': self._length,
206
218
  }
207
219
 
208
- def _consume_number(self):
220
+ def _consume_number(self) -> str:
209
221
  start = self._position # noqa
210
222
 
211
- buff = self._current
223
+ buff = check.not_none(self._current)
212
224
  while self._next() in self.VALID_NUMBER:
213
- buff += self._current
225
+ buff += check.not_none(self._current)
214
226
  return buff
215
227
 
216
- def _consume_variable(self):
228
+ def _consume_variable(self) -> Token:
217
229
  start = self._position
218
230
 
219
- buff = self._current
231
+ buff = check.not_none(self._current)
220
232
  self._next()
221
233
  if self._current not in self.START_IDENTIFIER:
222
234
  raise LexerError(
@@ -225,9 +237,9 @@ class Lexer:
225
237
  message=f'Invalid variable starting character {self._current}',
226
238
  )
227
239
 
228
- buff += self._current
240
+ buff += check.not_none(self._current)
229
241
  while self._next() in self.VALID_IDENTIFIER:
230
- buff += self._current
242
+ buff += check.not_none(self._current)
231
243
 
232
244
  return {
233
245
  'type': 'variable',
@@ -236,21 +248,21 @@ class Lexer:
236
248
  'end': start + len(buff),
237
249
  }
238
250
 
239
- def _peek_may_be_valid_unquoted_identifier(self):
251
+ def _peek_may_be_valid_unquoted_identifier(self) -> bool:
240
252
  if (self._position == self._length - 1):
241
253
  return False
242
254
  else:
243
255
  nxt = self._chars[self._position + 1]
244
256
  return nxt in self.START_IDENTIFIER
245
257
 
246
- def _peek_is_next_digit(self):
258
+ def _peek_is_next_digit(self) -> bool:
247
259
  if (self._position == self._length - 1):
248
260
  return False
249
261
  else:
250
262
  nxt = self._chars[self._position + 1]
251
263
  return nxt in self.VALID_NUMBER
252
264
 
253
- def _initialize_for_expression(self, expression):
265
+ def _initialize_for_expression(self, expression: str) -> None:
254
266
  if not expression:
255
267
  raise EmptyExpressionError
256
268
  self._position = 0
@@ -259,7 +271,7 @@ class Lexer:
259
271
  self._current = self._chars[self._position]
260
272
  self._length = len(self._expression)
261
273
 
262
- def _next(self):
274
+ def _next(self) -> str | None:
263
275
  if self._position == self._length - 1:
264
276
  self._current = None
265
277
  else:
@@ -267,7 +279,7 @@ class Lexer:
267
279
  self._current = self._chars[self._position]
268
280
  return self._current
269
281
 
270
- def _consume_until(self, delimiter):
282
+ def _consume_until(self, delimiter: str) -> str:
271
283
  # Consume until the delimiter is reached, allowing for the delimiter to be escaped with "\".
272
284
  start = self._position
273
285
 
@@ -293,12 +305,11 @@ class Lexer:
293
305
  self._next()
294
306
  return buff
295
307
 
296
- def _consume_literal(self):
308
+ def _consume_literal(self) -> Token:
297
309
  start = self._position
298
310
 
299
311
  token = self._consume_until('`')
300
312
  lexeme = token.replace('\\`', '`')
301
- parsed_json = None
302
313
  try:
303
314
  # Assume it is valid JSON and attempt to parse.
304
315
  parsed_json = json.loads(lexeme)
@@ -331,7 +342,7 @@ class Lexer:
331
342
  'end': token_len,
332
343
  }
333
344
 
334
- def _consume_quoted_identifier(self):
345
+ def _consume_quoted_identifier(self) -> Token:
335
346
  start = self._position
336
347
 
337
348
  lexeme = '"' + self._consume_until('"') + '"'
@@ -352,7 +363,7 @@ class Lexer:
352
363
  message=error_message,
353
364
  )
354
365
 
355
- def _consume_raw_string_literal(self):
366
+ def _consume_raw_string_literal(self) -> Token:
356
367
  start = self._position
357
368
 
358
369
  lexeme = self._consume_until("'") \
@@ -367,10 +378,10 @@ class Lexer:
367
378
  'end': token_len,
368
379
  }
369
380
 
370
- def _match_or_else(self, expected, match_type, else_type):
381
+ def _match_or_else(self, expected: str, match_type: str, else_type: str) -> Token:
371
382
  start = self._position
372
383
 
373
- current = self._current
384
+ current = check.not_none(self._current)
374
385
  next_char = self._next()
375
386
  if next_char == expected:
376
387
  self._next()