Add .ignore() for convenience
This commit is contained in:
parent
f03b303bdb
commit
eadba42762
@ -1,5 +1,5 @@
|
||||
fn main() {
|
||||
let src = "log(2 + 4, variable)";
|
||||
let src = "log(1, 2)";
|
||||
let ast = pivot::parse(src);
|
||||
println!("{}", ast);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ pub enum ParserKind {
|
||||
Regex(Regex),
|
||||
Constant(String),
|
||||
And,
|
||||
Ignore(bool),
|
||||
Ignore,
|
||||
Or,
|
||||
Repeat(usize),
|
||||
RepeatRange(Range<usize>),
|
||||
@ -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,6 +101,20 @@ impl Parser {
|
||||
}
|
||||
Constant(constant) => Ok((constant.clone(), s)),
|
||||
And => {
|
||||
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 (lmatched, lrest) = self.subparsers[0].parse(s)?;
|
||||
let (rmatched, rrest) = self.subparsers[1].parse(lrest)?;
|
||||
Ok((
|
||||
@ -103,15 +122,9 @@ impl Parser {
|
||||
rrest,
|
||||
))
|
||||
}
|
||||
Ignore(before) => {
|
||||
if *before {
|
||||
let (_, rest) = self.subparsers[0].parse(s)?;
|
||||
self.subparsers[1].parse(rest)
|
||||
} else {
|
||||
let (matched, rest) = self.subparsers[0].parse(s)?;
|
||||
let (_, rest) = self.subparsers[1].parse(rest)?;
|
||||
Ok((matched, rest))
|
||||
}
|
||||
Ignore => {
|
||||
self.subparsers[0].parse(s)
|
||||
}
|
||||
Or => {
|
||||
if let Ok(lresult) = self.subparsers[0].parse(s.clone()) {
|
||||
@ -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 {
|
||||
|
@ -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::<Vec<String>>(&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::<Vec<String>>(&matched)?;
|
||||
|
Loading…
x
Reference in New Issue
Block a user