Parse arithmetic and logical negation

This commit is contained in:
Joscha 2022-11-19 11:58:52 +01:00
parent 4be5283204
commit 63f8026007
3 changed files with 69 additions and 3 deletions

View file

@ -6,6 +6,7 @@ use crate::ast::Expr;
use super::basic::{space, Error};
use super::lit::lit;
use super::prefix::prefixed;
use super::suffix::suffixed;
use super::table_constr::table_constr;
use super::table_destr::table_destr;
@ -34,13 +35,14 @@ fn atom(
let var = var(expr.clone()).map(Expr::Var);
let table_constr = table_constr(expr.clone()).map(Expr::TableConstr);
let table_destr = table_destr(expr.clone()).map(Expr::TableDestr);
let paren = atom_paren(expr);
let paren = atom_paren(expr.clone());
lit.or(paren).or(table_destr).or(table_constr).or(var)
let base = lit.or(paren).or(table_destr).or(table_constr).or(var);
prefixed(suffixed(base, expr))
}
pub fn expr(
expr: impl Parser<char, Expr, Error = Error> + Clone,
) -> impl Parser<char, Expr, Error = Error> {
suffixed(atom(expr.clone()), expr)
atom(expr)
}

63
src/parser/prefix.rs Normal file
View file

@ -0,0 +1,63 @@
//! Corresponds to `Expr::Neg` and `Expr::Not` in `ast::expr`
use chumsky::prelude::*;
use crate::ast::{Expr, Space};
use crate::span::{HasSpan, Span};
use super::basic::{space, Error};
enum Prefix {
/// See [`Expr::Neg`].
Neg { minus: Span, s0: Space },
/// See [`Expr::Not`].
Not { not: Span, s0: Space },
}
impl Prefix {
fn into_expr(self, span: Span, expr: Expr) -> Expr {
let expr = Box::new(expr);
match self {
Self::Neg { minus, s0 } => Expr::Neg {
minus,
s0,
expr,
span,
},
Self::Not { not, s0 } => Expr::Not {
not,
s0,
expr,
span,
},
}
}
}
fn prefix_neg() -> impl Parser<char, Prefix, Error = Error> {
just('-')
.map_with_span(|_, span| span)
.then(space())
.map(|(minus, s0)| Prefix::Neg { minus, s0 })
}
fn prefix_not() -> impl Parser<char, Prefix, Error = Error> {
text::keyword("not")
.map_with_span(|_, span| span)
.then(space())
.map(|(not, s0)| Prefix::Not { not, s0 })
}
pub fn prefixed(
suffixed: impl Parser<char, Expr, Error = Error>,
) -> impl Parser<char, Expr, Error = Error> {
let prefix = prefix_neg()
.or(prefix_not())
.map_with_span(|prefix, span| (prefix, span));
prefix
.repeated()
.then(suffixed)
.foldr(|(prefix, span), expr| prefix.into_expr(expr.span().join(span), expr))
}