Add .ignore() for convenience
This commit is contained in:
parent
f03b303bdb
commit
eadba42762
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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)?;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user