@@ -25,6 +25,17 @@ use std::str;
2525use std:: string;
2626use std:: iter;
2727
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+
2839/// A piece is a portion of the format string which represents the next part
2940/// to emit. These are emitted as a stream by the `Parser` class.
3041#[ derive( Copy , Clone , PartialEq ) ]
@@ -40,7 +51,7 @@ pub enum Piece<'a> {
4051#[ derive( Copy , Clone , PartialEq ) ]
4152pub struct Argument < ' a > {
4253 /// Where to find this argument
43- pub position : Position < ' a > ,
54+ pub position : Position ,
4455 /// How to format the argument
4556 pub format : FormatSpec < ' a > ,
4657}
@@ -55,9 +66,9 @@ pub struct FormatSpec<'a> {
5566 /// Packed version of various flags provided
5667 pub flags : u32 ,
5768 /// The integer precision to use
58- pub precision : Count < ' a > ,
69+ pub precision : Count ,
5970 /// The string width requested for the resulting format
60- pub width : Count < ' a > ,
71+ pub width : Count ,
6172 /// The descriptor string representing the name of the format desired for
6273 /// this argument, this can be empty or any number of characters, although
6374 /// it is required to be one word.
@@ -66,16 +77,16 @@ pub struct FormatSpec<'a> {
6677
6778/// Enum describing where an argument for a format can be located.
6879#[ derive( Copy , Clone , PartialEq ) ]
69- pub enum Position < ' a > {
80+ pub enum Position {
7081 /// The argument is implied to be located at an index
7182 ArgumentImplicitlyIs ( usize ) ,
7283 /// The argument is located at a specific index given in the format
7384 ArgumentIs ( usize ) ,
7485 /// The argument has a name.
75- ArgumentNamed ( & ' a str ) ,
86+ ArgumentNamed ( Symbol ) ,
7687}
7788
78- impl Position < ' _ > {
89+ impl Position {
7990 pub fn index ( & self ) -> Option < usize > {
8091 match self {
8192 ArgumentIs ( i) | ArgumentImplicitlyIs ( i) => Some ( * i) ,
@@ -120,11 +131,11 @@ pub enum Flag {
120131/// A count is used for the precision and width parameters of an integer, and
121132/// can reference either an argument or a literal integer.
122133#[ derive( Copy , Clone , PartialEq ) ]
123- pub enum Count < ' a > {
134+ pub enum Count {
124135 /// The count is specified explicitly.
125136 CountIs ( usize ) ,
126137 /// The count is specified by the argument with the given name.
127- CountIsName ( & ' a str ) ,
138+ CountIsName ( Symbol ) ,
128139 /// The count is specified by the argument at the given index.
129140 CountIsParam ( usize ) ,
130141 /// The count is implied and cannot be explicitly specified.
@@ -135,9 +146,8 @@ pub struct ParseError {
135146 pub description : string:: String ,
136147 pub note : Option < string:: String > ,
137148 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 ) > ,
141151}
142152
143153/// The parser structure for interpreting the input format string. This is
@@ -156,44 +166,36 @@ pub struct Parser<'a> {
156166 /// `Some(raw count)` when the string is "raw", used to position spans correctly
157167 style : Option < usize > ,
158168 /// Start and end byte offset of every successfully parsed argument
159- pub arg_places : Vec < ( SpanIndex , SpanIndex ) > ,
169+ pub arg_places : Vec < InnerSpan > ,
160170 /// Characters that need to be shifted
161171 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 > ,
164174 /// Wether the source string is comes from `println!` as opposed to `format!` or `print!`
165175 append_newline : bool ,
166176}
167177
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-
177178impl < ' a > Iterator for Parser < ' a > {
178179 type Item = Piece < ' a > ;
179180
180181 fn next ( & mut self ) -> Option < Piece < ' a > > {
181182 if let Some ( & ( pos, c) ) = self . cur . peek ( ) {
182183 match c {
183184 '{' => {
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 ) ) ) ;
186188 self . cur . next ( ) ;
187189 if self . consume ( '{' ) {
188- self . last_opening_brace_pos = curr_last_brace;
190+ self . last_opening_brace = curr_last_brace;
189191
190192 Some ( String ( self . string ( pos + 1 ) ) )
191193 } else {
192194 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 ) ) ;
197199 }
198200 Some ( NextArgument ( arg) )
199201 }
@@ -208,8 +210,7 @@ impl<'a> Iterator for Parser<'a> {
208210 "unmatched `}` found" ,
209211 "unmatched `}`" ,
210212 "if you intended to print `}`, you can escape it using `}}`" ,
211- err_pos,
212- err_pos,
213+ err_pos. to ( err_pos) ,
213214 ) ;
214215 None
215216 }
@@ -241,7 +242,7 @@ impl<'a> Parser<'a> {
241242 style,
242243 arg_places : vec ! [ ] ,
243244 skips,
244- last_opening_brace_pos : None ,
245+ last_opening_brace : None ,
245246 append_newline,
246247 }
247248 }
@@ -253,15 +254,13 @@ impl<'a> Parser<'a> {
253254 & mut self ,
254255 description : S1 ,
255256 label : S2 ,
256- start : SpanIndex ,
257- end : SpanIndex ,
257+ span : InnerSpan ,
258258 ) {
259259 self . errors . push ( ParseError {
260260 description : description. into ( ) ,
261261 note : None ,
262262 label : label. into ( ) ,
263- start,
264- end,
263+ span,
265264 secondary_label : None ,
266265 } ) ;
267266 }
@@ -274,15 +273,13 @@ impl<'a> Parser<'a> {
274273 description : S1 ,
275274 label : S2 ,
276275 note : S3 ,
277- start : SpanIndex ,
278- end : SpanIndex ,
276+ span : InnerSpan ,
279277 ) {
280278 self . errors . push ( ParseError {
281279 description : description. into ( ) ,
282280 note : Some ( note. into ( ) ) ,
283281 label : label. into ( ) ,
284- start,
285- end,
282+ span,
286283 secondary_label : None ,
287284 } ) ;
288285 }
@@ -303,22 +300,21 @@ impl<'a> Parser<'a> {
303300 }
304301 }
305302
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 {
311304 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 ) ;
312308 for skip in & self . skips {
313309 if pos > * skip {
314310 pos += 1 ;
315- } else if pos == * skip && self . raw ( ) == 0 {
311+ } else if pos == * skip && raw == 0 {
316312 pos += 1 ;
317313 } else {
318314 break ;
319315 }
320316 }
321- SpanIndex ( self . raw ( ) + pos + 1 )
317+ InnerOffset ( raw + pos + 1 )
322318 }
323319
324320 /// Forces consumption of the specified character. If the character is not
@@ -336,8 +332,8 @@ impl<'a> Parser<'a> {
336332 let label = "expected `}`" . to_owned ( ) ;
337333 let ( note, secondary_label) = if c == '}' {
338334 ( 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 )
341337 } ) )
342338 } else {
343339 ( None , None )
@@ -346,8 +342,7 @@ impl<'a> Parser<'a> {
346342 description,
347343 note,
348344 label,
349- start : pos,
350- end : pos,
345+ span : pos. to ( pos) ,
351346 secondary_label,
352347 } ) ;
353348 None
@@ -361,8 +356,8 @@ impl<'a> Parser<'a> {
361356 let label = format ! ( "expected `{:?}`" , c) ;
362357 let ( note, secondary_label) = if c == '}' {
363358 ( 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 )
366361 } ) )
367362 } else {
368363 ( None , None )
@@ -371,12 +366,11 @@ impl<'a> Parser<'a> {
371366 description,
372367 note,
373368 label,
374- start : pos,
375- end : pos,
369+ span : pos. to ( pos) ,
376370 secondary_label,
377371 } ) ;
378372 } else {
379- self . err ( description, format ! ( "expected `{:?}`" , c) , pos, pos) ;
373+ self . err ( description, format ! ( "expected `{:?}`" , c) , pos. to ( pos) ) ;
380374 }
381375 None
382376 }
@@ -435,20 +429,24 @@ impl<'a> Parser<'a> {
435429 /// integer index of an argument, a named argument, or a blank string.
436430 /// Returns `Some(parsed_position)` if the position is not implicitly
437431 /// 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 > {
439433 if let Some ( i) = self . integer ( ) {
440434 Some ( ArgumentIs ( i) )
441435 } else {
442436 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+ }
444440 Some ( & ( pos, c) ) if c == '_' => {
445441 let invalid_name = self . string ( pos) ;
446442 self . err_with_note ( format ! ( "invalid argument name `{}`" , invalid_name) ,
447443 "invalid argument name" ,
448444 "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) ) )
452450 } ,
453451
454452 // This is an `ArgumentNext`.
@@ -556,7 +554,7 @@ impl<'a> Parser<'a> {
556554 /// Parses a Count parameter at the current position. This does not check
557555 /// for 'CountIsNextParam' because that is only used in precision, not
558556 /// width.
559- fn count ( & mut self ) -> Count < ' a > {
557+ fn count ( & mut self ) -> Count {
560558 if let Some ( i) = self . integer ( ) {
561559 if self . consume ( '$' ) {
562560 CountIsParam ( i)
@@ -570,7 +568,7 @@ impl<'a> Parser<'a> {
570568 self . cur = tmp;
571569 CountImplied
572570 } else if self . consume ( '$' ) {
573- CountIsName ( word)
571+ CountIsName ( Symbol :: intern ( word) )
574572 } else {
575573 self . cur = tmp;
576574 CountImplied
@@ -760,6 +758,8 @@ mod tests {
760758 }
761759 #[ test]
762760 fn format_counts ( ) {
761+ use syntax_pos:: { GLOBALS , Globals , edition} ;
762+ GLOBALS . set ( & Globals :: new ( edition:: DEFAULT_EDITION ) , || {
763763 same ( "{:10s}" ,
764764 & [ NextArgument ( Argument {
765765 position : ArgumentImplicitlyIs ( 0 ) ,
@@ -815,11 +815,12 @@ mod tests {
815815 fill : None ,
816816 align : AlignUnknown ,
817817 flags : 0 ,
818- precision : CountIsName ( "b" ) ,
819- width : CountIsName ( "a" ) ,
818+ precision : CountIsName ( Symbol :: intern ( "b" ) ) ,
819+ width : CountIsName ( Symbol :: intern ( "a" ) ) ,
820820 ty : "s" ,
821821 } ,
822822 } ) ] ) ;
823+ } ) ;
823824 }
824825 #[ test]
825826 fn format_flags ( ) {
0 commit comments