@@ -150,12 +150,17 @@ pub struct Parser<'a> {
150
150
pub errors : Vec < ParseError > ,
151
151
/// Current position of implicit positional argument pointer
152
152
curarg : usize ,
153
+ /// `Some(raw count)` when the string is "raw", used to position spans correctly
154
+ style : Option < usize > ,
155
+ /// How many newlines have been seen in the string so far, to adjust the error spans
156
+ seen_newlines : usize ,
153
157
}
154
158
155
159
impl < ' a > Iterator for Parser < ' a > {
156
160
type Item = Piece < ' a > ;
157
161
158
162
fn next ( & mut self ) -> Option < Piece < ' a > > {
163
+ let raw = self . style . map ( |raw| raw + self . seen_newlines ) . unwrap_or ( 0 ) ;
159
164
if let Some ( & ( pos, c) ) = self . cur . peek ( ) {
160
165
match c {
161
166
'{' => {
@@ -170,20 +175,24 @@ impl<'a> Iterator for Parser<'a> {
170
175
}
171
176
'}' => {
172
177
self . cur . next ( ) ;
173
- let pos = pos + 1 ;
174
178
if self . consume ( '}' ) {
175
- Some ( String ( self . string ( pos) ) )
179
+ Some ( String ( self . string ( pos + 1 ) ) )
176
180
} else {
181
+ let err_pos = pos + raw + 1 ;
177
182
self . err_with_note (
178
183
"unmatched `}` found" ,
179
184
"unmatched `}`" ,
180
185
"if you intended to print `}`, you can escape it using `}}`" ,
181
- pos ,
182
- pos ,
186
+ err_pos ,
187
+ err_pos ,
183
188
) ;
184
189
None
185
190
}
186
191
}
192
+ '\n' => {
193
+ self . seen_newlines += 1 ;
194
+ Some ( String ( self . string ( pos) ) )
195
+ }
187
196
_ => Some ( String ( self . string ( pos) ) ) ,
188
197
}
189
198
} else {
@@ -194,12 +203,14 @@ impl<'a> Iterator for Parser<'a> {
194
203
195
204
impl < ' a > Parser < ' a > {
196
205
/// Creates a new parser for the given format string
197
- pub fn new ( s : & ' a str ) -> Parser < ' a > {
206
+ pub fn new ( s : & ' a str , style : Option < usize > ) -> Parser < ' a > {
198
207
Parser {
199
208
input : s,
200
209
cur : s. char_indices ( ) . peekable ( ) ,
201
210
errors : vec ! [ ] ,
202
211
curarg : 0 ,
212
+ style,
213
+ seen_newlines : 0 ,
203
214
}
204
215
}
205
216
@@ -262,24 +273,32 @@ impl<'a> Parser<'a> {
262
273
/// found, an error is emitted.
263
274
fn must_consume ( & mut self , c : char ) {
264
275
self . ws ( ) ;
276
+ let raw = self . style . unwrap_or ( 0 ) ;
277
+
278
+ let padding = raw + self . seen_newlines ;
265
279
if let Some ( & ( pos, maybe) ) = self . cur . peek ( ) {
266
280
if c == maybe {
267
281
self . cur . next ( ) ;
268
282
} else {
283
+ let pos = pos + padding + 1 ;
269
284
self . err ( format ! ( "expected `{:?}`, found `{:?}`" , c, maybe) ,
270
285
format ! ( "expected `{}`" , c) ,
271
- pos + 1 ,
272
- pos + 1 ) ;
286
+ pos,
287
+ pos) ;
273
288
}
274
289
} else {
275
290
let msg = format ! ( "expected `{:?}` but string was terminated" , c) ;
276
- let pos = self . input . len ( ) + 1 ; // point at closing `"`
291
+ // point at closing `"`, unless the last char is `\n` to account for `println`
292
+ let pos = match self . input . chars ( ) . last ( ) {
293
+ Some ( '\n' ) => self . input . len ( ) ,
294
+ _ => self . input . len ( ) + 1 ,
295
+ } ;
277
296
if c == '}' {
278
297
self . err_with_note ( msg,
279
298
format ! ( "expected `{:?}`" , c) ,
280
299
"if you intended to print `{`, you can escape it using `{{`" ,
281
- pos,
282
- pos) ;
300
+ pos + padding ,
301
+ pos + padding ) ;
283
302
} else {
284
303
self . err ( msg, format ! ( "expected `{:?}`" , c) , pos, pos) ;
285
304
}
@@ -536,7 +555,7 @@ mod tests {
536
555
use super :: * ;
537
556
538
557
fn same ( fmt : & ' static str , p : & [ Piece < ' static > ] ) {
539
- let parser = Parser :: new ( fmt) ;
558
+ let parser = Parser :: new ( fmt, None ) ;
540
559
assert ! ( parser. collect:: <Vec <Piece <' static >>>( ) == p) ;
541
560
}
542
561
@@ -552,7 +571,7 @@ mod tests {
552
571
}
553
572
554
573
fn musterr ( s : & str ) {
555
- let mut p = Parser :: new ( s) ;
574
+ let mut p = Parser :: new ( s, None ) ;
556
575
p. next ( ) ;
557
576
assert ! ( !p. errors. is_empty( ) ) ;
558
577
}
0 commit comments