Skip to content

Commit

Permalink
fix(parser): properly handle spaces and multilines
Browse files Browse the repository at this point in the history
  • Loading branch information
woile committed Oct 7, 2024
1 parent cd3bd3c commit ff4cfe5
Showing 1 changed file with 16 additions and 3 deletions.
19 changes: 16 additions & 3 deletions crates/recipe-parser/src/parser.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use std::fmt::Display;

use winnow::ascii::{line_ending, multispace0, space0, space1};
use winnow::ascii::{line_ending, multispace0, multispace1, space0, space1};
use winnow::combinator::{alt, cut_err, delimited, opt, preceded, repeat, rest};
use winnow::error::{ContextError, ParseError, StrContext, StrContextValue};
use winnow::stream::AsChar;
use winnow::token::{take_till, take_until, take_while};
use winnow::{Located, PResult, Parser};

Expand Down Expand Up @@ -156,7 +155,7 @@ fn parse_recipe_ref<'a>(

/// Tokens are separated into words
fn parse_word<'a>(input: &mut Input<'a>) -> PResult<&'a str> {
take_till(1.., AsChar::is_space).parse_next(input)
take_till(1.., (' ', '\t', '\r', '\n')).parse_next(input)
}

fn parse_metadata<'a>(input: &mut Input<'a>) -> PResult<(&'a str, &'a str)> {
Expand Down Expand Up @@ -289,6 +288,7 @@ pub fn recipe_value<'a>(input: &mut Input<'a>) -> PResult<Token<'a>> {
"(".map(|v| Token::Word(v)),
parse_word.map(|v| Token::Word(v)),
space1.map(|v| Token::Space(v)),
multispace1.map(|v| Token::Space(v)),
))
.parse_next(input)
}
Expand Down Expand Up @@ -583,6 +583,19 @@ mod test {
println!("{:?}", recipe);
}

#[rstest]
#[case(" ", vec![Token::Space(" ")])]
#[case("\n\nhello", vec![Token::Space("\n\n"), Token::Word("hello")])]
#[case("hello\n", vec![Token::Word("hello"), Token::Space("\n")])]
#[case(">> tags: hello\n\nhello", vec![Token::Metadata {key: "tags", value: "hello"}, Token::Space("\n\n"), Token::Word("hello")])]
#[case(">> source: https://hello.com\n>> tags: hello\n", vec![Token::Metadata {key: "source", value: "https://hello.com"}, Token::Space("\n"), Token::Metadata {key: "tags", value: "hello"}, Token::Space("\n")])]
#[case("{holis}(100 gr)", vec![Token::Ingredient { name: "holis", quantity: Some("100"), unit: Some("gr") }])]
fn test_recipe_cases_ok(#[case] input: &str, #[case] expected: Vec<Token>) {
let mut input = Located::new(input);
let token = recipe(&mut input).expect("failed to parse token");
assert_eq!(token, expected)
}

#[rstest]
#[case("Foo. ")]
#[case("Foo.")]
Expand Down

0 comments on commit ff4cfe5

Please sign in to comment.