mirror of
https://github.com/zaphar/kitchen.git
synced 2025-07-22 19:40:14 -04:00
Better parser errors
This commit is contained in:
parent
78921d973c
commit
b46e5746b9
@ -16,7 +16,7 @@ use std::time::Duration;
|
|||||||
|
|
||||||
use abortable_parser::{
|
use abortable_parser::{
|
||||||
ascii_digit, consume_all, discard, do_each, either, eoi, make_fn, must, not, optional, peek,
|
ascii_digit, consume_all, discard, do_each, either, eoi, make_fn, must, not, optional, peek,
|
||||||
repeat, separated, text_token, trap, until, Result, StrIter,
|
repeat, separated, text_token, trap, until, with_err, Result, StrIter,
|
||||||
};
|
};
|
||||||
use inflector::Inflector;
|
use inflector::Inflector;
|
||||||
use num_rational::Ratio;
|
use num_rational::Ratio;
|
||||||
@ -37,7 +37,7 @@ pub fn as_recipe(i: &str) -> std::result::Result<Recipe, String> {
|
|||||||
make_fn!(
|
make_fn!(
|
||||||
pub recipe<StrIter, Recipe>,
|
pub recipe<StrIter, Recipe>,
|
||||||
do_each!(
|
do_each!(
|
||||||
title => title,
|
title => must!(title),
|
||||||
_ => optional!(para_separator),
|
_ => optional!(para_separator),
|
||||||
desc => optional!(do_each!(
|
desc => optional!(do_each!(
|
||||||
_ => peek!(not!(step_prefix)),
|
_ => peek!(not!(step_prefix)),
|
||||||
@ -127,7 +127,7 @@ make_fn!(
|
|||||||
pub step<StrIter, Step>,
|
pub step<StrIter, Step>,
|
||||||
do_each!(
|
do_each!(
|
||||||
dur => step_prefix,
|
dur => step_prefix,
|
||||||
ingredients => must!(ingredient_list),
|
ingredients => with_err!(must!(ingredient_list), "Missing ingredient list"),
|
||||||
_ => para_separator,
|
_ => para_separator,
|
||||||
desc => description,
|
desc => description,
|
||||||
_ => either!(discard!(para_separator), eoi),
|
_ => either!(discard!(para_separator), eoi),
|
||||||
@ -138,7 +138,7 @@ make_fn!(
|
|||||||
make_fn!(
|
make_fn!(
|
||||||
pub step_list<StrIter, Vec<Step>>,
|
pub step_list<StrIter, Vec<Step>>,
|
||||||
do_each!(
|
do_each!(
|
||||||
first_step => must!(step),
|
first_step => with_err!(must!(step), "Missing recipe steps"),
|
||||||
rest => repeat!(step),
|
rest => repeat!(step),
|
||||||
({
|
({
|
||||||
let mut steps = vec![first_step];
|
let mut steps = vec![first_step];
|
||||||
@ -303,6 +303,21 @@ pub fn measure(i: StrIter) -> abortable_parser::Result<StrIter, Measure> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn normalize_name(name: &str) -> String {
|
||||||
|
let parts: Vec<&str> = name.split_whitespace().collect();
|
||||||
|
if parts.len() >= 2 {
|
||||||
|
let mut prefix = parts[0..parts.len() - 1].join(" ");
|
||||||
|
// NOTE(jwall): The below unwrap is safe because of the length
|
||||||
|
// check above.
|
||||||
|
let last = parts.last().unwrap();
|
||||||
|
let normalized = last.to_singular();
|
||||||
|
prefix.push(' ');
|
||||||
|
prefix.push_str(&normalized);
|
||||||
|
return prefix;
|
||||||
|
}
|
||||||
|
return name.trim().to_owned();
|
||||||
|
}
|
||||||
|
|
||||||
make_fn!(
|
make_fn!(
|
||||||
pub ingredient_name<StrIter, String>,
|
pub ingredient_name<StrIter, String>,
|
||||||
do_each!(
|
do_each!(
|
||||||
@ -310,7 +325,7 @@ make_fn!(
|
|||||||
discard!(text_token!("\n")),
|
discard!(text_token!("\n")),
|
||||||
eoi,
|
eoi,
|
||||||
discard!(text_token!("(")))),
|
discard!(text_token!("(")))),
|
||||||
(name.trim().to_singular())
|
(normalize_name(name))
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -318,8 +333,8 @@ make_fn!(
|
|||||||
ingredient_modifier<StrIter, &str>,
|
ingredient_modifier<StrIter, &str>,
|
||||||
do_each!(
|
do_each!(
|
||||||
_ => text_token!("("),
|
_ => text_token!("("),
|
||||||
modifier => until!(text_token!(")")),
|
modifier => must!(until!(text_token!(")"))),
|
||||||
_ => text_token!(")"),
|
_ => must!(text_token!(")")),
|
||||||
(modifier)
|
(modifier)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -466,3 +466,33 @@ until thickened. Set aside to cool.
|
|||||||
err => assert!(false, "{:?}", err),
|
err => assert!(false, "{:?}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_recipe_missing_steps_parse_failure() {
|
||||||
|
let recipe = "title: gooey apple bake
|
||||||
|
|
||||||
|
A simple gooey apple bake recipe.
|
||||||
|
";
|
||||||
|
match parse::recipe(StrIter::new(recipe)) {
|
||||||
|
ParseResult::Abort(e) => {
|
||||||
|
assert_eq!(e.get_msg(), "Missing recipe steps");
|
||||||
|
}
|
||||||
|
other => assert!(false, "{:?}", other),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_step_no_ingredients_parse_failure() {
|
||||||
|
let step = "step:
|
||||||
|
|
||||||
|
step: ";
|
||||||
|
match parse::step(StrIter::new(step)) {
|
||||||
|
ParseResult::Abort(e) => {
|
||||||
|
eprintln!("err: {:?}", e);
|
||||||
|
assert_eq!(e.get_msg(), "Missing ingredient list");
|
||||||
|
}
|
||||||
|
other => {
|
||||||
|
assert!(false, "{:?}", other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user