This commit is contained in:
Erin 2023-09-12 19:54:59 +02:00 committed by ondra05
parent 2c2322bb6c
commit 1846fe41ae
4 changed files with 59 additions and 21 deletions

View file

@ -8,6 +8,7 @@ use utils::default;
mod syntax;
mod utils;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut buf = default();
stdin().read_to_string(&mut buf)?;

View file

@ -36,6 +36,7 @@ pub enum Expr<'a> {
Match(ExprRef<'a>, &'a [(Spanned<Pattern>, SpanExpr<'a>)]),
Set(ExprRef<'a>, ExprRef<'a>),
Func(Ident, &'a [Spanned<Pattern>], ExprRef<'a>),
Block(ExprList<'a>),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
@ -57,7 +58,7 @@ pub enum BinaryOperator {
Star,
Slash,
And,
Or,
VLine,
Lt,
Gt,
Equ,
@ -68,7 +69,7 @@ pub enum BinaryOperator {
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum UnaryOperator {
Not,
Neg,
Deref,
Tilde,
Minus,
Star,
}

View file

@ -1,4 +1,4 @@
use super::ast::{Literal, SpanExpr};
use super::ast::{BinaryOperator, Literal, SpanExpr, UnaryOperator};
use {
super::{
@ -15,39 +15,70 @@ use {
logos::Lexer,
};
/// Equivalently-named unit variant mapping
macro_rules! equivmap {
($src:ident, $target:ident, [$variant0:ident $(, $variant:ident)* $(,)?] $(,)?) => {
just($src::$variant0).to($target::$variant0)
$(.or(just($src::$variant).to($target::$variant)))*
};
}
fn expr<'a, I>() -> impl Parser<'a, I, SpanExpr<'a>, Extra<'a>> + Clone
where
I: Input<'a, Token = Token, Span = SimpleSpan> + ValueInput<'a>,
{
recursive(|expr| {
let ident = select!(Token::Ident(id) => Expr::Ident(id));
let atom = {
// Literal
select! {
Token::Int(a) => Literal::Integer(a),
Token::String(a) => Literal::String(a)
}
.map(Expr::Literal)
let literal = select! {
Token::Int(a) => Literal::Integer(a),
Token::String(a) => Literal::String(a)
}
.or(ident)
.map_with_span(Spanned::new)
.or(expr
.map(Expr::Literal);
let atom = literal.or(ident).map_with_span(Spanned::new).or(expr
.clone()
.delimited_by(just(Token::LeftParen), just(Token::RightParen)));
let call = atom
.clone()
.pipe(arena_box)
.then(
.foldl_with_state(
expr.clone()
.separated_by(just(Token::Comma))
.allow_trailing()
.pipe(arena_collect)
.delimited_by(just(Token::LeftParen), just(Token::RightParen)),
.delimited_by(just(Token::LeftParen), just(Token::RightParen))
.map_with_span(Spanned::new)
.repeated(),
|expr, paramlist, state: &mut State| {
Spanned::new(
Expr::Call(state.arena.alloc(expr), paramlist.item),
merge_spans(expr.span, paramlist.span),
)
},
)
.map(|(expr, params)| Expr::Call(expr, params));
.boxed();
call.map_with_span(Spanned::new).or(atom)
let unary = call;
let binary = unary.clone().foldl_with_state(
equivmap!(
Token,
BinaryOperator,
[Plus, Minus, Star, Slash, And, VLine, Lt, Gt, Equ, Nequ, LtEqu, GtEqu],
)
.map_with_span(Spanned::new)
.then(unary)
.repeated(),
|l, (op, r), state: &mut State| {
Spanned::new(
Expr::Binary(op, state.arena.alloc(l), state.arena.alloc(r)),
merge_spans(l.span, r.span),
)
},
);
binary.or(atom)
})
}
@ -105,3 +136,8 @@ where
{
parser.map_with_state(|item, _, state| &*state.arena.alloc(item))
}
#[inline]
fn merge_spans(start: SimpleSpan, end: SimpleSpan) -> SimpleSpan {
SimpleSpan::new(start.start, end.end)
}

View file

@ -39,7 +39,7 @@ pub enum Token {
#[token("*")] Star,
#[token("/")] Slash,
#[token("&")] And,
#[token("|")] Or,
#[token("|")] VLine,
#[token("~")] Tilde,
#[token("<")] Lt,