From 924b10b0cd6c09fa7afa58e6f7a068646d1e56af Mon Sep 17 00:00:00 2001 From: Joris Date: Mon, 14 Oct 2024 22:30:47 +0200 Subject: Use nom to parse lines --- src/deck.rs | 73 +++++++++++++++++++++---------------------------------------- 1 file changed, 25 insertions(+), 48 deletions(-) (limited to 'src/deck.rs') diff --git a/src/deck.rs b/src/deck.rs index 4491d9b..3fff77f 100644 --- a/src/deck.rs +++ b/src/deck.rs @@ -1,4 +1,5 @@ -use crate::{model::Line, util::serialization}; +use crate::model::Line; +use crate::parser; use anyhow::{Error, Result}; use std::fmt; use std::fs::File; @@ -7,13 +8,17 @@ use std::path::Path; #[derive(Debug, Clone)] struct ParseError { - line: usize, - message: String, + line: String, + line_number: usize, } impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Line {}: {}", self.line, self.message) + write!( + f, + "Error parsing line {}:\n\n{}", + self.line_number, self.line + ) } } @@ -40,39 +45,12 @@ pub fn read_file(path: &str) -> Result> { } fn read_line(index: usize, line: &str) -> Result> { - let line = line.trim(); - - if line.starts_with('#') || line.is_empty() { - Ok(None) - } else if !line.starts_with('-') { - Err(Error::from(ParseError { - line: index + 1, - message: "an entry should starts with “-”.".to_string(), - })) - } else { - let without_minus = line.split('-').skip(1).collect::>().join("-"); - let without_comment = without_minus.split('#').collect::>()[0].trim(); - let translation = without_comment.split(':').collect::>(); - if translation.len() != 2 { - Err(Error::from(ParseError { - line: index + 1, - message: "an entry should contain two parts separated by “:”.".to_string(), - })) - } else { - let t1 = translation[0].trim(); - let t2 = translation[1].trim(); - if t1.is_empty() || t2.is_empty() { - Err(Error::from(ParseError { - line: index + 1, - message: "an entry should contain two parts separated by “:”.".to_string(), - })) - } else { - Ok(Some(Line { - part_1: serialization::line_to_words(t1), - part_2: serialization::line_to_words(t2), - })) - } - } + match parser::parse_line(line) { + Ok(("", line)) => Ok(line), + _ => Err(Error::from(ParseError { + line_number: index + 1, + line: line.to_string(), + })), } } @@ -98,12 +76,11 @@ pub mod tests { #[test] fn errors() { - is_error("A : a"); - is_error("- A"); - is_error("- A -> a"); - is_error("- A : B : C"); - is_error("- : "); - is_error("- A : a\n-") + is_error("A"); + is_error("A -> a"); + is_error("A : B : C"); + is_error(":"); + is_error("A : a\n-") } #[test] @@ -117,19 +94,19 @@ pub mod tests { #[test] fn card() { - check("- A : a", &[(&["A"], &["a"])]); + check("A : a", &[(&["A"], &["a"])]); } #[test] fn cards() { - check("- A : a\n- B : b", &[(&["A"], &["a"]), (&["B"], &["b"])]); + check("A : a\nB : b", &[(&["A"], &["a"]), (&["B"], &["b"])]); } #[test] fn alternatives() { - check("- A : a1 | a2", &[(&["A"], &["a1", "a2"])]); - check("- A1 | A2 : a", &[(&["A1", "A2"], &["a"])]); - check("- A1 | A2 : a1 | a2", &[(&["A1", "A2"], &["a1", "a2"])]); + check("A : a1 | a2", &[(&["A"], &["a1", "a2"])]); + check("A1 | A2 : a", &[(&["A1", "A2"], &["a"])]); + check("A1 | A2 : a1 | a2", &[(&["A1", "A2"], &["a1", "a2"])]); } fn is_error(content: &str) { -- cgit v1.2.3