@@ -121,13 +121,8 @@ public function nextToken(): ?Token
121121 return $ this ->readLiteral ();
122122 }
123123
124- // Check for number.
125- if (ctype_digit ($ char )) {
126- return $ this ->readNumber ();
127- }
128-
129- // Otherwise, parse an atom.
130- return $ this ->readAtom ();
124+ // Otherwise, parse a number or atom.
125+ return $ this ->readNumberOrAtom ();
131126 }
132127
133128 /**
@@ -306,14 +301,44 @@ protected function readLiteral(): Literal
306301 return new Literal ($ literal );
307302 }
308303
304+ /**
305+ * Reads a number or atom token.
306+ */
307+ protected function readNumberOrAtom (): Token
308+ {
309+ $ position = $ this ->position ;
310+
311+ // First char must be a digit to even consider a number.
312+ if (! ctype_digit ($ this ->buffer [$ position ] ?? '' )) {
313+ return $ this ->readAtom ();
314+ }
315+
316+ // Walk forward to find the end of the digit run.
317+ while (ctype_digit ($ this ->buffer [$ position ] ?? '' )) {
318+ $ position ++;
319+
320+ $ this ->ensureBuffer ($ position - $ this ->position + 1 );
321+ }
322+
323+ $ next = $ this ->buffer [$ position ] ?? null ;
324+
325+ // If next is EOF or a delimiter, it's a Number.
326+ if ($ next === null || $ this ->isDelimiter ($ next )) {
327+ return $ this ->readNumber ();
328+ }
329+
330+ // Otherwise it's an Atom.
331+ return $ this ->readAtom ();
332+ }
333+
309334 /**
310335 * Reads a number token.
311336 *
312- * Numbers are sequences of digits .
337+ * A number consists of one or more digit characters and represents a numeric value .
313338 */
314339 protected function readNumber (): Number
315340 {
316- $ value = '' ;
341+ $ start = $ this -> position ;
317342
318343 while (true ) {
319344 $ this ->ensureBuffer (1 );
@@ -328,12 +353,10 @@ protected function readNumber(): Number
328353 break ;
329354 }
330355
331- $ value .= $ char ;
332-
333356 $ this ->advance ();
334357 }
335358
336- return new Number ($ value );
359+ return new Number (substr ( $ this -> buffer , $ start , $ this -> position - $ start ) );
337360 }
338361
339362 /**
@@ -347,6 +370,7 @@ protected function readAtom(): Atom
347370
348371 while (true ) {
349372 $ this ->ensureBuffer (1 );
373+
350374 $ char = $ this ->currentChar ();
351375
352376 if ($ char === null ) {
0 commit comments