@@ -25,6 +25,17 @@ use std::str;
25
25
use std:: string;
26
26
use std:: iter;
27
27
28
+ use syntax_pos:: { InnerSpan , Symbol } ;
29
+
30
+ #[ derive( Copy , Clone ) ]
31
+ struct InnerOffset ( usize ) ;
32
+
33
+ impl InnerOffset {
34
+ fn to ( self , end : InnerOffset ) -> InnerSpan {
35
+ InnerSpan :: new ( self . 0 , end. 0 )
36
+ }
37
+ }
38
+
28
39
/// A piece is a portion of the format string which represents the next part
29
40
/// to emit. These are emitted as a stream by the `Parser` class.
30
41
#[ derive( Copy , Clone , PartialEq ) ]
@@ -40,7 +51,7 @@ pub enum Piece<'a> {
40
51
#[ derive( Copy , Clone , PartialEq ) ]
41
52
pub struct Argument < ' a > {
42
53
/// Where to find this argument
43
- pub position : Position < ' a > ,
54
+ pub position : Position ,
44
55
/// How to format the argument
45
56
pub format : FormatSpec < ' a > ,
46
57
}
@@ -55,9 +66,9 @@ pub struct FormatSpec<'a> {
55
66
/// Packed version of various flags provided
56
67
pub flags : u32 ,
57
68
/// The integer precision to use
58
- pub precision : Count < ' a > ,
69
+ pub precision : Count ,
59
70
/// The string width requested for the resulting format
60
- pub width : Count < ' a > ,
71
+ pub width : Count ,
61
72
/// The descriptor string representing the name of the format desired for
62
73
/// this argument, this can be empty or any number of characters, although
63
74
/// it is required to be one word.
@@ -66,16 +77,16 @@ pub struct FormatSpec<'a> {
66
77
67
78
/// Enum describing where an argument for a format can be located.
68
79
#[ derive( Copy , Clone , PartialEq ) ]
69
- pub enum Position < ' a > {
80
+ pub enum Position {
70
81
/// The argument is implied to be located at an index
71
82
ArgumentImplicitlyIs ( usize ) ,
72
83
/// The argument is located at a specific index given in the format
73
84
ArgumentIs ( usize ) ,
74
85
/// The argument has a name.
75
- ArgumentNamed ( & ' a str ) ,
86
+ ArgumentNamed ( Symbol ) ,
76
87
}
77
88
78
- impl Position < ' _ > {
89
+ impl Position {
79
90
pub fn index ( & self ) -> Option < usize > {
80
91
match self {
81
92
ArgumentIs ( i) | ArgumentImplicitlyIs ( i) => Some ( * i) ,
@@ -120,11 +131,11 @@ pub enum Flag {
120
131
/// A count is used for the precision and width parameters of an integer, and
121
132
/// can reference either an argument or a literal integer.
122
133
#[ derive( Copy , Clone , PartialEq ) ]
123
- pub enum Count < ' a > {
134
+ pub enum Count {
124
135
/// The count is specified explicitly.
125
136
CountIs ( usize ) ,
126
137
/// The count is specified by the argument with the given name.
127
- CountIsName ( & ' a str ) ,
138
+ CountIsName ( Symbol ) ,
128
139
/// The count is specified by the argument at the given index.
129
140
CountIsParam ( usize ) ,
130
141
/// The count is implied and cannot be explicitly specified.
@@ -135,9 +146,8 @@ pub struct ParseError {
135
146
pub description : string:: String ,
136
147
pub note : Option < string:: String > ,
137
148
pub label : string:: String ,
138
- pub start : SpanIndex ,
139
- pub end : SpanIndex ,
140
- pub secondary_label : Option < ( string:: String , SpanIndex , SpanIndex ) > ,
149
+ pub span : InnerSpan ,
150
+ pub secondary_label : Option < ( string:: String , InnerSpan ) > ,
141
151
}
142
152
143
153
/// The parser structure for interpreting the input format string. This is
@@ -156,44 +166,36 @@ pub struct Parser<'a> {
156
166
/// `Some(raw count)` when the string is "raw", used to position spans correctly
157
167
style : Option < usize > ,
158
168
/// Start and end byte offset of every successfully parsed argument
159
- pub arg_places : Vec < ( SpanIndex , SpanIndex ) > ,
169
+ pub arg_places : Vec < InnerSpan > ,
160
170
/// Characters that need to be shifted
161
171
skips : Vec < usize > ,
162
- /// Span offset of the last opening brace seen, used for error reporting
163
- last_opening_brace_pos : Option < SpanIndex > ,
172
+ /// Span of the last opening brace seen, used for error reporting
173
+ last_opening_brace : Option < InnerSpan > ,
164
174
/// Wether the source string is comes from `println!` as opposed to `format!` or `print!`
165
175
append_newline : bool ,
166
176
}
167
177
168
- #[ derive( Clone , Copy , Debug ) ]
169
- pub struct SpanIndex ( pub usize ) ;
170
-
171
- impl SpanIndex {
172
- pub fn unwrap ( self ) -> usize {
173
- self . 0
174
- }
175
- }
176
-
177
178
impl < ' a > Iterator for Parser < ' a > {
178
179
type Item = Piece < ' a > ;
179
180
180
181
fn next ( & mut self ) -> Option < Piece < ' a > > {
181
182
if let Some ( & ( pos, c) ) = self . cur . peek ( ) {
182
183
match c {
183
184
'{' => {
184
- let curr_last_brace = self . last_opening_brace_pos ;
185
- self . last_opening_brace_pos = Some ( self . to_span_index ( pos) ) ;
185
+ let curr_last_brace = self . last_opening_brace ;
186
+ let byte_pos = self . to_span_index ( pos) ;
187
+ self . last_opening_brace = Some ( byte_pos. to ( InnerOffset ( byte_pos. 0 + 1 ) ) ) ;
186
188
self . cur . next ( ) ;
187
189
if self . consume ( '{' ) {
188
- self . last_opening_brace_pos = curr_last_brace;
190
+ self . last_opening_brace = curr_last_brace;
189
191
190
192
Some ( String ( self . string ( pos + 1 ) ) )
191
193
} else {
192
194
let arg = self . argument ( ) ;
193
- if let Some ( arg_pos ) = self . must_consume ( '}' ) . map ( |end| {
194
- ( self . to_span_index ( pos) , self . to_span_index ( end + 1 ) )
195
- } ) {
196
- self . arg_places . push ( arg_pos ) ;
195
+ if let Some ( end ) = self . must_consume ( '}' ) {
196
+ let start = self . to_span_index ( pos) ;
197
+ let end = self . to_span_index ( end + 1 ) ;
198
+ self . arg_places . push ( start . to ( end ) ) ;
197
199
}
198
200
Some ( NextArgument ( arg) )
199
201
}
@@ -208,8 +210,7 @@ impl<'a> Iterator for Parser<'a> {
208
210
"unmatched `}` found" ,
209
211
"unmatched `}`" ,
210
212
"if you intended to print `}`, you can escape it using `}}`" ,
211
- err_pos,
212
- err_pos,
213
+ err_pos. to ( err_pos) ,
213
214
) ;
214
215
None
215
216
}
@@ -241,7 +242,7 @@ impl<'a> Parser<'a> {
241
242
style,
242
243
arg_places : vec ! [ ] ,
243
244
skips,
244
- last_opening_brace_pos : None ,
245
+ last_opening_brace : None ,
245
246
append_newline,
246
247
}
247
248
}
@@ -253,15 +254,13 @@ impl<'a> Parser<'a> {
253
254
& mut self ,
254
255
description : S1 ,
255
256
label : S2 ,
256
- start : SpanIndex ,
257
- end : SpanIndex ,
257
+ span : InnerSpan ,
258
258
) {
259
259
self . errors . push ( ParseError {
260
260
description : description. into ( ) ,
261
261
note : None ,
262
262
label : label. into ( ) ,
263
- start,
264
- end,
263
+ span,
265
264
secondary_label : None ,
266
265
} ) ;
267
266
}
@@ -274,15 +273,13 @@ impl<'a> Parser<'a> {
274
273
description : S1 ,
275
274
label : S2 ,
276
275
note : S3 ,
277
- start : SpanIndex ,
278
- end : SpanIndex ,
276
+ span : InnerSpan ,
279
277
) {
280
278
self . errors . push ( ParseError {
281
279
description : description. into ( ) ,
282
280
note : Some ( note. into ( ) ) ,
283
281
label : label. into ( ) ,
284
- start,
285
- end,
282
+ span,
286
283
secondary_label : None ,
287
284
} ) ;
288
285
}
@@ -303,22 +300,21 @@ impl<'a> Parser<'a> {
303
300
}
304
301
}
305
302
306
- fn raw ( & self ) -> usize {
307
- self . style . map ( |raw| raw + 1 ) . unwrap_or ( 0 )
308
- }
309
-
310
- fn to_span_index ( & self , pos : usize ) -> SpanIndex {
303
+ fn to_span_index ( & self , pos : usize ) -> InnerOffset {
311
304
let mut pos = pos;
305
+ // This handles the raw string case, the raw argument is the number of #
306
+ // in r###"..."### (we need to add one because of the `r`).
307
+ let raw = self . style . map ( |raw| raw + 1 ) . unwrap_or ( 0 ) ;
312
308
for skip in & self . skips {
313
309
if pos > * skip {
314
310
pos += 1 ;
315
- } else if pos == * skip && self . raw ( ) == 0 {
311
+ } else if pos == * skip && raw == 0 {
316
312
pos += 1 ;
317
313
} else {
318
314
break ;
319
315
}
320
316
}
321
- SpanIndex ( self . raw ( ) + pos + 1 )
317
+ InnerOffset ( raw + pos + 1 )
322
318
}
323
319
324
320
/// Forces consumption of the specified character. If the character is not
@@ -336,8 +332,8 @@ impl<'a> Parser<'a> {
336
332
let label = "expected `}`" . to_owned ( ) ;
337
333
let ( note, secondary_label) = if c == '}' {
338
334
( Some ( "if you intended to print `{`, you can escape it using `{{`" . to_owned ( ) ) ,
339
- self . last_opening_brace_pos . map ( |pos | {
340
- ( "because of this opening brace" . to_owned ( ) , pos , pos )
335
+ self . last_opening_brace . map ( |sp | {
336
+ ( "because of this opening brace" . to_owned ( ) , sp )
341
337
} ) )
342
338
} else {
343
339
( None , None )
@@ -346,8 +342,7 @@ impl<'a> Parser<'a> {
346
342
description,
347
343
note,
348
344
label,
349
- start : pos,
350
- end : pos,
345
+ span : pos. to ( pos) ,
351
346
secondary_label,
352
347
} ) ;
353
348
None
@@ -361,8 +356,8 @@ impl<'a> Parser<'a> {
361
356
let label = format ! ( "expected `{:?}`" , c) ;
362
357
let ( note, secondary_label) = if c == '}' {
363
358
( Some ( "if you intended to print `{`, you can escape it using `{{`" . to_owned ( ) ) ,
364
- self . last_opening_brace_pos . map ( |pos | {
365
- ( "because of this opening brace" . to_owned ( ) , pos , pos )
359
+ self . last_opening_brace . map ( |sp | {
360
+ ( "because of this opening brace" . to_owned ( ) , sp )
366
361
} ) )
367
362
} else {
368
363
( None , None )
@@ -371,12 +366,11 @@ impl<'a> Parser<'a> {
371
366
description,
372
367
note,
373
368
label,
374
- start : pos,
375
- end : pos,
369
+ span : pos. to ( pos) ,
376
370
secondary_label,
377
371
} ) ;
378
372
} else {
379
- self . err ( description, format ! ( "expected `{:?}`" , c) , pos, pos) ;
373
+ self . err ( description, format ! ( "expected `{:?}`" , c) , pos. to ( pos) ) ;
380
374
}
381
375
None
382
376
}
@@ -435,20 +429,24 @@ impl<'a> Parser<'a> {
435
429
/// integer index of an argument, a named argument, or a blank string.
436
430
/// Returns `Some(parsed_position)` if the position is not implicitly
437
431
/// consuming a macro argument, `None` if it's the case.
438
- fn position ( & mut self ) -> Option < Position < ' a > > {
432
+ fn position ( & mut self ) -> Option < Position > {
439
433
if let Some ( i) = self . integer ( ) {
440
434
Some ( ArgumentIs ( i) )
441
435
} else {
442
436
match self . cur . peek ( ) {
443
- Some ( & ( _, c) ) if c. is_alphabetic ( ) => Some ( ArgumentNamed ( self . word ( ) ) ) ,
437
+ Some ( & ( _, c) ) if c. is_alphabetic ( ) => {
438
+ Some ( ArgumentNamed ( Symbol :: intern ( self . word ( ) ) ) )
439
+ }
444
440
Some ( & ( pos, c) ) if c == '_' => {
445
441
let invalid_name = self . string ( pos) ;
446
442
self . err_with_note ( format ! ( "invalid argument name `{}`" , invalid_name) ,
447
443
"invalid argument name" ,
448
444
"argument names cannot start with an underscore" ,
449
- self . to_span_index ( pos) ,
450
- self . to_span_index ( pos + invalid_name. len ( ) ) ) ;
451
- Some ( ArgumentNamed ( invalid_name) )
445
+ self . to_span_index ( pos) . to (
446
+ self . to_span_index ( pos + invalid_name. len ( ) )
447
+ ) ,
448
+ ) ;
449
+ Some ( ArgumentNamed ( Symbol :: intern ( invalid_name) ) )
452
450
} ,
453
451
454
452
// This is an `ArgumentNext`.
@@ -556,7 +554,7 @@ impl<'a> Parser<'a> {
556
554
/// Parses a Count parameter at the current position. This does not check
557
555
/// for 'CountIsNextParam' because that is only used in precision, not
558
556
/// width.
559
- fn count ( & mut self ) -> Count < ' a > {
557
+ fn count ( & mut self ) -> Count {
560
558
if let Some ( i) = self . integer ( ) {
561
559
if self . consume ( '$' ) {
562
560
CountIsParam ( i)
@@ -570,7 +568,7 @@ impl<'a> Parser<'a> {
570
568
self . cur = tmp;
571
569
CountImplied
572
570
} else if self . consume ( '$' ) {
573
- CountIsName ( word)
571
+ CountIsName ( Symbol :: intern ( word) )
574
572
} else {
575
573
self . cur = tmp;
576
574
CountImplied
@@ -760,6 +758,8 @@ mod tests {
760
758
}
761
759
#[ test]
762
760
fn format_counts ( ) {
761
+ use syntax_pos:: { GLOBALS , Globals , edition} ;
762
+ GLOBALS . set ( & Globals :: new ( edition:: DEFAULT_EDITION ) , || {
763
763
same ( "{:10s}" ,
764
764
& [ NextArgument ( Argument {
765
765
position : ArgumentImplicitlyIs ( 0 ) ,
@@ -815,11 +815,12 @@ mod tests {
815
815
fill : None ,
816
816
align : AlignUnknown ,
817
817
flags : 0 ,
818
- precision : CountIsName ( "b" ) ,
819
- width : CountIsName ( "a" ) ,
818
+ precision : CountIsName ( Symbol :: intern ( "b" ) ) ,
819
+ width : CountIsName ( Symbol :: intern ( "a" ) ) ,
820
820
ty : "s" ,
821
821
} ,
822
822
} ) ] ) ;
823
+ } ) ;
823
824
}
824
825
#[ test]
825
826
fn format_flags ( ) {
0 commit comments