From eadba427627516003faa4a933078dd1053671014 Mon Sep 17 00:00:00 2001 From: Garen Tyler Date: Wed, 2 Dec 2020 11:43:23 -0700 Subject: [PATCH] Add .ignore() for convenience --- src/main.rs | 2 +- src/parse/combinators.rs | 55 ++++++++++++++++++++++------------------ src/parse/mod.rs | 25 +++++++++--------- 3 files changed, 44 insertions(+), 38 deletions(-) diff --git a/src/main.rs b/src/main.rs index 3d34452..155dfb9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ fn main() { - let src = "log(2 + 4, variable)"; + let src = "log(1, 2)"; let ast = pivot::parse(src); println!("{}", ast); } diff --git a/src/parse/combinators.rs b/src/parse/combinators.rs index c60fb13..76044e4 100644 --- a/src/parse/combinators.rs +++ b/src/parse/combinators.rs @@ -8,7 +8,7 @@ pub enum ParserKind { Regex(Regex), Constant(String), And, - Ignore(bool), + Ignore, Or, Repeat(usize), RepeatRange(Range), @@ -29,7 +29,7 @@ impl std::fmt::Display for ParserKind { Regex(r) => write!(f, "Regex /{}/", r.as_str()), Constant(c) => write!(f, "Constant \"{}\"", c), And => write!(f, "And"), - Ignore(b) => write!(f, "Ignore{}", if *b { "Before" } else { "After" }), + Ignore => write!(f, "Ignore"), Or => write!(f, "Or"), Repeat(num) => write!(f, "Repeat {}", num), RepeatRange(range) => write!(f, "RepeatRange {:?}", range), @@ -47,7 +47,7 @@ impl Clone for ParserKind { Regex(r) => Regex(r.clone()), Constant(c) => Constant(c.clone()), And => And, - Ignore(b) => Ignore(*b), + Ignore => Ignore, Or => Or, Repeat(num) => Repeat(num.clone()), RepeatRange(range) => RepeatRange(range.clone()), @@ -57,6 +57,11 @@ impl Clone for ParserKind { } } } +impl PartialEq for ParserKind { + fn eq(&self, other: &ParserKind) -> bool { + format!("{}", self) == format!("{}", other) + } +} #[derive(Debug, Clone)] pub struct Parser { @@ -96,23 +101,31 @@ impl Parser { } Constant(constant) => Ok((constant.clone(), s)), And => { - let (lmatched, lrest) = self.subparsers[0].parse(s)?; - let (rmatched, rrest) = self.subparsers[1].parse(lrest)?; - Ok(( - to_string(&vec![lmatched.clone(), rmatched.clone()]).unwrap(), - rrest, - )) - } - Ignore(before) => { - if *before { + if self.subparsers[0].kind == Ignore + && self.subparsers[1].kind == Ignore { + Ok(("".into(), s)) + } else if self.subparsers[0].kind == Ignore { let (_, rest) = self.subparsers[0].parse(s)?; self.subparsers[1].parse(rest) + } else if self.subparsers[1].kind == Ignore { + let (matched, lrest) = self.subparsers[0].parse(s.clone())?; + if let Ok((_, rest)) = self.subparsers[1].parse(lrest) { + Ok((matched, rest)) + } else { + Err(s) + } } else { - let (matched, rest) = self.subparsers[0].parse(s)?; - let (_, rest) = self.subparsers[1].parse(rest)?; - Ok((matched, rest)) + let (lmatched, lrest) = self.subparsers[0].parse(s)?; + let (rmatched, rrest) = self.subparsers[1].parse(lrest)?; + Ok(( + to_string(&vec![lmatched.clone(), rmatched.clone()]).unwrap(), + rrest, + )) } } + Ignore => { + self.subparsers[0].parse(s) + } Or => { if let Ok(lresult) = self.subparsers[0].parse(s.clone()) { Ok(lresult) @@ -213,16 +226,10 @@ impl Parser { subparsers: vec![self, r], } } - pub fn ignore_before(self, r: Parser) -> Parser { + pub fn ignore(self) -> Parser { Parser { - kind: ParserKind::Ignore(true), - subparsers: vec![self, r], - } - } - pub fn ignore_after(self, r: Parser) -> Parser { - Parser { - kind: ParserKind::Ignore(false), - subparsers: vec![self, r], + kind: ParserKind::Ignore, + subparsers: vec![self], } } pub fn or(self, r: Parser) -> Parser { diff --git a/src/parse/mod.rs b/src/parse/mod.rs index af4781b..a779167 100644 --- a/src/parse/mod.rs +++ b/src/parse/mod.rs @@ -14,7 +14,7 @@ fn parse_expression(src: String) -> Result<(String, String), String> { let ignored = whitespace.or(comments).repeat_range(0..usize::MAX); // Token parser constructor. let i = ignored.clone(); - let token = move |pattern: &str| i.clone().ignore_before(Parser::regex(pattern)); + let token = move |pattern: &str| i.clone().ignore().and(Parser::regex(pattern)); // Token helper parsers. let FUNCTION = Parser::regex(r"function\b").or(ignored.clone()); let IF = token(r"if\b"); @@ -73,11 +73,10 @@ fn parse_expression(src: String) -> Result<(String, String), String> { // Expression parser. let expression = Parser::custom(parse_expression); // Call parser. - let args = expression - .clone() + let args = expression.clone() .and( - COMMA - .ignore_before(expression.clone()) + COMMA.clone().ignore() + .and(expression.clone()) .repeat_range(0..usize::MAX), ) .map(|matched| { @@ -90,11 +89,10 @@ fn parse_expression(src: String) -> Result<(String, String), String> { } Ok(to_string(&args)?) }); - let call = IDENTIFIER - .clone() - .ignore_after(LEFT_PAREN.clone()) + let call = IDENTIFIER.clone() + .and(LEFT_PAREN.clone().ignore()) .and(args.clone()) - .ignore_after(RIGHT_PAREN.clone()) + .and(RIGHT_PAREN.clone().ignore()) .map(|matched| { let data = from_str::>(&matched)?; let callee = data[0].clone(); @@ -112,10 +110,11 @@ fn parse_expression(src: String) -> Result<(String, String), String> { .clone() .or(IDENTIFIER.clone()) .or(NUMBER.clone()) - .or(LEFT_PAREN - .clone() - .ignore_before(expression.clone()) - .ignore_after(RIGHT_PAREN.clone())); + .or( + LEFT_PAREN.clone().ignore() + .and(expression.clone()) + .and(RIGHT_PAREN.clone().ignore()) + ); // Unary operator parsers. let unary = NOT.clone().optional().and(atom.clone()).map(|matched| { let data = from_str::>(&matched)?;