11//! Code related to parsing literals.
22
3- use crate :: ast:: { self , LitKind , MetaItemLit } ;
3+ use crate :: ast:: { self , LitKind , MetaItemLit , StrStyle } ;
44use crate :: token:: { self , Token } ;
55use rustc_lexer:: unescape:: { byte_from_char, unescape_byte, unescape_char, unescape_literal, Mode } ;
66use rustc_span:: symbol:: { kw, sym, Symbol } ;
77use rustc_span:: Span ;
8- use std:: ascii;
8+ use std:: { ascii, fmt, str} ;
9+
10+ // Escapes a string, represented as a symbol. Reuses the original symbol,
11+ // avoiding interning, if no changes are required.
12+ pub fn escape_string_symbol ( symbol : Symbol ) -> Symbol {
13+ let s = symbol. as_str ( ) ;
14+ let escaped = s. escape_default ( ) . to_string ( ) ;
15+ if s == escaped { symbol } else { Symbol :: intern ( & escaped) }
16+ }
17+
18+ // Escapes a char.
19+ pub fn escape_char_symbol ( ch : char ) -> Symbol {
20+ let s: String = ch. escape_default ( ) . map ( Into :: < char > :: into) . collect ( ) ;
21+ Symbol :: intern ( & s)
22+ }
23+
24+ // Escapes a byte string.
25+ pub fn escape_byte_str_symbol ( bytes : & [ u8 ] ) -> Symbol {
26+ let s = bytes. escape_ascii ( ) . to_string ( ) ;
27+ Symbol :: intern ( & s)
28+ }
929
1030#[ derive( Debug ) ]
1131pub enum LitError {
@@ -115,9 +135,9 @@ impl LitKind {
115135 }
116136 } ) ;
117137 error?;
118- LitKind :: ByteStr ( buf. into ( ) )
138+ LitKind :: ByteStr ( buf. into ( ) , StrStyle :: Cooked )
119139 }
120- token:: ByteStrRaw ( _ ) => {
140+ token:: ByteStrRaw ( n ) => {
121141 let s = symbol. as_str ( ) ;
122142 let bytes = if s. contains ( '\r' ) {
123143 let mut buf = Vec :: with_capacity ( s. len ( ) ) ;
@@ -136,69 +156,95 @@ impl LitKind {
136156 symbol. to_string ( ) . into_bytes ( )
137157 } ;
138158
139- LitKind :: ByteStr ( bytes. into ( ) )
159+ LitKind :: ByteStr ( bytes. into ( ) , StrStyle :: Raw ( n ) )
140160 }
141161 token:: Err => LitKind :: Err ,
142162 } )
143163 }
164+ }
144165
145- /// Attempts to recover a token from semantic literal.
146- /// This function is used when the original token doesn't exist (e.g. the literal is created
147- /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing).
148- pub fn to_token_lit ( & self ) -> token:: Lit {
149- let ( kind, symbol, suffix) = match * self {
150- LitKind :: Str ( symbol, ast:: StrStyle :: Cooked ) => {
151- // Don't re-intern unless the escaped string is different.
152- let s = symbol. as_str ( ) ;
153- let escaped = s. escape_default ( ) . to_string ( ) ;
154- let symbol = if s == escaped { symbol } else { Symbol :: intern ( & escaped) } ;
155- ( token:: Str , symbol, None )
156- }
157- LitKind :: Str ( symbol, ast:: StrStyle :: Raw ( n) ) => ( token:: StrRaw ( n) , symbol, None ) ,
158- LitKind :: ByteStr ( ref bytes) => {
159- let string = bytes. escape_ascii ( ) . to_string ( ) ;
160- ( token:: ByteStr , Symbol :: intern ( & string) , None )
166+ impl fmt:: Display for LitKind {
167+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
168+ match * self {
169+ LitKind :: Byte ( b) => {
170+ let b: String = ascii:: escape_default ( b) . map ( Into :: < char > :: into) . collect ( ) ;
171+ write ! ( f, "b'{}'" , b) ?;
161172 }
162- LitKind :: Byte ( byte) => {
163- let string: String = ascii:: escape_default ( byte) . map ( Into :: < char > :: into) . collect ( ) ;
164- ( token:: Byte , Symbol :: intern ( & string) , None )
173+ LitKind :: Char ( ch) => write ! ( f, "'{}'" , escape_char_symbol( ch) ) ?,
174+ LitKind :: Str ( sym, StrStyle :: Cooked ) => write ! ( f, "\" {}\" " , escape_string_symbol( sym) ) ?,
175+ LitKind :: Str ( sym, StrStyle :: Raw ( n) ) => write ! (
176+ f,
177+ "r{delim}\" {string}\" {delim}" ,
178+ delim = "#" . repeat( n as usize ) ,
179+ string = sym
180+ ) ?,
181+ LitKind :: ByteStr ( ref bytes, StrStyle :: Cooked ) => {
182+ write ! ( f, "b\" {}\" " , escape_byte_str_symbol( bytes) ) ?
165183 }
166- LitKind :: Char ( ch) => {
167- let string: String = ch. escape_default ( ) . map ( Into :: < char > :: into) . collect ( ) ;
168- ( token:: Char , Symbol :: intern ( & string) , None )
184+ LitKind :: ByteStr ( ref bytes, StrStyle :: Raw ( n) ) => {
185+ // Unwrap because raw byte string literals can only contain ASCII.
186+ let symbol = str:: from_utf8 ( bytes) . unwrap ( ) ;
187+ write ! (
188+ f,
189+ "br{delim}\" {string}\" {delim}" ,
190+ delim = "#" . repeat( n as usize ) ,
191+ string = symbol
192+ ) ?;
169193 }
170194 LitKind :: Int ( n, ty) => {
171- let suffix = match ty {
172- ast :: LitIntType :: Unsigned ( ty ) => Some ( ty . name ( ) ) ,
173- ast:: LitIntType :: Signed ( ty) => Some ( ty. name ( ) ) ,
174- ast:: LitIntType :: Unsuffixed => None ,
175- } ;
176- ( token :: Integer , sym :: integer ( n ) , suffix )
195+ write ! ( f , "{}" , n ) ? ;
196+ match ty {
197+ ast:: LitIntType :: Unsigned ( ty) => write ! ( f , "{}" , ty. name( ) ) ? ,
198+ ast:: LitIntType :: Signed ( ty ) => write ! ( f , "{}" , ty . name ( ) ) ? ,
199+ ast :: LitIntType :: Unsuffixed => { }
200+ }
177201 }
178202 LitKind :: Float ( symbol, ty) => {
179- let suffix = match ty {
180- ast :: LitFloatType :: Suffixed ( ty ) => Some ( ty . name ( ) ) ,
181- ast:: LitFloatType :: Unsuffixed => None ,
182- } ;
183- ( token :: Float , symbol , suffix )
203+ write ! ( f , "{}" , symbol ) ? ;
204+ match ty {
205+ ast:: LitFloatType :: Suffixed ( ty ) => write ! ( f , "{}" , ty . name ( ) ) ? ,
206+ ast :: LitFloatType :: Unsuffixed => { }
207+ }
184208 }
185- LitKind :: Bool ( value) => {
186- let symbol = if value { kw:: True } else { kw:: False } ;
187- ( token:: Bool , symbol, None )
209+ LitKind :: Bool ( b) => write ! ( f, "{}" , if b { "true" } else { "false" } ) ?,
210+ LitKind :: Err => {
211+ // This only shows up in places like `-Zunpretty=hir` output, so we
212+ // don't bother to produce something useful.
213+ write ! ( f, "<bad-literal>" ) ?;
188214 }
189- // This only shows up in places like `-Zunpretty=hir` output, so we
190- // don't bother to produce something useful.
191- LitKind :: Err => ( token:: Err , Symbol :: intern ( "<bad-literal>" ) , None ) ,
192- } ;
215+ }
193216
194- token :: Lit :: new ( kind , symbol , suffix )
217+ Ok ( ( ) )
195218 }
196219}
197220
198221impl MetaItemLit {
199- /// Converts token literal into a meta item literal.
222+ /// Converts a token literal into a meta item literal.
200223 pub fn from_token_lit ( token_lit : token:: Lit , span : Span ) -> Result < MetaItemLit , LitError > {
201- Ok ( MetaItemLit { token_lit, kind : LitKind :: from_token_lit ( token_lit) ?, span } )
224+ Ok ( MetaItemLit {
225+ symbol : token_lit. symbol ,
226+ suffix : token_lit. suffix ,
227+ kind : LitKind :: from_token_lit ( token_lit) ?,
228+ span,
229+ } )
230+ }
231+
232+ /// Cheaply converts a meta item literal into a token literal.
233+ pub fn as_token_lit ( & self ) -> token:: Lit {
234+ let kind = match self . kind {
235+ LitKind :: Bool ( _) => token:: Bool ,
236+ LitKind :: Str ( _, ast:: StrStyle :: Cooked ) => token:: Str ,
237+ LitKind :: Str ( _, ast:: StrStyle :: Raw ( n) ) => token:: StrRaw ( n) ,
238+ LitKind :: ByteStr ( _, ast:: StrStyle :: Cooked ) => token:: ByteStr ,
239+ LitKind :: ByteStr ( _, ast:: StrStyle :: Raw ( n) ) => token:: ByteStrRaw ( n) ,
240+ LitKind :: Byte ( _) => token:: Byte ,
241+ LitKind :: Char ( _) => token:: Char ,
242+ LitKind :: Int ( ..) => token:: Integer ,
243+ LitKind :: Float ( ..) => token:: Float ,
244+ LitKind :: Err => token:: Err ,
245+ } ;
246+
247+ token:: Lit :: new ( kind, self . symbol , self . suffix )
202248 }
203249
204250 /// Converts an arbitrary token into meta item literal.
0 commit comments