Skip to content

Commit

Permalink
New primitive to consume empty lines (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
scouten authored Dec 27, 2023
1 parent ffb1b32 commit f197912
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 1 deletion.
15 changes: 15 additions & 0 deletions src/primitives/line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,21 @@ pub(crate) fn empty_line(input: Span<'_>) -> IResult<Span, Span> {
}
}

/// Consumes zero or more empty lines.
///
/// Returns the original input if any error occurs or no empty lines are found.
#[allow(dead_code)]
pub(crate) fn consume_empty_lines(mut input: Span<'_>) -> Span {
while !input.data().is_empty() {
match empty_line(input) {
Ok((rem, _)) => input = rem,
Err(_) => break,
}
}

input
}

fn trim_rem_start_matches<'a>(rem_inp: (Span<'a>, Span<'a>), c: char) -> (Span<'a>, Span<'a>) {
if let Some(rem) = rem_inp.0.strip_prefix(c) {
let prefix_len = rem_inp.0.len() - rem.len();
Expand Down
2 changes: 1 addition & 1 deletion src/primitives/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod line;
#[allow(unused_imports)]
pub(crate) use line::{empty_line, line, non_empty_line, normalized_line};
pub(crate) use line::{consume_empty_lines, empty_line, line, non_empty_line, normalized_line};

/// Represents a subset of the overall input stream.
///
Expand Down
88 changes: 88 additions & 0 deletions src/tests/primitives/line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,3 +445,91 @@ mod empty_line {
assert_eq!(expected_err, actual_err);
}
}

mod consume_empty_lines {
use crate::{primitives::consume_empty_lines, Span};

#[test]
fn empty_source() {
let rem = consume_empty_lines(Span::new("", true));
assert_eq!(rem, Span::new("", true));
}

#[test]
fn consumes_empty_line() {
let rem = consume_empty_lines(Span::new("\nabc", true));

assert_eq!(rem.line(), 2);
assert_eq!(rem.col(), 1);
assert_eq!(*rem.data(), "abc");
}

#[test]
fn doesnt_consume_non_empty_line() {
let rem = consume_empty_lines(Span::new("abc", true));
assert_eq!(rem, Span::new("abc", true));
}

#[test]
fn doesnt_consume_leading_space() {
let rem = consume_empty_lines(Span::new(" abc", true));
assert_eq!(rem, Span::new(" abc", true));
}

#[test]
fn consumes_line_with_only_spaces() {
let rem = consume_empty_lines(Span::new(" \nabc", true));

assert_eq!(rem.line(), 2);
assert_eq!(rem.col(), 1);
assert_eq!(*rem.data(), "abc");
}

#[test]
fn consumes_spaces_and_tabs() {
let rem = consume_empty_lines(Span::new(" \t \nabc", true));

assert_eq!(rem.line(), 2);
assert_eq!(rem.col(), 1);
assert_eq!(*rem.data(), "abc");
}

#[test]
fn consumes_multiple_lines() {
let rem = consume_empty_lines(Span::new("\n \t \n\nabc", true));

assert_eq!(rem.line(), 4);
assert_eq!(rem.col(), 1);
assert_eq!(*rem.data(), "abc");
}

#[test]
fn consumes_crlf() {
// Should consume \r\n sequence.

let rem = consume_empty_lines(Span::new(" \r\ndef", true));

assert_eq!(rem.line(), 2);
assert_eq!(rem.col(), 1);
assert_eq!(*rem.data(), "def");
}

#[test]
fn doesnt_consume_lfcr() {
// Should consume \n but not a subsequent \r.

let rem = consume_empty_lines(Span::new(" \n\rdef", true));

assert_eq!(rem.line(), 2);
assert_eq!(rem.col(), 1);
assert_eq!(*rem.data(), "\rdef");
}

#[test]
fn standalone_cr_doesnt_end_line() {
// A "line" with \r and no immediate \n is not considered empty.

let rem = consume_empty_lines(Span::new(" \rdef", true));
assert_eq!(rem, Span::new(" \rdef", true));
}
}

0 comments on commit f197912

Please sign in to comment.