From 1846fe41aed5ef10755d2602188fc894db2244a9 Mon Sep 17 00:00:00 2001 From: Erin Date: Tue, 12 Sep 2023 19:54:59 +0200 Subject: [PATCH] sth --- src/main.rs | 1 + src/syntax/ast.rs | 9 +++--- src/syntax/parser.rs | 68 +++++++++++++++++++++++++++++++++----------- src/syntax/token.rs | 2 +- 4 files changed, 59 insertions(+), 21 deletions(-) diff --git a/src/main.rs b/src/main.rs index b4f78c5..da3537e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,7 @@ use utils::default; mod syntax; mod utils; + fn main() -> Result<(), Box> { let mut buf = default(); stdin().read_to_string(&mut buf)?; diff --git a/src/syntax/ast.rs b/src/syntax/ast.rs index e351646..45fb1cf 100644 --- a/src/syntax/ast.rs +++ b/src/syntax/ast.rs @@ -36,6 +36,7 @@ pub enum Expr<'a> { Match(ExprRef<'a>, &'a [(Spanned, SpanExpr<'a>)]), Set(ExprRef<'a>, ExprRef<'a>), Func(Ident, &'a [Spanned], 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, } diff --git a/src/syntax/parser.rs b/src/syntax/parser.rs index 5266491..78b7b31 100644 --- a/src/syntax/parser.rs +++ b/src/syntax/parser.rs @@ -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) +} diff --git a/src/syntax/token.rs b/src/syntax/token.rs index ecfc47a..6ce9a45 100644 --- a/src/syntax/token.rs +++ b/src/syntax/token.rs @@ -39,7 +39,7 @@ pub enum Token { #[token("*")] Star, #[token("/")] Slash, #[token("&")] And, - #[token("|")] Or, + #[token("|")] VLine, #[token("~")] Tilde, #[token("<")] Lt,