@@ -222,12 +222,15 @@ def _emit(self, type: TokenType, value: str, line: int, column: int = 0) -> None
222222 """Emit a token with the given type and value at the specified line and column."""
223223 self ._tokens .append (Token (type , value , line , column ))
224224
225- def _read_conditional (self , condition : Callable [[str ], bool ], * , or_eof : bool = True ) -> str :
226- """Read until the current character matches the condition.
225+ def _read_conditional (
226+ self , condition : str | Callable [[str ], bool ], * , or_eof : bool = True , invert : bool = False
227+ ) -> str :
228+ """Read while or until the current character matches the condition.
227229
228230 Args:
229231 condition: A function that returns ``True`` to stop.
230232 or_eof: If True, also stop if EOF is reached. If False, EOF will not stop the read and will raise an error.
233+ invert: If True, invert the condition (i.e. read while it matches instead of until it matches).
231234 """
232235 start = self ._pos
233236 while True :
@@ -236,8 +239,13 @@ def _read_conditional(self, condition: Callable[[str], bool], *, or_eof: bool =
236239 self ._assert_not_eof ()
237240 break
238241
239- if condition (self .data [self ._pos ]):
240- break
242+ ch = self .data [self ._pos ]
243+ if isinstance (condition , str ):
244+ if (ch in condition ) != invert :
245+ break
246+ else :
247+ if condition (ch ) != invert :
248+ break
241249
242250 self ._pos += 1
243251
@@ -252,9 +260,6 @@ def _read_until(self, condition: str | Callable[[str], bool], *, or_eof: bool =
252260 condition: Characters to match, or a function that returns ``True`` to stop.
253261 or_eof: If True, also stop if EOF is reached. If False, EOF will not stop the read and will raise an error.
254262 """
255- if isinstance (condition , str ):
256- condition = functools .partial (operator .contains , condition )
257-
258263 return self ._read_conditional (condition , or_eof = or_eof )
259264
260265 def _read_while (self , condition : str | Callable [[str ], bool ], * , or_eof : bool = True ) -> str :
@@ -264,14 +269,7 @@ def _read_while(self, condition: str | Callable[[str], bool], *, or_eof: bool =
264269 condition: Characters to match, or a function that returns ``True`` to continue.
265270 or_eof: If True, also stop if EOF is reached. If False, EOF will not stop the read and will raise an error.
266271 """
267-
268- def _invert (condition : Callable [[str ], bool ], ch : str ) -> bool :
269- return not condition (ch )
270-
271- if isinstance (condition , str ):
272- condition = functools .partial (operator .contains , condition )
273-
274- return self ._read_conditional (functools .partial (_invert , condition ), or_eof = or_eof )
272+ return self ._read_conditional (condition , or_eof = or_eof , invert = True )
275273
276274 def _skip_whitespace (self ) -> None :
277275 """Skip whitespace characters."""
0 commit comments