Skip to content

Commit

Permalink
Fix line/column position for strings containing \r\n
Browse files Browse the repository at this point in the history
Fixes #153
  • Loading branch information
kevinmehall committed Jan 22, 2017
1 parent 21bcb88 commit 078f352
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 17 deletions.
2 changes: 2 additions & 0 deletions peg-tests/src/test_grammar.rustpeg
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,5 @@ pub infix_arith -> i64 = #infix<number> {
issue152 -> i32 // a
= "5" { 5 //b
}

pub error_pos = ("a" / "\n" / "\r")*
21 changes: 21 additions & 0 deletions peg-tests/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,24 @@ fn test_infix_arith() {
assert_eq!(infix_arith("2+2^2^2^2/2+2"), Ok(32772));
assert_eq!(infix_arith("1024/2/2/2+1"), Ok(129));
}

#[test]
fn test_error_pos() {
let err = error_pos("aab\n").unwrap_err();
assert_eq!(err.line, 1);
assert_eq!(err.column, 3);
assert_eq!(err.offset, 2);
assert_eq!(err.expected, ["\r", "\n", "a"].iter().map(|x| *x).collect());

let err = error_pos("aa\naaaa\nbaaa\n").unwrap_err();
assert_eq!(err.line, 3);
assert_eq!(err.column, 1);

let err = error_pos("aa\naaaa\naaab\naa").unwrap_err();
assert_eq!(err.line, 3);
assert_eq!(err.column, 4);

let err = error_pos("aa\r\naaaa\r\naaab\r\naa").unwrap_err();
assert_eq!(err.line, 3);
assert_eq!(err.column, 4);
}
10 changes: 4 additions & 6 deletions src/grammar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,10 @@ input : & str , state : & mut ParseState , pos : usize ) -> RuleResult < ( )
let ( _ , next ) = char_range_at ( input , pos ) ; Matched ( next , ( ) ) }
else { state . mark_failure ( pos , "<character>" ) } } fn pos_to_line (
input : & str , pos : usize ) -> ( usize , usize ) {
let mut remaining = pos ; let mut lineno : usize = 1 ; for line in input .
lines ( ) {
let line_length = line . len ( ) + 1 ; if remaining < line_length {
return ( lineno , remaining + 1 ) ; } remaining -= line_length ; lineno += 1 ;
} return ( lineno , remaining + 1 ) ; } impl < 'input > ParseState < 'input >
{
let before = & input [ .. pos ] ; let line = before . as_bytes ( ) . iter (
) . filter ( | && c | c == b'\n' ) . count ( ) + 1 ; let col = before . chars
( ) . rev ( ) . take_while ( | & c | c != '\n' ) . count ( ) + 1 ; (
line , col ) } impl < 'input > ParseState < 'input > {
fn mark_failure ( & mut self , pos : usize , expected : & 'static str ) ->
RuleResult < ( ) > {
if self . suppress_fail == 0 {
Expand Down
15 changes: 4 additions & 11 deletions src/translate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,17 +221,10 @@ static HELPERS: &'static str = stringify! {
}

fn pos_to_line(input: &str, pos: usize) -> (usize, usize) {
let mut remaining = pos;
let mut lineno: usize = 1;
for line in input.lines() {
let line_length = line.len() + 1;
if remaining < line_length {
return (lineno, remaining + 1);
}
remaining -= line_length;
lineno += 1;
}
return (lineno, remaining + 1);
let before = &input[..pos];
let line = before.as_bytes().iter().filter(|&&c| c == b'\n').count() + 1;
let col = before.chars().rev().take_while(|&c| c != '\n').count() + 1;
(line, col)
}

impl<'input> ParseState<'input> {
Expand Down

0 comments on commit 078f352

Please sign in to comment.