Add .ignore() for convenience

This commit is contained in:
Garen Tyler 2020-12-02 11:43:23 -07:00
parent f03b303bdb
commit eadba42762
3 changed files with 44 additions and 38 deletions

View File

@ -1,5 +1,5 @@
fn main() { fn main() {
let src = "log(2 + 4, variable)"; let src = "log(1, 2)";
let ast = pivot::parse(src); let ast = pivot::parse(src);
println!("{}", ast); println!("{}", ast);
} }

View File

@ -8,7 +8,7 @@ pub enum ParserKind {
Regex(Regex), Regex(Regex),
Constant(String), Constant(String),
And, And,
Ignore(bool), Ignore,
Or, Or,
Repeat(usize), Repeat(usize),
RepeatRange(Range<usize>), RepeatRange(Range<usize>),
@ -29,7 +29,7 @@ impl std::fmt::Display for ParserKind {
Regex(r) => write!(f, "Regex /{}/", r.as_str()), Regex(r) => write!(f, "Regex /{}/", r.as_str()),
Constant(c) => write!(f, "Constant \"{}\"", c), Constant(c) => write!(f, "Constant \"{}\"", c),
And => write!(f, "And"), And => write!(f, "And"),
Ignore(b) => write!(f, "Ignore{}", if *b { "Before" } else { "After" }), Ignore => write!(f, "Ignore"),
Or => write!(f, "Or"), Or => write!(f, "Or"),
Repeat(num) => write!(f, "Repeat {}", num), Repeat(num) => write!(f, "Repeat {}", num),
RepeatRange(range) => write!(f, "RepeatRange {:?}", range), RepeatRange(range) => write!(f, "RepeatRange {:?}", range),
@ -47,7 +47,7 @@ impl Clone for ParserKind {
Regex(r) => Regex(r.clone()), Regex(r) => Regex(r.clone()),
Constant(c) => Constant(c.clone()), Constant(c) => Constant(c.clone()),
And => And, And => And,
Ignore(b) => Ignore(*b), Ignore => Ignore,
Or => Or, Or => Or,
Repeat(num) => Repeat(num.clone()), Repeat(num) => Repeat(num.clone()),
RepeatRange(range) => RepeatRange(range.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)] #[derive(Debug, Clone)]
pub struct Parser { pub struct Parser {
@ -96,23 +101,31 @@ impl Parser {
} }
Constant(constant) => Ok((constant.clone(), s)), Constant(constant) => Ok((constant.clone(), s)),
And => { And => {
let (lmatched, lrest) = self.subparsers[0].parse(s)?; if self.subparsers[0].kind == Ignore
let (rmatched, rrest) = self.subparsers[1].parse(lrest)?; && self.subparsers[1].kind == Ignore {
Ok(( Ok(("".into(), s))
to_string(&vec![lmatched.clone(), rmatched.clone()]).unwrap(), } else if self.subparsers[0].kind == Ignore {
rrest,
))
}
Ignore(before) => {
if *before {
let (_, rest) = self.subparsers[0].parse(s)?; let (_, rest) = self.subparsers[0].parse(s)?;
self.subparsers[1].parse(rest) 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 { } else {
let (matched, rest) = self.subparsers[0].parse(s)?; let (lmatched, lrest) = self.subparsers[0].parse(s)?;
let (_, rest) = self.subparsers[1].parse(rest)?; let (rmatched, rrest) = self.subparsers[1].parse(lrest)?;
Ok((matched, rest)) Ok((
to_string(&vec![lmatched.clone(), rmatched.clone()]).unwrap(),
rrest,
))
} }
} }
Ignore => {
self.subparsers[0].parse(s)
}
Or => { Or => {
if let Ok(lresult) = self.subparsers[0].parse(s.clone()) { if let Ok(lresult) = self.subparsers[0].parse(s.clone()) {
Ok(lresult) Ok(lresult)
@ -213,16 +226,10 @@ impl Parser {
subparsers: vec![self, r], subparsers: vec![self, r],
} }
} }
pub fn ignore_before(self, r: Parser) -> Parser { pub fn ignore(self) -> Parser {
Parser { Parser {
kind: ParserKind::Ignore(true), kind: ParserKind::Ignore,
subparsers: vec![self, r], subparsers: vec![self],
}
}
pub fn ignore_after(self, r: Parser) -> Parser {
Parser {
kind: ParserKind::Ignore(false),
subparsers: vec![self, r],
} }
} }
pub fn or(self, r: Parser) -> Parser { pub fn or(self, r: Parser) -> Parser {

View File

@ -14,7 +14,7 @@ fn parse_expression(src: String) -> Result<(String, String), String> {
let ignored = whitespace.or(comments).repeat_range(0..usize::MAX); let ignored = whitespace.or(comments).repeat_range(0..usize::MAX);
// Token parser constructor. // Token parser constructor.
let i = ignored.clone(); 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. // Token helper parsers.
let FUNCTION = Parser::regex(r"function\b").or(ignored.clone()); let FUNCTION = Parser::regex(r"function\b").or(ignored.clone());
let IF = token(r"if\b"); let IF = token(r"if\b");
@ -73,11 +73,10 @@ fn parse_expression(src: String) -> Result<(String, String), String> {
// Expression parser. // Expression parser.
let expression = Parser::custom(parse_expression); let expression = Parser::custom(parse_expression);
// Call parser. // Call parser.
let args = expression let args = expression.clone()
.clone()
.and( .and(
COMMA COMMA.clone().ignore()
.ignore_before(expression.clone()) .and(expression.clone())
.repeat_range(0..usize::MAX), .repeat_range(0..usize::MAX),
) )
.map(|matched| { .map(|matched| {
@ -90,11 +89,10 @@ fn parse_expression(src: String) -> Result<(String, String), String> {
} }
Ok(to_string(&args)?) Ok(to_string(&args)?)
}); });
let call = IDENTIFIER let call = IDENTIFIER.clone()
.clone() .and(LEFT_PAREN.clone().ignore())
.ignore_after(LEFT_PAREN.clone())
.and(args.clone()) .and(args.clone())
.ignore_after(RIGHT_PAREN.clone()) .and(RIGHT_PAREN.clone().ignore())
.map(|matched| { .map(|matched| {
let data = from_str::<Vec<String>>(&matched)?; let data = from_str::<Vec<String>>(&matched)?;
let callee = data[0].clone(); let callee = data[0].clone();
@ -112,10 +110,11 @@ fn parse_expression(src: String) -> Result<(String, String), String> {
.clone() .clone()
.or(IDENTIFIER.clone()) .or(IDENTIFIER.clone())
.or(NUMBER.clone()) .or(NUMBER.clone())
.or(LEFT_PAREN .or(
.clone() LEFT_PAREN.clone().ignore()
.ignore_before(expression.clone()) .and(expression.clone())
.ignore_after(RIGHT_PAREN.clone())); .and(RIGHT_PAREN.clone().ignore())
);
// Unary operator parsers. // Unary operator parsers.
let unary = NOT.clone().optional().and(atom.clone()).map(|matched| { let unary = NOT.clone().optional().and(atom.clone()).map(|matched| {
let data = from_str::<Vec<String>>(&matched)?; let data = from_str::<Vec<String>>(&matched)?;