use chumsky::pratt::*;
use chumsky::prelude::*;
#[derive(Debug)]
enum Term<'a> {
Var(&'a str),
Zero,
One,
Bot,
Top,
Neg(Box<Term<'a>>),
Bang(Box<Term<'a>>),
Quest(Box<Term<'a>>),
Tensor(Box<Term<'a>>, Box<Term<'a>>),
Par(Box<Term<'a>>, Box<Term<'a>>),
With(Box<Term<'a>>, Box<Term<'a>>),
Plus(Box<Term<'a>>, Box<Term<'a>>),
Lollipop(Box<Term<'a>>, Box<Term<'a>>),
}
#[derive(Debug)]
struct Sequent<'a> {
left: Vec<Term<'a>>,
right: Vec<Term<'a>>,
}
fn constant_parser<'a>() -> impl Parser<'a, &'a str, Term<'a>, extra::Err<Simple<'a, char>>> + Clone
{
choice((
text::keyword("0").map(|_| Term::Zero),
text::keyword("1").map(|_| Term::One),
text::keyword("bot").map(|_| Term::Bot),
text::keyword("⊥").map(|_| Term::Bot),
text::keyword("top").map(|_| Term::Top),
text::keyword("⊤").map(|_| Term::Top),
))
}
fn variable_parser<'a>() -> impl Parser<'a, &'a str, Term<'a>, extra::Err<Simple<'a, char>>> + Clone
{
text::ident().map(Term::Var)
}
fn term_parser<'a>() -> impl Parser<'a, &'a str, Term<'a>, extra::Err<Simple<'a, char>>> + Clone {
recursive(|term| {
let atom = choice((
constant_parser(),
variable_parser(),
term.delimited_by(just('('), just(')')),
))
.padded();
atom.pratt((
postfix(7, just('^'), |lhs, _, _| Term::Neg(Box::new(lhs))),
prefix(6, just('~'), |_, rhs, _| Term::Neg(Box::new(rhs))),
prefix(6, just('!'), |_, rhs, _| Term::Bang(Box::new(rhs))),
prefix(6, just('?'), |_, rhs, _| Term::Quest(Box::new(rhs))),
infix(left(5), just('*'), |l, _, r, _| {
Term::Tensor(Box::new(l), Box::new(r))
}),
infix(left(5), just('⊗'), |l, _, r, _| {
Term::Tensor(Box::new(l), Box::new(r))
}),
infix(left(4), text::keyword("par"), |l, _, r, _| {
Term::Par(Box::new(l), Box::new(r))
}),
infix(left(4), just('|'), |l, _, r, _| {
Term::Par(Box::new(l), Box::new(r))
}),
infix(left(4), just('⅋'), |l, _, r, _| {
Term::Par(Box::new(l), Box::new(r))
}),
infix(left(3), just('&'), |l, _, r, _| {
Term::With(Box::new(l), Box::new(r))
}),
infix(left(2), just('+'), |l, _, r, _| {
Term::Plus(Box::new(l), Box::new(r))
}),
infix(left(2), just('⊕'), |l, _, r, _| {
Term::Plus(Box::new(l), Box::new(r))
}),
infix(right(1), just("-o"), |l, _, r, _| {
Term::Lollipop(Box::new(l), Box::new(r))
}),
infix(right(0), just('⊸'), |l, _, r, _| {
Term::Lollipop(Box::new(l), Box::new(r))
}),
))
})
}
fn sequent_parser<'a>() -> impl Parser<'a, &'a str, Sequent<'a>, extra::Err<Simple<'a, char>>> {
let terms_list = term_parser()
.clone()
.separated_by(just(',').padded())
.collect::<Vec<Term<'a>>>();
let tack = choice((just("|-"), just("⊢"))).padded();
terms_list
.clone() .then(tack) .then(terms_list) .map(|((left, _), right)| Sequent { left, right })
.then_ignore(end()) }
pub fn parse_raw_sequent<'a>(input: &'a str) -> Result<super::raw::Sequent, ()> {
let result: Result<Sequent, _> = sequent_parser().parse(input).into_result();
todo!()
}