@@ -98,11 +98,17 @@ static final class Token {
9898 final TokenType type ;
9999 final int start ;
100100 final int end ;
101+ final @ Nullable String text ;
101102
102103 Token (TokenType type , int start , int end ) {
104+ this (type , start , end , null );
105+ }
106+
107+ Token (TokenType type , int start , int end , @ Nullable String text ) {
103108 this .type = type ;
104109 this .start = start ;
105110 this .end = end ;
111+ this .text = text ;
106112 }
107113
108114 @ Override
@@ -149,35 +155,28 @@ static final class LexerError {
149155 .buildOrThrow ();
150156
151157 private final CelCodePointArray content ;
158+ private final int size ;
152159 private int position ;
153160 private LexerError error ;
154161
155162 Lexer (CelCodePointArray content ) {
156163 this .content = content ;
164+ this .size = content .size ();
157165 this .position = 0 ;
158166 this .error = null ;
159167 }
160168
161169 Token lex () {
170+ consumeWhitespaceAndComments ();
162171 int start = position ;
163- if (position >= content . size () ) {
172+ if (position >= size ) {
164173 return makeToken (TokenType .END , start , start );
165174 }
166175 int c = content .get (position );
167176 switch (c ) {
168- case '\f' :
169- case '\n' :
170- case ' ' :
171- case '\r' :
172- case 0x0B : // \v (vertical tab)
173- case '\t' :
174- {
175- consumeWhitespace ();
176- return makeToken (TokenType .WHITESPACE , start , position );
177- }
178177 case '.' :
179178 {
180- if (position + 1 < content . size () && isDigit (content .get (position + 1 ))) {
179+ if (position + 1 < size && isDigit (content .get (position + 1 ))) {
181180 return consumeNumericLiteral ();
182181 }
183182 advance (1 );
@@ -283,10 +282,6 @@ Token lex() {
283282 case '/' :
284283 {
285284 advance (1 );
286- if (consume ('/' )) {
287- consumeLine ();
288- return makeToken (TokenType .COMMENT , start , position );
289- }
290285 return makeToken (TokenType .SLASH , start , position );
291286 }
292287 case '&' :
@@ -391,7 +386,7 @@ private void advance(int n) {
391386 }
392387
393388 private boolean match (int c ) {
394- return position < content . size () && content .get (position ) == c ;
389+ return position < size && content .get (position ) == c ;
395390 }
396391
397392 private boolean consume (int c ) {
@@ -403,7 +398,7 @@ private boolean consume(int c) {
403398 }
404399
405400 private boolean consumeIf (IntPredicate predicate ) {
406- if (position < content . size () ) {
401+ if (position < size ) {
407402 int cp = content .get (position );
408403 if (predicate .test (cp )) {
409404 advance (1 );
@@ -414,7 +409,7 @@ private boolean consumeIf(IntPredicate predicate) {
414409 }
415410
416411 private void consumeLine () {
417- while (position < content . size () ) {
412+ while (position < size ) {
418413 if (content .get (position ) == '\n' ) {
419414 advance (1 );
420415 return ;
@@ -423,8 +418,8 @@ private void consumeLine() {
423418 }
424419 }
425420
426- private void consumeWhitespace () {
427- while (position < content . size () ) {
421+ private void consumeWhitespaceAndComments () {
422+ while (position < size ) {
428423 int c = content .get (position );
429424 switch (c ) {
430425 case '\f' :
@@ -433,38 +428,35 @@ private void consumeWhitespace() {
433428 case '\r' :
434429 case 11 : // \v
435430 case '\t' :
436- advance ( 1 ) ;
431+ position ++ ;
437432 break ;
433+ case '/' :
434+ if (position + 1 < size && content .get (position + 1 ) == '/' ) {
435+ consumeLine ();
436+ break ;
437+ } else {
438+ return ;
439+ }
438440 default :
439441 return ;
440442 }
441443 }
442444 }
443445
444446 private boolean consumeDigits () {
445- boolean advanced = false ;
446- while (position < content .size ()) {
447- int c = content .get (position );
448- if (!isDigit (c )) {
449- break ;
450- }
451- advance (1 );
452- advanced = true ;
447+ int start = position ;
448+ while (position < size && isDigit (content .get (position ))) {
449+ position ++;
453450 }
454- return advanced ;
451+ return position > start ;
455452 }
456453
457454 private boolean consumeHexDigits () {
458- boolean advanced = false ;
459- while (position < content .size ()) {
460- int c = content .get (position );
461- if (!isHexDigit (c )) {
462- break ;
463- }
464- advance (1 );
465- advanced = true ;
455+ int start = position ;
456+ while (position < size && isHexDigit (content .get (position ))) {
457+ position ++;
466458 }
467- return advanced ;
459+ return position > start ;
468460 }
469461
470462 private TokenType consumeIntegralSuffix () {
@@ -486,7 +478,7 @@ private Token consumeQuotedIdent() {
486478 private boolean consumeUntilAfter (int c , boolean isRaw ) {
487479 int pos = position ;
488480 boolean escaped = false ;
489- while (pos < content . size () ) {
481+ while (pos < size ) {
490482 int cc = content .get (pos );
491483 if (cc == '\n' || cc == '\r' ) {
492484 position = pos ;
@@ -503,20 +495,20 @@ private boolean consumeUntilAfter(int c, boolean isRaw) {
503495 }
504496 pos ++;
505497 }
506- position = content . size () ;
498+ position = size ;
507499 return false ;
508500 }
509501
510502 private boolean consumeUntilAfterTripleQuote (int quote , boolean isRaw ) {
511503 int pos = position ;
512504 boolean escaped = false ;
513- while (pos < content . size () ) {
505+ while (pos < size ) {
514506 int cc = content .get (pos );
515507 if (!isRaw && cc == '\\' ) {
516508 escaped = !escaped ;
517509 } else {
518510 if ((isRaw || !escaped )
519- && pos + 2 < content . size ()
511+ && pos + 2 < size
520512 && cc == quote
521513 && content .get (pos + 1 ) == quote
522514 && content .get (pos + 2 ) == quote ) {
@@ -527,16 +519,14 @@ private boolean consumeUntilAfterTripleQuote(int quote, boolean isRaw) {
527519 }
528520 pos ++;
529521 }
530- position = content . size () ;
522+ position = size ;
531523 return false ;
532524 }
533525
534526 private Token consumeStringLiteral (int start , int quote , boolean isBytes , boolean isRaw ) {
535527 advance (1 );
536528 boolean isTripleQuote =
537- position + 1 < content .size ()
538- && content .get (position ) == quote
539- && content .get (position + 1 ) == quote ;
529+ position + 1 < size && content .get (position ) == quote && content .get (position + 1 ) == quote ;
540530 if (isTripleQuote ) {
541531 advance (2 );
542532 if (!consumeUntilAfterTripleQuote (quote , isRaw )) {
@@ -556,7 +546,7 @@ private Token consumeStringLiteral(int start, int quote, boolean isBytes, boolea
556546
557547 private @ Nullable Token consumePrefixedStringLiteral () {
558548 int start = position ;
559- if (position >= content . size () ) {
549+ if (position >= size ) {
560550 return null ;
561551 }
562552 int c = content .get (position );
@@ -566,15 +556,15 @@ private Token consumeStringLiteral(int start, int quote, boolean isBytes, boolea
566556 return null ;
567557 }
568558 int lookahead = 1 ;
569- if (position + 1 < content . size () ) {
559+ if (position + 1 < size ) {
570560 int c2 = content .get (position + 1 );
571561 if (isBytes ? (c2 == 'r' || c2 == 'R' ) : (c2 == 'b' || c2 == 'B' )) {
572562 isBytes = true ;
573563 isRaw = true ;
574564 lookahead = 2 ;
575565 }
576566 }
577- if (position + lookahead < content . size () ) {
567+ if (position + lookahead < size ) {
578568 int quote = content .get (position + lookahead );
579569 if (quote == '"' || quote == '\'' ) {
580570 advance (lookahead );
@@ -612,9 +602,9 @@ private Token consumeNumericLiteral() {
612602 return makeToken (tokenType , start , position );
613603 }
614604 consumeDigits ();
615- if (position < content . size ()
605+ if (position < size
616606 && content .get (position ) == '.'
617- && position + 1 < content . size ()
607+ && position + 1 < size
618608 && isDigit (content .get (position + 1 ))) {
619609 floatingPoint = true ;
620610 advance (1 );
@@ -639,19 +629,15 @@ && isDigit(content.get(position + 1))) {
639629
640630 private Token consumeIdent () {
641631 int start = position ;
642- while (position < content .size ()) {
643- int c = content .get (position );
644- if (!isIdentTrailing (c )) {
645- break ;
646- }
647- advance (1 );
632+ while (position < size && isIdentTrailing (content .get (position ))) {
633+ position ++;
648634 }
649635 int end = position ;
650636 String word = content .slice (start , end ).toString ();
651637 TokenType keywordType = KEYWORDS .get (word );
652638 if (keywordType != null ) {
653639 return makeToken (keywordType , start , end );
654640 }
655- return makeToken (TokenType .IDENT , start , end );
641+ return new Token (TokenType .IDENT , start , end , word );
656642 }
657643}
0 commit comments