Use pratt parser for prefix logic
This commit is contained in:
parent
11d9a2f1c7
commit
23b0a5e5fc
2 changed files with 62 additions and 69 deletions
|
|
@ -59,34 +59,33 @@ variable = {
|
||||||
| "e"
|
| "e"
|
||||||
}
|
}
|
||||||
|
|
||||||
unop_neg = { "-" }
|
prefix_neg = { "-" }
|
||||||
unop_not = { "!" }
|
prefix_not = { "!" }
|
||||||
unop = _{ unop_neg | unop_not }
|
prefix = _{ prefix_neg | prefix_not }
|
||||||
|
|
||||||
op_add = { "+" }
|
infix_add = { "+" }
|
||||||
op_sub = { "-" }
|
infix_sub = { "-" }
|
||||||
op_mul = { "*" }
|
infix_mul = { "*" }
|
||||||
op_div = { "/" }
|
infix_div = { "/" }
|
||||||
op_mod = { "%" }
|
infix_mod = { "%" }
|
||||||
op_eq = { "=" }
|
infix_eq = { "=" }
|
||||||
op_neq = { "!=" }
|
infix_neq = { "!=" }
|
||||||
op_lt = { "<" }
|
infix_lt = { "<" }
|
||||||
op_lte = { "<=" }
|
infix_lte = { "<=" }
|
||||||
op_gt = { ">" }
|
infix_gt = { ">" }
|
||||||
op_gte = { ">=" }
|
infix_gte = { ">=" }
|
||||||
op_and = { "&" }
|
infix_and = { "&" }
|
||||||
op_or = { "|" }
|
infix_or = { "|" }
|
||||||
op_xor = { "^" }
|
infix_xor = { "^" }
|
||||||
op = _{
|
infix = _{
|
||||||
op_add | op_sub | op_mul | op_div | op_mod
|
infix_add | infix_sub | infix_mul | infix_div | infix_mod
|
||||||
| op_eq | op_neq | op_lt | op_lte | op_gt | op_gte
|
| infix_eq | infix_neq | infix_lt | infix_lte | infix_gt | infix_gte
|
||||||
| op_and | op_or | op_xor
|
| infix_and | infix_or | infix_xor
|
||||||
}
|
}
|
||||||
|
|
||||||
paren_expr = { "(" ~ expr ~ ")" }
|
paren_expr = { "(" ~ expr ~ ")" }
|
||||||
unop_expr = { unop ~ expr }
|
term = { number | boolean | variable | paren_expr }
|
||||||
term = { number | boolean | variable | paren_expr | unop_expr }
|
expr = { prefix* ~ term ~ (infix ~ prefix* ~ term)* }
|
||||||
expr = { term ~ (op ~ term)* }
|
|
||||||
|
|
||||||
date_fixed_start = { datum ~ delta? ~ time? }
|
date_fixed_start = { datum ~ delta? ~ time? }
|
||||||
date_fixed_end = { datum ~ delta? ~ time? | delta ~ time? | time }
|
date_fixed_end = { datum ~ delta? ~ time? | delta ~ time? | time }
|
||||||
|
|
|
||||||
|
|
@ -359,24 +359,6 @@ fn parse_variable(p: Pair<'_, Rule>) -> Var {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_unop_expr(p: Pair<'_, Rule>) -> Spanned<Expr> {
|
|
||||||
assert_eq!(p.as_rule(), Rule::unop_expr);
|
|
||||||
let span = (&p.as_span()).into();
|
|
||||||
|
|
||||||
let mut p = p.into_inner();
|
|
||||||
let p_op = p.next().unwrap();
|
|
||||||
let p_expr = p.next().unwrap();
|
|
||||||
assert_eq!(p.next(), None);
|
|
||||||
|
|
||||||
let inner = parse_expr(p_expr);
|
|
||||||
let expr = match p_op.as_rule() {
|
|
||||||
Rule::unop_neg => Expr::Neg(Box::new(inner)),
|
|
||||||
Rule::unop_not => Expr::Not(Box::new(inner)),
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
Spanned::new(span, expr)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_paren_expr(p: Pair<'_, Rule>) -> Spanned<Expr> {
|
fn parse_paren_expr(p: Pair<'_, Rule>) -> Spanned<Expr> {
|
||||||
assert_eq!(p.as_rule(), Rule::paren_expr);
|
assert_eq!(p.as_rule(), Rule::paren_expr);
|
||||||
let span = (&p.as_span()).into();
|
let span = (&p.as_span()).into();
|
||||||
|
|
@ -392,34 +374,43 @@ fn parse_term(p: Pair<'_, Rule>) -> Spanned<Expr> {
|
||||||
Rule::number => Spanned::new(span, Expr::Lit(parse_number(p).into())),
|
Rule::number => Spanned::new(span, Expr::Lit(parse_number(p).into())),
|
||||||
Rule::boolean => Spanned::new(span, Expr::Var(parse_boolean(p))),
|
Rule::boolean => Spanned::new(span, Expr::Var(parse_boolean(p))),
|
||||||
Rule::variable => Spanned::new(span, Expr::Var(parse_variable(p))),
|
Rule::variable => Spanned::new(span, Expr::Var(parse_variable(p))),
|
||||||
Rule::unop_expr => parse_unop_expr(p),
|
|
||||||
Rule::paren_expr => parse_paren_expr(p),
|
Rule::paren_expr => parse_paren_expr(p),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_op(l: Spanned<Expr>, p: Pair<'_, Rule>, r: Spanned<Expr>) -> Spanned<Expr> {
|
fn parse_prefix(p: Pair<'_, Rule>, s: Spanned<Expr>) -> Spanned<Expr> {
|
||||||
|
let span = s.span.join((&p.as_span()).into());
|
||||||
|
let expr = match p.as_rule() {
|
||||||
|
Rule::prefix_neg => Expr::Neg(Box::new(s)),
|
||||||
|
Rule::prefix_not => Expr::Not(Box::new(s)),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
Spanned::new(span, expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_infix(l: Spanned<Expr>, p: Pair<'_, Rule>, r: Spanned<Expr>) -> Spanned<Expr> {
|
||||||
let span = l.span.join(r.span);
|
let span = l.span.join(r.span);
|
||||||
let expr = match p.as_rule() {
|
let expr = match p.as_rule() {
|
||||||
// Integer-y operations
|
// Integer-y operations
|
||||||
Rule::op_add => Expr::Add(Box::new(l), Box::new(r)),
|
Rule::infix_add => Expr::Add(Box::new(l), Box::new(r)),
|
||||||
Rule::op_sub => Expr::Sub(Box::new(l), Box::new(r)),
|
Rule::infix_sub => Expr::Sub(Box::new(l), Box::new(r)),
|
||||||
Rule::op_mul => Expr::Mul(Box::new(l), Box::new(r)),
|
Rule::infix_mul => Expr::Mul(Box::new(l), Box::new(r)),
|
||||||
Rule::op_div => Expr::Div(Box::new(l), Box::new(r)),
|
Rule::infix_div => Expr::Div(Box::new(l), Box::new(r)),
|
||||||
Rule::op_mod => Expr::Mod(Box::new(l), Box::new(r)),
|
Rule::infix_mod => Expr::Mod(Box::new(l), Box::new(r)),
|
||||||
|
|
||||||
// Comparisons
|
// Comparisons
|
||||||
Rule::op_eq => Expr::Eq(Box::new(l), Box::new(r)),
|
Rule::infix_eq => Expr::Eq(Box::new(l), Box::new(r)),
|
||||||
Rule::op_neq => Expr::Neq(Box::new(l), Box::new(r)),
|
Rule::infix_neq => Expr::Neq(Box::new(l), Box::new(r)),
|
||||||
Rule::op_lt => Expr::Lt(Box::new(l), Box::new(r)),
|
Rule::infix_lt => Expr::Lt(Box::new(l), Box::new(r)),
|
||||||
Rule::op_lte => Expr::Lte(Box::new(l), Box::new(r)),
|
Rule::infix_lte => Expr::Lte(Box::new(l), Box::new(r)),
|
||||||
Rule::op_gt => Expr::Gt(Box::new(l), Box::new(r)),
|
Rule::infix_gt => Expr::Gt(Box::new(l), Box::new(r)),
|
||||||
Rule::op_gte => Expr::Gte(Box::new(l), Box::new(r)),
|
Rule::infix_gte => Expr::Gte(Box::new(l), Box::new(r)),
|
||||||
|
|
||||||
// Boolean-y operations
|
// Boolean-y operations
|
||||||
Rule::op_and => Expr::And(Box::new(l), Box::new(r)),
|
Rule::infix_and => Expr::And(Box::new(l), Box::new(r)),
|
||||||
Rule::op_or => Expr::Or(Box::new(l), Box::new(r)),
|
Rule::infix_or => Expr::Or(Box::new(l), Box::new(r)),
|
||||||
Rule::op_xor => Expr::Xor(Box::new(l), Box::new(r)),
|
Rule::infix_xor => Expr::Xor(Box::new(l), Box::new(r)),
|
||||||
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
@ -429,19 +420,22 @@ fn parse_op(l: Spanned<Expr>, p: Pair<'_, Rule>, r: Spanned<Expr>) -> Spanned<Ex
|
||||||
fn parse_expr(p: Pair<'_, Rule>) -> Spanned<Expr> {
|
fn parse_expr(p: Pair<'_, Rule>) -> Spanned<Expr> {
|
||||||
assert_eq!(p.as_rule(), Rule::expr);
|
assert_eq!(p.as_rule(), Rule::expr);
|
||||||
|
|
||||||
fn infl(rule: Rule) -> Op<Rule> {
|
|
||||||
Op::infix(rule, Assoc::Left)
|
|
||||||
}
|
|
||||||
|
|
||||||
PrattParser::new()
|
PrattParser::new()
|
||||||
.op(infl(Rule::op_or) | infl(Rule::op_xor))
|
.op(Op::infix(Rule::infix_or, Assoc::Left) | Op::infix(Rule::infix_xor, Assoc::Left))
|
||||||
.op(infl(Rule::op_and))
|
.op(Op::infix(Rule::infix_and, Assoc::Left))
|
||||||
.op(infl(Rule::op_eq) | infl(Rule::op_neq))
|
.op(Op::infix(Rule::infix_eq, Assoc::Left) | Op::infix(Rule::infix_neq, Assoc::Left))
|
||||||
.op(infl(Rule::op_lt) | infl(Rule::op_lte) | infl(Rule::op_gt) | infl(Rule::op_gte))
|
.op(Op::infix(Rule::infix_lt, Assoc::Left)
|
||||||
.op(infl(Rule::op_mul) | infl(Rule::op_div) | infl(Rule::op_mod))
|
| Op::infix(Rule::infix_lte, Assoc::Left)
|
||||||
.op(infl(Rule::op_add) | infl(Rule::op_sub))
|
| Op::infix(Rule::infix_gt, Assoc::Left)
|
||||||
|
| Op::infix(Rule::infix_gte, Assoc::Left))
|
||||||
|
.op(Op::infix(Rule::infix_mul, Assoc::Left)
|
||||||
|
| Op::infix(Rule::infix_div, Assoc::Left)
|
||||||
|
| Op::infix(Rule::infix_mod, Assoc::Left))
|
||||||
|
.op(Op::infix(Rule::infix_add, Assoc::Left) | Op::infix(Rule::infix_sub, Assoc::Left))
|
||||||
|
.op(Op::prefix(Rule::prefix_neg) | Op::prefix(Rule::prefix_not))
|
||||||
.map_primary(parse_term)
|
.map_primary(parse_term)
|
||||||
.map_infix(parse_op)
|
.map_prefix(parse_prefix)
|
||||||
|
.map_infix(parse_infix)
|
||||||
.parse(p.into_inner())
|
.parse(p.into_inner())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue