From b21bdd025264d640535604134d561a04b44882a5 Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Tue, 2 Nov 2021 21:09:00 -0400 Subject: [PATCH] disable macro-error diagnostic for this workspace. --- .vscode/settings.json | 5 +++ recipes/src/lib.rs | 12 +++++-- recipes/src/parse.rs | 74 +++++++++++++++++++++++++++++++++++++- recipes/src/test.rs | 84 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 172 insertions(+), 3 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..9f01ac6 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "rust-analyzer.diagnostics.disabled": [ + "macro-error" + ] +} \ No newline at end of file diff --git a/recipes/src/lib.rs b/recipes/src/lib.rs index 36d4c0b..7167a37 100644 --- a/recipes/src/lib.rs +++ b/recipes/src/lib.rs @@ -11,7 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -mod parse; +pub mod parse; pub mod unit; use std::collections::BTreeMap; @@ -20,7 +20,7 @@ use std::str::FromStr; use chrono::NaiveDate; use uuid::{self, Uuid}; -use parse::{ingredient, measure}; +use parse::*; use unit::*; #[derive(Debug, Clone, PartialEq)] @@ -141,6 +141,14 @@ impl Step { } } + pub fn with_ingredients(mut self, ingredients: Iter) -> Step + where + Iter: IntoIterator, + { + self.add_ingredients(ingredients); + self + } + pub fn add_ingredients(&mut self, ingredients: Iter) where Iter: IntoIterator, diff --git a/recipes/src/parse.rs b/recipes/src/parse.rs index 734e6fb..8813089 100644 --- a/recipes/src/parse.rs +++ b/recipes/src/parse.rs @@ -21,9 +21,81 @@ use num_rational::Ratio; use crate::{ unit::{Measure, Measure::*, Quantity, VolumeMeasure::*}, - Ingredient, + Ingredient, Recipe, Step, }; +make_fn!( + pub recipe, + do_each!( + title => title, + _ => optional!(para_separator), + desc => optional!(do_each!( + _ => peek!(not!(step_prefix)), + desc => description, + (desc) + )), + _ => optional!(para_separator), + steps => step_list, + (Recipe::new(title, desc).with_steps(steps)) + ) +); + +make_fn!( + pub title, + do_each!( + _ => text_token!("title:"), + _ => optional!(ws), + title => until!(text_token!("\n")), + _ => text_token!("\n"), + (title) + ) +); + +make_fn!( + para_separator, + do_each!( + _ => text_token!("\n"), + _ => optional!(ws), + _ => text_token!("\n"), + ("") + ) +); + +make_fn!( + pub description, + until!(either!( + discard!(para_separator), + eoi, + )) +); + +make_fn!( + pub step_prefix, + do_each!( + _ => text_token!("step:"), + _ => optional!(ws), + _ => para_separator, + ("") + ) +); + +make_fn!( + pub step, + do_each!( + _ => step_prefix, + ingredients => ingredient_list, + _ => para_separator, + desc => description, + _ => either!(discard!(para_separator), eoi), + (Step::new(None, desc).with_ingredients(ingredients)) + ) +); + +make_fn!( + pub step_list>, + repeat!(step) +); + make_fn!(ws, consume_all!(either!( text_token!(" "), diff --git a/recipes/src/test.rs b/recipes/src/test.rs index b4bb13e..c983b2e 100644 --- a/recipes/src/test.rs +++ b/recipes/src/test.rs @@ -338,3 +338,87 @@ fn test_ingredient_list_parse() { } } } + +#[test] +fn test_single_step() { + let step = "step: + +1 tbsp flour +2 tbsp butter +1 cup apple (chopped) + +Saute apples in butter until golden brown. Add flour slowly +until thickens. Set aside to cool."; + + match parse::step(StrIter::new(step)) { + ParseResult::Complete(_, step) => { + assert_eq!(step.ingredients.len(), 3); + assert_eq!( + step.instructions, + "Saute apples in butter until golden brown. Add flour slowly +until thickens. Set aside to cool." + ); + } + err => assert!(false, "{:?}", err), + } +} + +#[test] +fn test_multiple_steps() { + let steps = "step: + +1 tbsp flour +2 tbsp butter +1 cup apple (chopped) + +Saute apples in butter until golden brown. Add flour slowly +until thickens. Set aside to cool. + +step: + +1 tbsp flour +2 tbsp butter + +Saute apples in butter until golden brown. Add flour slowly +until thickened. Set aside to cool. +"; + + match parse::step_list(StrIter::new(steps)) { + ParseResult::Complete(_, steps) => { + assert_eq!(steps.len(), 2); + } + err => assert!(false, "{:?}", err), + } +} + +#[test] +fn test_recipe_multiple_steps() { + let recipe = "title: gooey apple bake + +A simple gooey apple bake recipe. + +step: + +1 tbsp flour +2 tbsp butter +1 cup apple (chopped) + +Saute apples in butter until golden brown. Add flour slowly +until thickens. Set aside to cool. + +step: + +1 tbsp flour +2 tbsp butter + +Saute apples in butter until golden brown. Add flour slowly +until thickened. Set aside to cool. +"; + + match parse::recipe(StrIter::new(recipe)) { + ParseResult::Complete(_, recipe) => { + assert_eq!(recipe.steps.len(), 2); + } + err => assert!(false, "{:?}", err), + } +}