@@ -210,7 +210,7 @@ pub struct Tokenizer<'a> {
210210 /// Counted in bytes, not code points. From 0.
211211 position : usize ,
212212 /// Cache for `source_location()`
213- last_known_line_break : Cell < ( usize , usize ) > ,
213+ last_known_source_location : Cell < ( SourcePosition , SourceLocation ) > ,
214214 var_functions : VarFunctions ,
215215}
216216
@@ -228,7 +228,8 @@ impl<'a> Tokenizer<'a> {
228228 Tokenizer {
229229 input : input,
230230 position : 0 ,
231- last_known_line_break : Cell :: new ( ( 1 , 0 ) ) ,
231+ last_known_source_location : Cell :: new ( ( SourcePosition ( 0 ) ,
232+ SourceLocation { line : 1 , column : 1 } ) ) ,
232233 var_functions : VarFunctions :: DontCare ,
233234 }
234235 }
@@ -278,37 +279,33 @@ impl<'a> Tokenizer<'a> {
278279
279280 pub fn source_location ( & self , position : SourcePosition ) -> SourceLocation {
280281 let target = position. 0 ;
281- let mut line_number ;
282+ let mut location ;
282283 let mut position;
283- let ( last_known_line_number , position_after_last_known_newline ) =
284- self . last_known_line_break . get ( ) ;
285- if target >= position_after_last_known_newline {
286- position = position_after_last_known_newline ;
287- line_number = last_known_line_number ;
284+ let ( SourcePosition ( last_known_position ) , last_known_location ) =
285+ self . last_known_source_location . get ( ) ;
286+ if target >= last_known_position {
287+ position = last_known_position ;
288+ location = last_known_location ;
288289 } else {
290+ // For now we’re only traversing the source *forwards* to count newlines.
291+ // So if the requested position is before the last known one,
292+ // start over from the beginning.
289293 position = 0 ;
290- line_number = 1 ;
294+ location = SourceLocation { line : 1 , column : 1 } ;
291295 }
292296 let mut source = & self . input [ position..target] ;
293- while let Some ( newline_position) = source. find ( & [ '\n' , '\r' , '\x0C' ] [ .. ] ) {
297+ while let Some ( newline_position) = source. find ( |c| matches ! ( c , '\n' | '\r' | '\x0C' ) ) {
294298 let offset = newline_position +
295- if source[ newline_position..] . starts_with ( "\r \n " ) {
296- 2
297- } else {
298- 1
299- } ;
299+ if source[ newline_position..] . starts_with ( "\r \n " ) { 2 } else { 1 } ;
300300 source = & source[ offset..] ;
301301 position += offset;
302- line_number += 1 ;
302+ location. line += 1 ;
303+ location. column = 1 ;
303304 }
304305 debug_assert ! ( position <= target) ;
305- self . last_known_line_break . set ( ( line_number, position) ) ;
306- SourceLocation {
307- line : line_number,
308- // `target == position` when `target` is at the beginning of the line,
309- // so add 1 so that the column numbers start at 1.
310- column : target - position + 1 ,
311- }
306+ location. column += target - position;
307+ self . last_known_source_location . set ( ( SourcePosition ( target) , location) ) ;
308+ location
312309 }
313310
314311 #[ inline]
@@ -371,7 +368,7 @@ pub struct SourceLocation {
371368 /// The line number, starting at 1 for the first line.
372369 pub line : usize ,
373370
374- /// The column number within a line, starting at 1 for the character of the line.
371+ /// The column number within a line, starting at 1 for first the character of the line.
375372 pub column : usize ,
376373}
377374
0 commit comments