Completed
Pull Request — master (#195)
by Christoffer
17:48
created

TokenReader::createInt()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 1
1
<?php
2
3
namespace Digia\GraphQL\Language;
4
5
use Digia\GraphQL\Error\SyntaxErrorException;
6
7
class TokenReader implements TokenReaderInterface
8
{
9
    protected const PATTERN_COMMENT      = "/#[\u{0009}\u{0020}-\u{FFFF}]*/A";
10
    protected const PATTERN_NAME         = '/[_A-Za-z][_0-9A-Za-z]*/A';
11
    protected const PATTERN_INT          = '/((?!\.)(-?(0|[1-9][0-9]*)))+$/A';
12
    protected const PATTERN_FLOAT        = '/-?(0|[1-9][0-9]*)(\.[0-9]+)?((E|e)(\+|-)?[0-9]+)?/A';
13
    protected const PATTERN_SPREAD       = '/\.\.\./A';
14
    protected const PATTERN_STRING       = "/\"([^\"\\\u{000A}\u{000D}]|(\\([\u{0020}-\u{FFFF}]|[\"\\/bfnrt]))))*\"/As";
15
    protected const PATTERN_BLOCK_STRING = '/"""("?"?(\\"""|\\(?!=""")|[^"\\]))*"""/As';
16
    protected const PUNCTUATION          = '!$&:=@|()[]{}';
17
18
    /**
19
     * The lexer owning this token reader.
20
     *
21
     * @var LexerInterface
22
     */
23
    protected $lexer;
24
25
    /**
26
     * @inheritdoc
27
     */
28
    public function setLexer(LexerInterface $lexer)
29
    {
30
        $this->lexer = $lexer;
31
        return $this;
32
    }
33
34
    /**
35
     * @inheritdoc
36
     */
37
    public function getLexer(): LexerInterface
38
    {
39
        return $this->lexer;
40
    }
41
42
    /**
43
     * @inheritdoc
44
     * @throws SyntaxErrorException
45
     */
46
    public function read(string $body, int $pos, int $line, int $col, Token $prev): ?Token
47
    {
48
        if (false !== \strpos(self::PUNCTUATION, $body[$pos])) {
49
            return $this->createPunctuation($body, $pos, $line, $col, $prev);
50
        }
51
52
        if (\preg_match(static::PATTERN_COMMENT, $body, $match, null, $pos)) {
53
            return $this->createComment($pos, $pos + \mb_strlen($match[0]), $line, $col, $prev, $match[0]);
0 ignored issues
show
Bug introduced by
$pos of type integer is incompatible with the type array expected by parameter $args of Digia\GraphQL\Language\T...Reader::createComment(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

53
            return $this->createComment(/** @scrutinizer ignore-type */ $pos, $pos + \mb_strlen($match[0]), $line, $col, $prev, $match[0]);
Loading history...
Bug introduced by
$prev of type Digia\GraphQL\Language\Token is incompatible with the type array expected by parameter $args of Digia\GraphQL\Language\T...Reader::createComment(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

53
            return $this->createComment($pos, $pos + \mb_strlen($match[0]), $line, $col, /** @scrutinizer ignore-type */ $prev, $match[0]);
Loading history...
54
        }
55
56
        if (\preg_match(static::PATTERN_NAME, $body, $match, null, $pos)) {
57
            return $this->createName($pos, $pos + \mb_strlen($match[0]), $line, $col, $prev, $match[0]);
0 ignored issues
show
Bug introduced by
$pos of type integer is incompatible with the type array expected by parameter $args of Digia\GraphQL\Language\TokenReader::createName(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

57
            return $this->createName(/** @scrutinizer ignore-type */ $pos, $pos + \mb_strlen($match[0]), $line, $col, $prev, $match[0]);
Loading history...
Bug introduced by
$prev of type Digia\GraphQL\Language\Token is incompatible with the type array expected by parameter $args of Digia\GraphQL\Language\TokenReader::createName(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

57
            return $this->createName($pos, $pos + \mb_strlen($match[0]), $line, $col, /** @scrutinizer ignore-type */ $prev, $match[0]);
Loading history...
58
        }
59
60
        if (\preg_match(static::PATTERN_INT, $body, $match, null, $pos)) {
61
            return $this->createInt($pos, $pos + \mb_strlen($match[0]), $line, $col, $prev, $match[0]);
0 ignored issues
show
Bug introduced by
$pos of type integer is incompatible with the type array expected by parameter $args of Digia\GraphQL\Language\TokenReader::createInt(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

61
            return $this->createInt(/** @scrutinizer ignore-type */ $pos, $pos + \mb_strlen($match[0]), $line, $col, $prev, $match[0]);
Loading history...
Bug introduced by
$prev of type Digia\GraphQL\Language\Token is incompatible with the type array expected by parameter $args of Digia\GraphQL\Language\TokenReader::createInt(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

61
            return $this->createInt($pos, $pos + \mb_strlen($match[0]), $line, $col, /** @scrutinizer ignore-type */ $prev, $match[0]);
Loading history...
62
        }
63
64
        if (\preg_match(static::PATTERN_FLOAT, $body, $match, null, $pos)) {
65
            return $this->createFloat($pos, $pos + \mb_strlen($match[0]), $line, $col, $prev, $match[0]);
0 ignored issues
show
Bug introduced by
$pos of type integer is incompatible with the type array expected by parameter $args of Digia\GraphQL\Language\TokenReader::createFloat(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

65
            return $this->createFloat(/** @scrutinizer ignore-type */ $pos, $pos + \mb_strlen($match[0]), $line, $col, $prev, $match[0]);
Loading history...
Bug introduced by
$prev of type Digia\GraphQL\Language\Token is incompatible with the type array expected by parameter $args of Digia\GraphQL\Language\TokenReader::createFloat(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

65
            return $this->createFloat($pos, $pos + \mb_strlen($match[0]), $line, $col, /** @scrutinizer ignore-type */ $prev, $match[0]);
Loading history...
66
        }
67
68
        if (\preg_match(static::PATTERN_SPREAD, $body, $match, null, $pos)) {
69
            return $this->createSpread($pos, $pos + 3, $line, $col, $prev);
0 ignored issues
show
Bug introduced by
$pos of type integer is incompatible with the type array expected by parameter $args of Digia\GraphQL\Language\TokenReader::createSpread(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

69
            return $this->createSpread(/** @scrutinizer ignore-type */ $pos, $pos + 3, $line, $col, $prev);
Loading history...
Bug introduced by
$prev of type Digia\GraphQL\Language\Token is incompatible with the type array expected by parameter $args of Digia\GraphQL\Language\TokenReader::createSpread(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

69
            return $this->createSpread($pos, $pos + 3, $line, $col, /** @scrutinizer ignore-type */ $prev);
Loading history...
70
        }
71
72
        if (\preg_match(static::PATTERN_STRING, $body, $match, null, $pos)) {
73
            return $this->createString($pos, $pos + \mb_strlen($match[0]), $line, $col, $prev, $match[0]);
0 ignored issues
show
Bug introduced by
$pos of type integer is incompatible with the type array expected by parameter $args of Digia\GraphQL\Language\TokenReader::createString(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

73
            return $this->createString(/** @scrutinizer ignore-type */ $pos, $pos + \mb_strlen($match[0]), $line, $col, $prev, $match[0]);
Loading history...
Bug introduced by
$prev of type Digia\GraphQL\Language\Token is incompatible with the type array expected by parameter $args of Digia\GraphQL\Language\TokenReader::createString(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

73
            return $this->createString($pos, $pos + \mb_strlen($match[0]), $line, $col, /** @scrutinizer ignore-type */ $prev, $match[0]);
Loading history...
74
        }
75
76
        if (\preg_match(static::PATTERN_BLOCK_STRING, $body, $match, null, $pos)) {
77
            return $this->createBlockString($pos, $pos + \mb_strlen($match[0]), $line, $col, $prev, $match[0]);
0 ignored issues
show
Bug introduced by
$pos of type integer is incompatible with the type array expected by parameter $args of Digia\GraphQL\Language\T...er::createBlockString(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

77
            return $this->createBlockString(/** @scrutinizer ignore-type */ $pos, $pos + \mb_strlen($match[0]), $line, $col, $prev, $match[0]);
Loading history...
Bug introduced by
$prev of type Digia\GraphQL\Language\Token is incompatible with the type array expected by parameter $args of Digia\GraphQL\Language\T...er::createBlockString(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

77
            return $this->createBlockString($pos, $pos + \mb_strlen($match[0]), $line, $col, /** @scrutinizer ignore-type */ $prev, $match[0]);
Loading history...
78
        }
79
80
        return null;
81
    }
82
83
    /**
84
     * @param string      $kind
85
     * @param int         $start
86
     * @param int         $line
87
     * @param int         $col
88
     * @param Token       $prev
89
     * @param null|string $value
90
     * @return Token
91
     */
92
    protected function createToken(
93
        string $kind,
94
        int $start,
95
        int $end,
96
        int $line,
97
        int $col,
98
        Token $prev,
99
        ?string $value = null
100
    ): Token {
101
        return new Token($kind, $start, $end, $line, $col, $prev, $value);
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type string; however, parameter $value of Digia\GraphQL\Language\Token::__construct() does only seem to accept null, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

101
        return new Token($kind, $start, $end, $line, $col, $prev, /** @scrutinizer ignore-type */ $value);
Loading history...
102
    }
103
104
    /**
105
     * @param string $body
106
     * @param int    $pos
107
     * @param int    $line
108
     * @param int    $col
109
     * @param Token  $prev
110
     * @return Token
111
     */
112
    protected function createPunctuation(string $body, int $pos, int $line, int $col, Token $prev): Token
113
    {
114
        $code = \ord($body[$pos]);
115
116
        switch ($code) {
117
            case 33: // !
118
                return $this->createBang($pos, $line, $col, $prev);
119
            case 36: // $
120
                return $this->createDollar($pos, $line, $col, $prev);
121
            case 38: // &
122
                return $this->createAmp($pos, $line, $col, $prev);
123
            case 58: // :
124
                return $this->createColon($pos, $line, $col, $prev);
125
            case 61: // =
126
                return $this->createEquals($pos, $line, $col, $prev);
127
            case 64: // @
128
                return $this->createAt($pos, $line, $col, $prev);
129
            case 124: // |
130
                return $this->createPipe($pos, $line, $col, $prev);
131
            case 40:
132
            case 41: // ( or )~
133
                return $this->createParenthesis($code, $pos, $line, $col, $prev);
134
            case 91:
135
            case 93: // [ or ]
136
                return $this->createBracket($code, $pos, $line, $col, $prev);
137
            case 123:
138
            case 125: // { or }
139
                return $this->createBrace($code, $pos, $line, $col, $prev);
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return Digia\GraphQL\Language\Token. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
140
        }
141
    }
142
143
    /**
144
     * @param int   $pos
145
     * @param int   $line
146
     * @param int   $col
147
     * @param Token $prev
148
     * @return Token
149
     */
150
    protected function createColon(int $pos, int $line, int $col, Token $prev): Token
151
    {
152
        return new Token(TokenKindEnum::COLON, $pos, $pos + 1, $line, $col, $prev);
153
    }
154
155
    /**
156
     * @param int   $pos
157
     * @param int   $line
158
     * @param int   $col
159
     * @param Token $prev
160
     * @return Token
161
     */
162
    protected function createAmp(int $pos, int $line, int $col, Token $prev): Token
163
    {
164
        return new Token(TokenKindEnum::AMP, $pos, $pos + 1, $line, $col, $prev);
165
    }
166
167
    /**
168
     * @param int   $pos
169
     * @param int   $line
170
     * @param int   $col
171
     * @param Token $prev
172
     * @return Token
173
     */
174
    protected function createBang(int $pos, int $line, int $col, Token $prev): Token
175
    {
176
        return new Token(TokenKindEnum::BANG, $pos, $pos + 1, $line, $col, $prev);
177
    }
178
179
    /**
180
     * @param int   $code
181
     * @param int   $pos
182
     * @param int   $line
183
     * @param int   $col
184
     * @param Token $prev
185
     * @return Token
186
     */
187
    protected function createBrace(int $code, int $pos, int $line, int $col, Token $prev): Token
188
    {
189
        return $code === 123
190
            ? new Token(TokenKindEnum::BRACE_L, $pos, $pos + 1, $line, $col, $prev)
191
            : new Token(TokenKindEnum::BRACE_R, $pos, $pos + 1, $line, $col, $prev);
192
    }
193
194
    /**
195
     * @param int   $code
196
     * @param int   $pos
197
     * @param int   $line
198
     * @param int   $col
199
     * @param Token $prev
200
     * @return Token
201
     */
202
    protected function createBracket(int $code, int $pos, int $line, int $col, Token $prev): Token
203
    {
204
        return $code === 91
205
            ? new Token(TokenKindEnum::BRACKET_L, $pos, $pos + 1, $line, $col, $prev)
206
            : new Token(TokenKindEnum::BRACKET_R, $pos, $pos + 1, $line, $col, $prev);
207
    }
208
209
    /**
210
     * @param int   $pos
211
     * @param int   $line
212
     * @param int   $col
213
     * @param Token $prev
214
     * @return Token
215
     */
216
    protected function createDollar(int $pos, int $line, int $col, Token $prev): Token
217
    {
218
        return new Token(TokenKindEnum::DOLLAR, $pos, $pos + 1, $line, $col, $prev);
219
    }
220
221
    /**
222
     * @param int   $pos
223
     * @param int   $line
224
     * @param int   $col
225
     * @param Token $prev
226
     * @return Token
227
     */
228
    protected function createPipe(int $pos, int $line, int $col, Token $prev): Token
229
    {
230
        return new Token(TokenKindEnum::PIPE, $pos, $pos + 1, $line, $col, $prev);
231
    }
232
233
    /**
234
     * @param int   $code
235
     * @param int   $pos
236
     * @param int   $line
237
     * @param int   $col
238
     * @param Token $prev
239
     * @return Token
240
     */
241
    protected function createParenthesis(int $code, int $pos, int $line, int $col, Token $prev): Token
242
    {
243
        return $code === 40
244
            ? new Token(TokenKindEnum::PAREN_L, $pos, $pos + 1, $line, $col, $prev)
245
            : new Token(TokenKindEnum::PAREN_R, $pos, $pos + 1, $line, $col, $prev);
246
    }
247
248
    /**
249
     * @param int   $pos
250
     * @param int   $line
251
     * @param int   $col
252
     * @param Token $prev
253
     * @return Token
254
     */
255
    protected function createEquals(int $pos, int $line, int $col, Token $prev): Token
256
    {
257
        return new Token(TokenKindEnum::EQUALS, $pos, $pos + 1, $line, $col, $prev);
258
    }
259
260
    /**
261
     * @param int   $pos
262
     * @param int   $line
263
     * @param int   $col
264
     * @param Token $prev
265
     * @return Token
266
     */
267
    protected function createAt(int $pos, int $line, int $col, Token $prev): Token
268
    {
269
        return new Token(TokenKindEnum::AT, $pos, $pos + 1, $line, $col, $prev);
270
    }
271
272
    /**
273
     * @param array ...$args
274
     * @return Token
275
     */
276
    protected function createComment(...$args): Token
277
    {
278
        return $this->createToken(TokenKindEnum::COMMENT, ...$args);
279
    }
280
281
    /**
282
     * @param array ...$args
283
     * @return Token
284
     */
285
    protected function createName(...$args): Token
286
    {
287
        return $this->createToken(TokenKindEnum::NAME, ...$args);
288
    }
289
290
    /**
291
     * @param array ...$args
292
     * @return Token
293
     */
294
    protected function createInt(...$args): Token
295
    {
296
        return $this->createToken(TokenKindEnum::INT, ...$args);
297
    }
298
299
    /**
300
     * @param array ...$args
301
     * @return Token
302
     */
303
    protected function createFloat(...$args): Token
304
    {
305
        return $this->createToken(TokenKindEnum::FLOAT, ...$args);
306
    }
307
308
    /**
309
     * @param array ...$args
310
     * @return Token
311
     */
312
    protected function createSpread(...$args): Token
313
    {
314
        return $this->createToken(TokenKindEnum::SPREAD, ...$args);
315
    }
316
317
    /**
318
     * @param array ...$args
319
     * @return Token
320
     */
321
    protected function createString(...$args): Token
322
    {
323
        return $this->createToken(TokenKindEnum::STRING, ...$args);
324
    }
325
326
    /**
327
     * @param array ...$args
328
     * @return Token
329
     */
330
    protected function createBlockString(...$args): Token
331
    {
332
        return $this->createToken(TokenKindEnum::BLOCK_STRING, ...$args);
333
    }
334
335
//    /**
336
//     * @param string $body
337
//     * @param int    $bodyLength
338
//     * @param int    $pos
339
//     * @param int    $line
340
//     * @param int    $col
341
//     * @param Token  $prev
342
//     * @return Token
343
//     * @throws SyntaxErrorException
344
//     */
345
//    protected function readBlockString(string $body, int $bodyLength, int $pos, int $line, int $col, Token $prev): Token
346
//    {
347
//        $start      = $pos;
348
//        $pos        = $start + 3;
349
//        $chunkStart = $pos;
350
//        $rawValue   = '';
351
//
352
//        while ($pos < $bodyLength && ($code = charCodeAt($body, $pos)) !== null) {
353
//            // Closing Triple-Quote (""")
354
//            if (isTripleQuote($body, $code, $pos)) {
355
//                $rawValue .= sliceString($body, $chunkStart, $pos);
356
//                return new Token(
357
//                    TokenKindEnum::BLOCK_STRING,
358
//                    $start,
359
//                    $pos + 3,
360
//                    $line,
361
//                    $col,
362
//                    $prev,
363
//                    blockStringValue($rawValue)
364
//                );
365
//            }
366
//
367
//            if (isSourceCharacter($code) && !isLineTerminator($code)) {
368
//                throw new SyntaxErrorException(
369
//                    $this->lexer->getSource(),
370
//                    $pos,
371
//                    \sprintf('Invalid character within String: %s.', printCharCode($code))
372
//                );
373
//            }
374
//
375
//            if (isEscapedTripleQuote($body, $code, $pos)) {
376
//                $rawValue   .= sliceString($body, $chunkStart, $pos) . '"""';
377
//                $pos        += 4;
378
//                $chunkStart = $pos;
379
//            } else {
380
//                ++$pos;
381
//            }
382
//        }
383
//
384
//        throw new SyntaxErrorException($this->lexer->getSource(), $pos, 'Unterminated string.');
385
//    }
386
//
387
//    /**
388
//     * @param int   $code
389
//     * @param int   $pos
390
//     * @param int   $line
391
//     * @param int   $col
392
//     * @param Token $prev
393
//     * @return Token
394
//     * @throws SyntaxErrorException
395
//     */
396
//    protected function readNumber(int $code, int $pos, int $line, int $col, Token $prev): Token
397
//    {
398
//        $body    = $this->lexer->getBody();
399
//        $start   = $pos;
400
//        $isFloat = false;
401
//
402
//        if ($code === 45) {
403
//            // -
404
//            $code = charCodeAt($body, ++$pos);
405
//        }
406
//
407
//        if ($code === 48) {
408
//            // 0
409
//            $code = charCodeAt($body, ++$pos);
410
//
411
//            if (isNumber($code)) {
412
//                throw new SyntaxErrorException(
413
//                    $this->lexer->getSource(),
414
//                    $pos,
415
//                    \sprintf('Invalid number, unexpected digit after 0: %s.', printCharCode($code))
416
//                );
417
//            }
418
//        } else {
419
//            $pos  = $this->readDigits($code, $pos);
420
//            $code = charCodeAt($body, $pos);
421
//        }
422
//
423
//        if ($code === 46) {
424
//            // .
425
//            $isFloat = true;
426
//            $code    = charCodeAt($body, ++$pos);
427
//            $pos     = $this->readDigits($code, $pos);
428
//            $code    = charCodeAt($body, $pos);
429
//        }
430
//
431
//        if ($code === 69 || $code === 101) {
432
//            // e or E
433
//            $isFloat = true;
434
//            $code    = charCodeAt($body, ++$pos);
435
//
436
//            if ($code === 43 || $code === 45) {
437
//                // + or -
438
//                $code = charCodeAt($body, ++$pos);
439
//            }
440
//
441
//            $pos = $this->readDigits($code, $pos);
442
//        }
443
//
444
//        return new Token(
445
//            $isFloat ? TokenKindEnum::FLOAT : TokenKindEnum::INT,
446
//            $start,
447
//            $pos,
448
//            $line,
449
//            $col,
450
//            $prev,
451
//            sliceString($body, $start, $pos)
452
//        );
453
//    }
454
//
455
//    /**
456
//     * @param string $body
457
//     * @param int    $bodyLength
458
//     * @param int    $pos
459
//     * @param int    $line
460
//     * @param int    $col
461
//     * @param Token  $prev
462
//     * @return Token
463
//     * @throws SyntaxErrorException
464
//     */
465
//    protected function readString(string $body, int $bodyLength, int $pos, int $line, int $col, Token $prev): Token
466
//    {
467
//        $start      = $pos;
468
//        $pos        = $start + 1;
469
//        $chunkStart = $pos;
470
//        $value      = '';
471
//
472
//        while ($pos < $bodyLength && ($code = charCodeAt($body, $pos)) !== null && !isLineTerminator($code)) {
473
//            // Closing Quote (")
474
//            if ($code === 34) {
475
//                $value .= sliceString($body, $chunkStart, $pos);
476
//                return new Token(TokenKindEnum::STRING, $start, $pos + 1, $line, $col, $prev, $value);
477
//            }
478
//
479
//            if (isSourceCharacter($code)) {
480
//                throw new SyntaxErrorException(
481
//                    $this->lexer->getSource(),
482
//                    $pos,
483
//                    \sprintf('Invalid character within String: %s.', printCharCode($code))
484
//                );
485
//            }
486
//
487
//            ++$pos;
488
//
489
//            if ($code === 92) {
490
//                // \
491
//                $value .= sliceString($body, $chunkStart, $pos - 1);
492
//                $code  = charCodeAt($body, $pos);
493
//
494
//                switch ($code) {
495
//                    case 34:
496
//                        $value .= '"';
497
//                        break;
498
//                    case 47:
499
//                        $value .= '/';
500
//                        break;
501
//                    case 92:
502
//                        $value .= '\\';
503
//                        break;
504
//                    case 98:
505
//                        $value .= '\b';
506
//                        break;
507
//                    case 102:
508
//                        $value .= '\f';
509
//                        break;
510
//                    case 110:
511
//                        $value .= '\n';
512
//                        break;
513
//                    case 114:
514
//                        $value .= '\r';
515
//                        break;
516
//                    case 116:
517
//                        $value .= '\t';
518
//                        break;
519
//                    case 117:
520
//                        // u
521
//                        $unicodeString = sliceString($body, $pos + 1, $pos + 5);
522
//
523
//                        if (!\preg_match('/[0-9A-Fa-f]{4}/', $unicodeString)) {
524
//                            throw new SyntaxErrorException(
525
//                                $this->lexer->getSource(),
526
//                                $pos,
527
//                                \sprintf('Invalid character escape sequence: \\u%s.', $unicodeString)
528
//                            );
529
//                        }
530
//
531
//                        $value .= '\\u' . $unicodeString;
532
//                        $pos   += 4;
533
//                        break;
534
//                    default:
535
//                        throw new SyntaxErrorException(
536
//                            $this->lexer->getSource(),
537
//                            $pos,
538
//                            \sprintf('Invalid character escape sequence: \\%s.', \chr($code))
539
//                        );
540
//                }
541
//
542
//                ++$pos;
543
//
544
//                $chunkStart = $pos;
545
//            }
546
//        }
547
//
548
//        throw new SyntaxErrorException($this->lexer->getSource(), $pos, 'Unterminated string.');
549
//    }
550
//
551
//    /**
552
//     * @param int   $pos
553
//     * @param int   $line
554
//     * @param int   $col
555
//     * @param Token $prev
556
//     * @return Token
557
//     */
558
//    protected function readComment(int $pos, int $line, int $col, Token $prev): Token
559
//    {
560
//        $body  = $this->lexer->getBody();
561
//        $start = $pos;
562
//
563
//        do {
564
//            $code = charCodeAt($body, ++$pos);
565
//        } while ($code !== null && ($code > 0x001f || $code === 0x0009)); // SourceCharacter but not LineTerminator
566
//
567
//        return new Token(
568
//            TokenKindEnum::COMMENT,
569
//            $start,
570
//            $pos,
571
//            $line,
572
//            $col,
573
//            $prev,
574
//            sliceString($body, $start + 1, $pos)
575
//        );
576
//    }
577
//
578
//    /**
579
//     * @param int $code
580
//     * @param int $pos
581
//     * @return int
582
//     * @throws SyntaxErrorException
583
//     */
584
//    protected function readDigits(int $code, int $pos): int
585
//    {
586
//        $body = $this->lexer->getBody();
587
//
588
//        if (isNumber($code)) {
589
//            do {
590
//                $code = charCodeAt($body, ++$pos);
591
//            } while (isNumber($code));
592
//
593
//            return $pos;
594
//        }
595
//
596
//        throw new SyntaxErrorException(
597
//            $this->lexer->getSource(),
598
//            $pos,
599
//            sprintf('Invalid number, expected digit but got: %s.', printCharCode($code))
600
//        );
601
//    }
602
}
603