@@ -501,18 +501,26 @@ fn scan_numeric_escape(rdr: @mut StringReader, n_hex_digits: uint) -> char {
501
501
return accum_int as char ;
502
502
}
503
503
504
+ fn ident_start ( c : char ) -> bool {
505
+ ( c >= 'a' && c <= 'z' )
506
+ || ( c >= 'A' && c <= 'Z' )
507
+ || c == '_'
508
+ || ( c > 'z' && char:: is_XID_start ( c) )
509
+ }
510
+
511
+ fn ident_continue ( c : char ) -> bool {
512
+ ( c >= 'a' && c <= 'z' )
513
+ || ( c >= 'A' && c <= 'Z' )
514
+ || ( c >= '0' && c <= '9' )
515
+ || c == '_'
516
+ || ( c > 'z' && char:: is_XID_continue ( c) )
517
+ }
518
+
504
519
fn next_token_inner( rdr : @mut StringReader ) -> token:: Token {
505
520
let mut accum_str = ~"";
506
521
let mut c = rdr. curr ;
507
- if ( c >= 'a' && c <= 'z' )
508
- || ( c >= 'A' && c <= 'Z' )
509
- || c == '_'
510
- || ( c > 'z' && char:: is_XID_start ( c) ) {
511
- while ( c >= 'a' && c <= 'z' )
512
- || ( c >= 'A' && c <= 'Z' )
513
- || ( c >= '0' && c <= '9' )
514
- || c == '_'
515
- || ( c > 'z' && char:: is_XID_continue ( c) ) {
522
+ if ident_start ( c) {
523
+ while ident_continue ( c) {
516
524
str:: push_char ( & mut accum_str, c) ;
517
525
bump ( rdr) ;
518
526
c = rdr. curr ;
@@ -617,10 +625,26 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
617
625
}
618
626
}
619
627
'\'' => {
628
+ // Either a character constant 'a' OR a lifetime name 'abc
620
629
bump ( rdr) ;
621
630
let mut c2 = rdr. curr ;
622
631
bump ( rdr) ;
632
+
633
+ // If the character is an ident start not followed by another single
634
+ // quote, then this is a lifetime name:
635
+ if ident_start ( c2) && rdr. curr != '\'' {
636
+ let mut lifetime_name = ~"";
637
+ lifetime_name. push_char ( c2) ;
638
+ while ident_continue ( rdr. curr ) {
639
+ lifetime_name. push_char ( rdr. curr ) ;
640
+ bump ( rdr) ;
641
+ }
642
+ return token:: LIFETIME ( rdr. interner . intern ( @lifetime_name) ) ;
643
+ }
644
+
645
+ // Otherwise it is a character constant:
623
646
if c2 == '\\' {
647
+ // '\X' for some X must be a character constant:
624
648
let escaped = rdr. curr ;
625
649
bump ( rdr) ;
626
650
match escaped {
@@ -730,17 +754,29 @@ pub mod test {
730
754
use util:: interner;
731
755
use diagnostic;
732
756
use util:: testing:: { check_equal, check_equal_ptr} ;
733
- #[ tetst] fn t1 ( ) {
734
- let teststr =
735
- @~"/* my source file * /
736
- fn main ( ) { io:: println ( ~\" zebra\" ) ; } \n ";
757
+
758
+ struct Env {
759
+ interner : @token:: ident_interner ,
760
+ string_reader : @mut StringReader
761
+ }
762
+
763
+ fn setup ( teststr : ~str ) -> Env {
737
764
let cm = CodeMap :: new ( ) ;
738
- let fm = cm. new_filemap ( ~"zebra. rs ", teststr) ;
765
+ let fm = cm. new_filemap ( ~"zebra. rs ", @ teststr) ;
739
766
let ident_interner = token:: mk_ident_interner ( ) ; // interner::mk();
740
- let id = ident_interner. intern ( @~"fn ") ;
741
767
let span_handler =
742
768
diagnostic:: mk_span_handler ( diagnostic:: mk_handler ( None ) , @cm) ;
743
- let string_reader = new_string_reader ( span_handler, fm, ident_interner) ;
769
+ Env {
770
+ interner : ident_interner,
771
+ string_reader : new_string_reader ( span_handler, fm, ident_interner)
772
+ }
773
+ }
774
+
775
+ #[ test] fn t1 ( ) {
776
+ let Env { interner : ident_interner, string_reader} =
777
+ setup ( ~"/* my source file * / \
778
+ fn main ( ) { io:: println ( ~\" zebra\" ) ; } \n ") ;
779
+ let id = ident_interner. intern ( @~"fn ") ;
744
780
let tok1 = string_reader. next_token ( ) ;
745
781
let tok2 = TokenAndSpan {
746
782
tok : token:: IDENT ( id, false ) ,
@@ -757,6 +793,35 @@ fn main() { io::println(~\"zebra\"); }\n";
757
793
// the lparen is already read:
758
794
check_equal ( string_reader. last_pos , BytePos ( 29 ) )
759
795
}
796
+
797
+ #[ test] fn character_a ( ) {
798
+ let env = setup ( ~"'a' ") ;
799
+ let TokenAndSpan { tok, sp : _} =
800
+ env. string_reader . next_token ( ) ;
801
+ assert tok == token:: LIT_INT ( 'a' as i64 , ast:: ty_char) ;
802
+ }
803
+
804
+ #[ test] fn character_space ( ) {
805
+ let env = setup ( ~"' ' ") ;
806
+ let TokenAndSpan { tok, sp : _} =
807
+ env. string_reader . next_token ( ) ;
808
+ assert tok == token:: LIT_INT ( ' ' as i64 , ast:: ty_char) ;
809
+ }
810
+
811
+ #[ test] fn character_escaped ( ) {
812
+ let env = setup ( ~"'\n' ") ;
813
+ let TokenAndSpan { tok, sp : _} =
814
+ env. string_reader . next_token ( ) ;
815
+ assert tok == token:: LIT_INT ( '\n' as i64 , ast:: ty_char) ;
816
+ }
817
+
818
+ #[ test] fn lifetime_name ( ) {
819
+ let env = setup ( ~"' abc") ;
820
+ let TokenAndSpan { tok, sp: _} =
821
+ env. string_reader . next_token ( ) ;
822
+ let id = env. interner . intern ( @~"abc") ;
823
+ assert tok == token:: LIFETIME ( id) ;
824
+ }
760
825
}
761
826
762
827
//
0 commit comments