1
1
//! Code related to parsing literals.
2
2
3
- use crate :: ast:: { self , LitKind , MetaItemLit } ;
3
+ use crate :: ast:: { self , LitKind , MetaItemLit , StrStyle } ;
4
4
use crate :: token:: { self , Token } ;
5
5
use rustc_lexer:: unescape:: { byte_from_char, unescape_byte, unescape_char, unescape_literal, Mode } ;
6
6
use rustc_span:: symbol:: { kw, sym, Symbol } ;
7
7
use 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
+ }
9
29
10
30
#[ derive( Debug ) ]
11
31
pub enum LitError {
@@ -115,9 +135,9 @@ impl LitKind {
115
135
}
116
136
} ) ;
117
137
error?;
118
- LitKind :: ByteStr ( buf. into ( ) )
138
+ LitKind :: ByteStr ( buf. into ( ) , StrStyle :: Cooked )
119
139
}
120
- token:: ByteStrRaw ( _ ) => {
140
+ token:: ByteStrRaw ( n ) => {
121
141
let s = symbol. as_str ( ) ;
122
142
let bytes = if s. contains ( '\r' ) {
123
143
let mut buf = Vec :: with_capacity ( s. len ( ) ) ;
@@ -136,69 +156,95 @@ impl LitKind {
136
156
symbol. to_string ( ) . into_bytes ( )
137
157
} ;
138
158
139
- LitKind :: ByteStr ( bytes. into ( ) )
159
+ LitKind :: ByteStr ( bytes. into ( ) , StrStyle :: Raw ( n ) )
140
160
}
141
161
token:: Err => LitKind :: Err ,
142
162
} )
143
163
}
164
+ }
144
165
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) ?;
161
172
}
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) ) ?
165
183
}
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
+ ) ?;
169
193
}
170
194
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
+ }
177
201
}
178
202
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
+ }
184
208
}
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>" ) ?;
188
214
}
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
+ }
193
216
194
- token :: Lit :: new ( kind , symbol , suffix )
217
+ Ok ( ( ) )
195
218
}
196
219
}
197
220
198
221
impl MetaItemLit {
199
- /// Converts token literal into a meta item literal.
222
+ /// Converts a token literal into a meta item literal.
200
223
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 )
202
248
}
203
249
204
250
/// Converts an arbitrary token into meta item literal.
0 commit comments