Files
binocle/src/parser.rs
T
surv 86c507df21
CI / fmt (push) Has been cancelled
CI / clippy (push) Has been cancelled
CI / doc (push) Has been cancelled
CI / test macos-latest (push) Has been cancelled
CI / test windows-latest (push) Has been cancelled
First commit
2026-08-08 11:02:48 +02:00

46 lines
1.6 KiB
Rust

use winnow::Parser;
use winnow::ascii::multispace0;
use winnow::combinator::{Infix, Prefix, peek};
use winnow::combinator::{delimited, dispatch, expression, fail};
use winnow::error::ContextError;
use winnow::token::any;
use crate::binary_repr::parse_binary_repr;
use crate::expr::{BinOp, Expr, UnaryOp};
pub fn parser<'i>(size: usize) -> impl Parser<&'i str, Expr, ContextError> {
move |i: &mut &str| {
use Infix::Left;
expression(delimited(
multispace0,
dispatch! {peek(any);
'(' => delimited('(', parser(size).map(|e| Expr::Group(Box::new(e))), ')'),
_ => parse_binary_repr(size).map(Expr::Constant),
},
multispace0,
))
.prefix(delimited(
multispace0,
dispatch! {any;
'-' => Prefix(12, |_, a| Ok(Expr::UnaryOp(UnaryOp::Neg, Box::new(a)))),
'!' => Prefix(12, |_, a| Ok(Expr::UnaryOp(UnaryOp::Not, Box::new(a)))),
_ => fail,
},
multispace0,
))
.infix(delimited(
multispace0,
dispatch! {any;
'+' => Left(5, |_, a, b| Ok(Expr::BinaryOp(Box::new(a), BinOp::Plus, Box::new(b)))),
'-' => Left(5, |_, a, b| Ok(Expr::BinaryOp(Box::new(a), BinOp::Sub, Box::new(b)))),
'*' => Left(7, |_, a, b| Ok(Expr::BinaryOp(Box::new(a), BinOp::Mul, Box::new(b)))),
'/' => Left(7, |_, a, b| Ok(Expr::BinaryOp(Box::new(a), BinOp::Div, Box::new(b)))),
_ => fail,
},
multispace0,
))
.parse_next(i)
}
}