@@ -650,12 +650,13 @@ impl<'a> StringReader<'a> {
650
650
/// token, and updates the interner
651
651
fn next_token_inner ( & mut self ) -> token:: Token {
652
652
let c = self . curr ;
653
- if ident_start ( c) && match ( c. unwrap ( ) , self . nextch ( ) ) {
653
+ if ident_start ( c) && match ( c. unwrap ( ) , self . nextch ( ) , self . nextnextch ( ) ) {
654
654
// Note: r as in r" or r#" is part of a raw string literal,
655
655
// b as in b' is part of a byte literal.
656
656
// They are not identifiers, and are handled further down.
657
- ( 'r' , Some ( '"' ) ) | ( 'r' , Some ( '#' ) ) |
658
- ( 'b' , Some ( '"' ) ) | ( 'b' , Some ( '\'' ) ) => false ,
657
+ ( 'r' , Some ( '"' ) , _) | ( 'r' , Some ( '#' ) , _) |
658
+ ( 'b' , Some ( '"' ) , _) | ( 'b' , Some ( '\'' ) , _) |
659
+ ( 'b' , Some ( 'r' ) , Some ( '"' ) ) | ( 'b' , Some ( 'r' ) , Some ( '#' ) ) => false ,
659
660
_ => true
660
661
} {
661
662
let start = self . last_pos ;
@@ -863,6 +864,7 @@ impl<'a> StringReader<'a> {
863
864
return match self . curr {
864
865
Some ( '\'' ) => parse_byte ( self ) ,
865
866
Some ( '"' ) => parse_byte_string ( self ) ,
867
+ Some ( 'r' ) => parse_raw_byte_string ( self ) ,
866
868
_ => unreachable ! ( ) // Should have been a token::IDENT above.
867
869
} ;
868
870
@@ -978,6 +980,54 @@ impl<'a> StringReader<'a> {
978
980
self_. bump ( ) ;
979
981
return token:: LIT_BINARY ( Rc :: new ( value) ) ;
980
982
}
983
+
984
+ fn parse_raw_byte_string ( self_ : & mut StringReader ) -> token:: Token {
985
+ let start_bpos = self_. last_pos ;
986
+ self_. bump ( ) ;
987
+ let mut hash_count = 0 u;
988
+ while self_. curr_is ( '#' ) {
989
+ self_. bump ( ) ;
990
+ hash_count += 1 ;
991
+ }
992
+
993
+ if self_. is_eof ( ) {
994
+ self_. fatal_span ( start_bpos, self_. last_pos , "unterminated raw string" ) ;
995
+ } else if !self_. curr_is ( '"' ) {
996
+ self_. fatal_span_char ( start_bpos, self_. last_pos ,
997
+ "only `#` is allowed in raw string delimitation; \
998
+ found illegal character",
999
+ self_. curr . unwrap ( ) ) ;
1000
+ }
1001
+ self_. bump ( ) ;
1002
+ let content_start_bpos = self_. last_pos ;
1003
+ let mut content_end_bpos;
1004
+ ' outer: loop {
1005
+ match self_. curr {
1006
+ None => self_. fatal_span ( start_bpos, self_. last_pos ,
1007
+ "unterminated raw string" ) ,
1008
+ Some ( '"' ) => {
1009
+ content_end_bpos = self_. last_pos ;
1010
+ for _ in range ( 0 , hash_count) {
1011
+ self_. bump ( ) ;
1012
+ if !self_. curr_is ( '#' ) {
1013
+ continue ' outer;
1014
+ }
1015
+ }
1016
+ break ;
1017
+ } ,
1018
+ Some ( c) => if c > '\x7F' {
1019
+ self_. err_span_char ( self_. last_pos , self_. last_pos ,
1020
+ "raw byte string must be ASCII" , c) ;
1021
+ }
1022
+ }
1023
+ self_. bump ( ) ;
1024
+ }
1025
+ self_. bump ( ) ;
1026
+ let bytes = self_. with_str_from_to ( content_start_bpos,
1027
+ content_end_bpos,
1028
+ |s| s. as_bytes ( ) . to_owned ( ) ) ;
1029
+ return token:: LIT_BINARY_RAW ( Rc :: new ( bytes) , hash_count) ;
1030
+ }
981
1031
}
982
1032
'"' => {
983
1033
let mut accum_str = String :: new ( ) ;
0 commit comments