@@ -103,15 +103,8 @@ def desc(self) -> str:
103
103
return f"{ kind } { value !r} " if value else kind
104
104
105
105
106
- def char_at (s , pos ):
107
- try :
108
- return s [pos ]
109
- except IndexError :
110
- return None
111
-
112
-
113
106
def print_char (char ):
114
- return TokenKind . EOF . value if char is None else repr ( char )
107
+ return repr ( char ) if char else TokenKind . EOF . value
115
108
116
109
117
110
_KIND_FOR_PUNCT = {
@@ -191,24 +184,23 @@ def read_token(self, prev: Token) -> Token:
191
184
if pos >= body_length :
192
185
return Token (TokenKind .EOF , body_length , body_length , line , col , prev )
193
186
194
- char = char_at (body , pos )
195
- if char is not None :
196
- kind = _KIND_FOR_PUNCT .get (char )
197
- if kind :
198
- return Token (kind , pos , pos + 1 , line , col , prev )
199
- if char == "#" :
200
- return self .read_comment (pos , line , col , prev )
201
- elif char == "." :
202
- if char == char_at (body , pos + 1 ) == char_at (body , pos + 2 ):
203
- return Token (TokenKind .SPREAD , pos , pos + 3 , line , col , prev )
204
- elif "A" <= char <= "Z" or "a" <= char <= "z" or char == "_" :
205
- return self .read_name (pos , line , col , prev )
206
- elif "0" <= char <= "9" or char == "-" :
207
- return self .read_number (pos , char , line , col , prev )
208
- elif char == '"' :
209
- if char == char_at (body , pos + 1 ) == char_at (body , pos + 2 ):
210
- return self .read_block_string (pos , line , col , prev )
211
- return self .read_string (pos , line , col , prev )
187
+ char = body [pos ]
188
+ kind = _KIND_FOR_PUNCT .get (char )
189
+ if kind :
190
+ return Token (kind , pos , pos + 1 , line , col , prev )
191
+ if char == "#" :
192
+ return self .read_comment (pos , line , col , prev )
193
+ elif char == "." :
194
+ if body [pos + 1 : pos + 3 ] == ".." :
195
+ return Token (TokenKind .SPREAD , pos , pos + 3 , line , col , prev )
196
+ elif "A" <= char <= "Z" or "a" <= char <= "z" or char == "_" :
197
+ return self .read_name (pos , line , col , prev )
198
+ elif "0" <= char <= "9" or char == "-" :
199
+ return self .read_number (pos , char , line , col , prev )
200
+ elif char == '"' :
201
+ if body [pos + 1 : pos + 3 ] == '""' :
202
+ return self .read_block_string (pos , line , col , prev )
203
+ return self .read_string (pos , line , col , prev )
212
204
213
205
raise GraphQLSyntaxError (source , pos , unexpected_character_message (char ))
214
206
@@ -221,15 +213,15 @@ def position_after_whitespace(self, body: str, start_position: int) -> int:
221
213
body_length = len (body )
222
214
position = start_position
223
215
while position < body_length :
224
- char = char_at ( body , position )
225
- if char is not None and char in " \t ,\ufeff " :
216
+ char = body [ position ]
217
+ if char in " \t ,\ufeff " :
226
218
position += 1
227
219
elif char == "\n " :
228
220
position += 1
229
221
self .line += 1
230
222
self .line_start = position
231
223
elif char == "\r " :
232
- if char_at ( body , position + 1 ) == "\n " :
224
+ if body [ position + 1 : position + 2 ] == "\n " :
233
225
position += 2
234
226
else :
235
227
position += 1
@@ -245,8 +237,11 @@ def read_comment(self, start: int, line: int, col: int, prev: Token) -> Token:
245
237
position = start
246
238
while True :
247
239
position += 1
248
- char = char_at (body , position )
249
- if char is None or (char < " " and char != "\t " ):
240
+ try :
241
+ char = body [position ]
242
+ except IndexError :
243
+ break
244
+ if char < " " and char != "\t " :
250
245
break
251
246
return Token (
252
247
TokenKind .COMMENT ,
@@ -271,32 +266,32 @@ def read_number(
271
266
is_float = False
272
267
if char == "-" :
273
268
position += 1
274
- char = char_at ( body , position )
269
+ char = body [ position : position + 1 ]
275
270
if char == "0" :
276
271
position += 1
277
- char = char_at ( body , position )
278
- if char is not None and "0" <= char <= "9" :
272
+ char = body [ position : position + 1 ]
273
+ if "0" <= char <= "9" :
279
274
raise GraphQLSyntaxError (
280
275
source ,
281
276
position ,
282
277
f"Invalid number, unexpected digit after 0: { print_char (char )} ." ,
283
278
)
284
279
else :
285
280
position = self .read_digits (position , char )
286
- char = char_at ( body , position )
281
+ char = body [ position : position + 1 ]
287
282
if char == "." :
288
283
is_float = True
289
284
position += 1
290
- char = char_at ( body , position )
285
+ char = body [ position : position + 1 ]
291
286
position = self .read_digits (position , char )
292
- char = char_at ( body , position )
293
- if char is not None and char in "Ee" :
287
+ char = body [ position : position + 1 ]
288
+ if char and char in "Ee" :
294
289
is_float = True
295
290
position += 1
296
- char = char_at ( body , position )
297
- if char is not None and char in "+-" :
291
+ char = body [ position : position + 1 ]
292
+ if char and char in "+-" :
298
293
position += 1
299
- char = char_at ( body , position )
294
+ char = body [ position : position + 1 ]
300
295
position = self .read_digits (position , char )
301
296
return Token (
302
297
TokenKind .FLOAT if is_float else TokenKind .INT ,
@@ -313,9 +308,9 @@ def read_digits(self, start: int, char: str) -> int:
313
308
source = self .source
314
309
body = source .body
315
310
position = start
316
- while char is not None and "0" <= char <= "9" :
311
+ while "0" <= char <= "9" :
317
312
position += 1
318
- char = char_at ( body , position )
313
+ char = body [ position : position + 1 ]
319
314
if position == start :
320
315
raise GraphQLSyntaxError (
321
316
source ,
@@ -328,14 +323,15 @@ def read_string(self, start: int, line: int, col: int, prev: Token) -> Token:
328
323
"""Read a string token from the source file."""
329
324
source = self .source
330
325
body = source .body
326
+ body_length = len (body )
331
327
position = start + 1
332
328
chunk_start = position
333
329
value : List [str ] = []
334
330
append = value .append
335
331
336
- while position < len ( body ) :
337
- char = char_at ( body , position )
338
- if char is None or char in "\n \r " :
332
+ while position < body_length :
333
+ char = body [ position ]
334
+ if char in "\n \r " :
339
335
break
340
336
if char == '"' :
341
337
append (body [chunk_start :position ])
@@ -357,17 +353,12 @@ def read_string(self, start: int, line: int, col: int, prev: Token) -> Token:
357
353
position += 1
358
354
if char == "\\ " :
359
355
append (body [chunk_start : position - 1 ])
360
- char = char_at ( body , position )
356
+ char = body [ position : position + 1 ]
361
357
escaped = _ESCAPED_CHARS .get (char )
362
358
if escaped :
363
359
value .append (escaped )
364
- elif char == "u" :
365
- code = uni_char_code (
366
- char_at (body , position + 1 ),
367
- char_at (body , position + 2 ),
368
- char_at (body , position + 3 ),
369
- char_at (body , position + 4 ),
370
- )
360
+ elif char == "u" and position + 4 < body_length :
361
+ code = uni_char_code (* body [position + 1 : position + 5 ])
371
362
if code < 0 :
372
363
escape = repr (body [position : position + 5 ])
373
364
escape = escape [:1 ] + "\\ " + escape [1 :]
@@ -394,19 +385,14 @@ def read_string(self, start: int, line: int, col: int, prev: Token) -> Token:
394
385
def read_block_string (self , start : int , line : int , col : int , prev : Token ) -> Token :
395
386
source = self .source
396
387
body = source .body
388
+ body_length = len (body )
397
389
position = start + 3
398
390
chunk_start = position
399
391
raw_value = ""
400
392
401
- while position < len (body ):
402
- char = char_at (body , position )
403
- if char is None :
404
- break
405
- if (
406
- char == '"'
407
- and char_at (body , position + 1 ) == '"'
408
- and char_at (body , position + 2 ) == '"'
409
- ):
393
+ while position < body_length :
394
+ char = body [position ]
395
+ if char == '"' and body [position + 1 : position + 3 ] == '""' :
410
396
raw_value += body [chunk_start :position ]
411
397
return Token (
412
398
TokenKind .BLOCK_STRING ,
@@ -429,18 +415,13 @@ def read_block_string(self, start: int, line: int, col: int, prev: Token) -> Tok
429
415
self .line += 1
430
416
self .line_start = position
431
417
elif char == "\r " :
432
- if char_at ( body , position + 1 ) == "\n " :
418
+ if body [ position + 1 : position + 2 ] == "\n " :
433
419
position += 2
434
420
else :
435
421
position += 1
436
422
self .line += 1
437
423
self .line_start = position
438
- elif (
439
- char == "\\ "
440
- and char_at (body , position + 1 ) == '"'
441
- and char_at (body , position + 2 ) == '"'
442
- and char_at (body , position + 3 ) == '"'
443
- ):
424
+ elif char == "\\ " and body [position + 1 : position + 4 ] == '"""' :
444
425
raw_value += body [chunk_start :position ] + '"""'
445
426
position += 4
446
427
chunk_start = position
@@ -455,8 +436,8 @@ def read_name(self, start: int, line: int, col: int, prev: Token) -> Token:
455
436
body_length = len (body )
456
437
position = start + 1
457
438
while position < body_length :
458
- char = char_at ( body , position )
459
- if char is None or not (
439
+ char = body [ position ]
440
+ if not (
460
441
char == "_"
461
442
or "0" <= char <= "9"
462
443
or "A" <= char <= "Z"
0 commit comments