@@ -149,6 +149,16 @@ impl reader for TtReader {
149
149
fn dup ( @mut self ) -> @mut reader { dup_tt_reader ( self ) as @mut reader }
150
150
}
151
151
152
+ // report a lexical error spanning [`from_pos`, `to_pos`)
153
+ fn fatal_span ( rdr : @mut StringReader ,
154
+ from_pos : BytePos ,
155
+ to_pos : BytePos ,
156
+ m : ~str )
157
+ -> ! {
158
+ rdr. peek_span = codemap:: mk_sp ( from_pos, to_pos) ;
159
+ rdr. fatal ( m) ;
160
+ }
161
+
152
162
// EFFECT: advance peek_tok and peek_span to refer to the next token.
153
163
// EFFECT: update the interner, maybe.
154
164
fn string_advance_token ( r : @mut StringReader ) {
@@ -327,7 +337,8 @@ fn consume_block_comment(rdr: @mut StringReader)
327
337
bump ( rdr) ;
328
338
}
329
339
if is_eof ( rdr) {
330
- rdr. fatal ( ~"unterminated block doc-comment") ;
340
+ fatal_span ( rdr, start_bpos, rdr. last_pos ,
341
+ ~"unterminated block doc-comment") ;
331
342
} else {
332
343
bump ( rdr) ;
333
344
bump ( rdr) ;
@@ -344,8 +355,12 @@ fn consume_block_comment(rdr: @mut StringReader)
344
355
}
345
356
}
346
357
} else {
358
+ let start_bpos = rdr. last_pos - BytePos ( 2 u) ;
347
359
loop {
348
- if is_eof ( rdr) { rdr. fatal ( ~"unterminated block comment") ; }
360
+ if is_eof ( rdr) {
361
+ fatal_span ( rdr, start_bpos, rdr. last_pos ,
362
+ ~"unterminated block comment") ;
363
+ }
349
364
if rdr. curr == '*' && nextch ( rdr) == '/' {
350
365
bump ( rdr) ;
351
366
bump ( rdr) ;
@@ -362,6 +377,7 @@ fn consume_block_comment(rdr: @mut StringReader)
362
377
}
363
378
364
379
fn scan_exponent ( rdr : @mut StringReader ) -> Option < ~str > {
380
+ let start_bpos = rdr. last_pos ;
365
381
let mut c = rdr. curr ;
366
382
let mut rslt = ~"";
367
383
if c == 'e' || c == 'E' {
@@ -375,7 +391,10 @@ fn scan_exponent(rdr: @mut StringReader) -> Option<~str> {
375
391
let exponent = scan_digits ( rdr, 10 u) ;
376
392
if exponent. len ( ) > 0 u {
377
393
return Some ( rslt + exponent) ;
378
- } else { rdr. fatal ( ~"scan_exponent: bad fp literal") ; }
394
+ } else {
395
+ fatal_span ( rdr, start_bpos, rdr. last_pos ,
396
+ ~"scan_exponent: bad fp literal") ;
397
+ }
379
398
} else { return None :: < ~str > ; }
380
399
}
381
400
@@ -399,6 +418,7 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token {
399
418
let mut base = 10 u;
400
419
let mut c = c;
401
420
let mut n = nextch ( rdr) ;
421
+ let start_bpos = rdr. last_pos ;
402
422
if c == '0' && n == 'x' {
403
423
bump ( rdr) ;
404
424
bump ( rdr) ;
@@ -442,11 +462,13 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token {
442
462
else { either:: Right ( ast:: ty_u64) } ;
443
463
}
444
464
if num_str. len ( ) == 0 u {
445
- rdr. fatal ( ~"no valid digits found for number") ;
465
+ fatal_span ( rdr, start_bpos, rdr. last_pos ,
466
+ ~"no valid digits found for number") ;
446
467
}
447
468
let parsed = match from_str_radix :: < u64 > ( num_str, base as uint ) {
448
469
Some ( p) => p,
449
- None => rdr. fatal ( ~"int literal is too large")
470
+ None => fatal_span ( rdr, start_bpos, rdr. last_pos ,
471
+ ~"int literal is too large")
450
472
} ;
451
473
452
474
match tp {
@@ -464,8 +486,10 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token {
464
486
}
465
487
if is_float {
466
488
match base {
467
- 16 u => rdr. fatal ( ~"hexadecimal float literal is not supported") ,
468
- 2 u => rdr. fatal ( ~"binary float literal is not supported") ,
489
+ 16 u => fatal_span ( rdr, start_bpos, rdr. last_pos ,
490
+ ~"hexadecimal float literal is not supported") ,
491
+ 2 u => fatal_span ( rdr, start_bpos, rdr. last_pos ,
492
+ ~"binary float literal is not supported") ,
469
493
_ => ( )
470
494
}
471
495
}
@@ -507,11 +531,13 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token {
507
531
return token:: LIT_FLOAT_UNSUFFIXED ( str_to_ident ( num_str) ) ;
508
532
} else {
509
533
if num_str. len ( ) == 0 u {
510
- rdr. fatal ( ~"no valid digits found for number") ;
534
+ fatal_span ( rdr, start_bpos, rdr. last_pos ,
535
+ ~"no valid digits found for number") ;
511
536
}
512
537
let parsed = match from_str_radix :: < u64 > ( num_str, base as uint ) {
513
538
Some ( p) => p,
514
- None => rdr. fatal ( ~"int literal is too large")
539
+ None => fatal_span ( rdr, start_bpos, rdr. last_pos ,
540
+ ~"int literal is too large")
515
541
} ;
516
542
517
543
debug ! ( "lexing %s as an unsuffixed integer literal" ,
@@ -523,19 +549,23 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token {
523
549
fn scan_numeric_escape ( rdr : @mut StringReader , n_hex_digits : uint ) -> char {
524
550
let mut accum_int = 0 ;
525
551
let mut i = n_hex_digits;
552
+ let start_bpos = rdr. last_pos ;
526
553
while i != 0 u {
527
554
let n = rdr. curr ;
528
- bump ( rdr) ;
529
555
if !is_hex_digit ( n) {
530
- rdr. fatal ( fmt ! ( "illegal numeric character escape: %d" , n as int) ) ;
556
+ fatal_span ( rdr, rdr. last_pos , rdr. pos ,
557
+ fmt ! ( "illegal numeric character escape: %d" ,
558
+ n as int) ) ;
531
559
}
560
+ bump ( rdr) ;
532
561
accum_int *= 16 ;
533
562
accum_int += hex_digit_val ( n) ;
534
563
i -= 1 u;
535
564
}
536
565
match char:: from_u32 ( accum_int as u32 ) {
537
566
Some ( x) => x,
538
- None => rdr. fatal ( fmt ! ( "illegal numeric character escape" ) )
567
+ None => fatal_span ( rdr, start_bpos, rdr. last_pos ,
568
+ fmt ! ( "illegal numeric character escape" ) )
539
569
}
540
570
}
541
571
@@ -691,6 +721,7 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
691
721
if c2 == '\\' {
692
722
// '\X' for some X must be a character constant:
693
723
let escaped = rdr. curr ;
724
+ let escaped_pos = rdr. last_pos ;
694
725
bump ( rdr) ;
695
726
match escaped {
696
727
'n' => { c2 = '\n' ; }
@@ -704,12 +735,18 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
704
735
'u' => { c2 = scan_numeric_escape ( rdr, 4 u) ; }
705
736
'U' => { c2 = scan_numeric_escape ( rdr, 8 u) ; }
706
737
c2 => {
707
- rdr. fatal ( fmt ! ( "unknown character escape: %d" , c2 as int) ) ;
738
+ fatal_span ( rdr, escaped_pos, rdr. last_pos ,
739
+ fmt ! ( "unknown character escape: %d" , c2 as int) ) ;
708
740
}
709
741
}
710
742
}
711
743
if rdr. curr != '\'' {
712
- rdr. fatal ( ~"unterminated character constant") ;
744
+ fatal_span ( rdr,
745
+ // Byte offsetting here is okay because the character
746
+ // before position `start` is an ascii single quote.
747
+ start - BytePos ( 1 u) ,
748
+ rdr. last_pos ,
749
+ ~"unterminated character constant") ;
713
750
}
714
751
bump ( rdr) ; // advance curr past token
715
752
return token:: LIT_CHAR ( c2 as u32 ) ;
@@ -721,7 +758,9 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
721
758
while rdr. curr != '"' {
722
759
if is_eof ( rdr) {
723
760
do with_str_from ( rdr, n) |s| {
724
- rdr. fatal ( fmt ! ( "unterminated double quote string: %s" , s) ) ;
761
+ fatal_span ( rdr, n, rdr. last_pos ,
762
+ fmt ! ( "unterminated double quote string: %s" ,
763
+ s) ) ;
725
764
}
726
765
}
727
766
@@ -730,6 +769,7 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
730
769
match ch {
731
770
'\\' => {
732
771
let escaped = rdr. curr ;
772
+ let escaped_pos = rdr. last_pos ;
733
773
bump ( rdr) ;
734
774
match escaped {
735
775
'n' => accum_str. push_char ( '\n' ) ,
@@ -750,7 +790,8 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
750
790
accum_str. push_char ( scan_numeric_escape ( rdr, 8 u) ) ;
751
791
}
752
792
c2 => {
753
- rdr. fatal ( fmt ! ( "unknown string escape: %d" , c2 as int) ) ;
793
+ fatal_span ( rdr, escaped_pos, rdr. last_pos ,
794
+ fmt ! ( "unknown string escape: %d" , c2 as int) ) ;
754
795
}
755
796
}
756
797
}
@@ -786,11 +827,10 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
786
827
'^' => { return binop ( rdr, token:: CARET ) ; }
787
828
'%' => { return binop ( rdr, token:: PERCENT ) ; }
788
829
c => {
789
- // So the error span points to the unrecognized character
790
- rdr. peek_span = codemap:: mk_sp ( rdr. last_pos , rdr. pos ) ;
791
830
let mut cs = ~"";
792
831
char:: escape_default ( c, |c| cs. push_char ( c) ) ;
793
- rdr. fatal ( fmt ! ( "unknown start of token: %s" , cs) ) ;
832
+ fatal_span ( rdr, rdr. last_pos , rdr. pos ,
833
+ fmt ! ( "unknown start of token: %s" , cs) ) ;
794
834
}
795
835
}
796
836
}
0 commit comments