From c4fbc7a0c19314e0e60b5f7778a46b2cfe05ea17 Mon Sep 17 00:00:00 2001 From: Erin Date: Fri, 15 Sep 2023 23:22:45 +0200 Subject: [PATCH] Syntactic changes --- src/syntax/ast.rs | 31 +++++++++++------ src/syntax/parser.rs | 80 ++++++++++++++++++++++---------------------- src/syntax/token.rs | 7 ++-- 3 files changed, 65 insertions(+), 53 deletions(-) diff --git a/src/syntax/ast.rs b/src/syntax/ast.rs index fd54f81..adb2b81 100644 --- a/src/syntax/ast.rs +++ b/src/syntax/ast.rs @@ -26,20 +26,32 @@ pub enum Expr<'a> { Call(ExprRef<'a>, ExprList<'a>), Binary(Spanned, ExprRef<'a>, ExprRef<'a>), Unary(Spanned, ExprRef<'a>), - BindLocal(Spanned, ExprRef<'a>, Option>), - BindIn( - Spanned, - ExprRef<'a>, - ExprList<'a>, - Option>, - ), + Def(DefKind, Spanned, Option>, ExprRef<'a>), Set(ExprRef<'a>, ExprRef<'a>), - Match(ExprRef<'a>, &'a [(Spanned, SpanExpr<'a>)]), - Func(&'a [(Spanned, Spanned)], Spanned, ExprRef<'a>), + Switch( + ExprRef<'a>, + &'a [(Spanned, SpanExpr<'a>)], + Option>, + ), + Loop(ExprList<'a>), + Func( + &'a [(Spanned, Spanned)], + Spanned, + ExprRef<'a>, + ), Block(ExprList<'a>), + Break(Option>), + Return(Option>), + Continue, Unit, } +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum DefKind { + Const, + Var, +} + #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Type { Ident(Ident), @@ -50,7 +62,6 @@ pub enum Type { pub enum Pattern { Ident(Ident), Literal(Literal), - None, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] diff --git a/src/syntax/parser.rs b/src/syntax/parser.rs index 3dd8aef..7816b3b 100644 --- a/src/syntax/parser.rs +++ b/src/syntax/parser.rs @@ -1,8 +1,8 @@ -use super::ast::Type; +use super::ast::DefKind; use { super::{ - ast::{BinaryOperator, Expr, Literal, Pattern, SpanExpr, Spanned, UnaryOperator}, + ast::{BinaryOperator, Expr, Literal, Pattern, SpanExpr, Spanned, Type, UnaryOperator}, token::Token, }, crate::utils::Pipe, @@ -35,13 +35,6 @@ where Token::String(a) => Literal::String(a) }; - let pattern = select! { - Token::Ident(id) => Pattern::Ident(id), - Token::Underscore => Pattern::None, - } - .or(literal.map(Pattern::Literal)) - .map_with_span(Spanned::new); - let type_ = just([Token::LeftParen, Token::RightParen]) .to(Type::Unit) .or(ident.map(Type::Ident)) @@ -56,8 +49,9 @@ where let func = just(Token::Func) .ignore_then( - pattern - .then_ignore(just(Token::Colon)) + ident + .map_with_span(Spanned::new) + .then_ignore(just(Token::RArrow)) .then(type_) .separated_by(just(Token::Comma)) .allow_trailing() @@ -158,26 +152,13 @@ where }, ); - let bind = { - let start = pattern.then_ignore(just(Token::Colon)).then(expr.clone()); // := - let else_ = just(Token::Else).ignore_then(block.clone()).or_not(); // else {…} - - // := [else {…}] - let local = start.clone().then(else_.clone()).map_with_state( - |((pat, expr), else_), _, state| { - Expr::BindLocal(pat, &*state.arena.alloc(expr), else_) - }, - ); - - // := {…} else {…} - let in_ = start.then(block.clone()).then(else_).map_with_state( - |(((pat, expr), block), else_), _, state| { - Expr::BindIn(pat, &*state.arena.alloc(expr), block, else_) - }, - ); - - in_.or(local) - }; + // (const/var) [:] = + let def = equivmap!(Token, DefKind, [Var, Const]) + .then(ident.map_with_span(Spanned::new)) + .then(just(Token::Colon).ignore_then(type_).or_not()) + .then_ignore(just(Token::Equ)) + .then(expr.clone().pipe(arena_box)) + .map(|(((kind, ident), type_), expr)| Expr::Def(kind, ident, type_, expr)); // let set = atom @@ -188,25 +169,44 @@ where Expr::Set(state.arena.alloc(place), state.arena.alloc(expr)) }); - // .match { , … } - let match_ = atom + // .switch { , … } + let switch = atom .clone() - .then_ignore(just([Token::Dot, Token::Match])) + .then_ignore(just([Token::Dot, Token::Switch])) .then( - pattern + ident + .map(Pattern::Ident) + .or(literal.map(Pattern::Literal)) + .map_with_span(Spanned::new) .then_ignore(just(Token::RArrow)) - .then(expr) + .then(expr.clone()) .separated_by(just(Token::Comma)) .allow_trailing() .pipe(arena_collect) + .then( + just(Token::Else) + .ignore_then(just(Token::RArrow)) + .ignore_then(expr.clone().pipe(arena_box)) + .or_not(), + ) .delimited_by(just(Token::LeftCurly), just(Token::RightCurly)), ) - .map_with_state(|(expr, branches), _, state| { - Expr::Match(state.arena.alloc(expr), branches) + .map_with_state(|(expr, (branches, else_)), _, state| { + Expr::Switch(state.arena.alloc(expr), branches, else_) }); - bind.or(set) - .or(match_) + let loop_ = just(Token::Loop).ignore_then(block.clone()).map(Expr::Loop); + let brk_ret = just(Token::Break) + .to(Expr::Break as fn(_) -> _) + .or(just(Token::Ret).to(Expr::Return as fn(_) -> _)) + .then(expr.pipe(arena_box).or_not()) + .map(|(variant, expr)| variant(expr)); + + def.or(set) + .or(switch) + .or(loop_) + .or(brk_ret) + .or(just(Token::Continue).to(Expr::Continue)) .or(block.map(Expr::Block)) .map_with_span(Spanned::new) .or(binary) diff --git a/src/syntax/token.rs b/src/syntax/token.rs index 2651e09..8966c35 100644 --- a/src/syntax/token.rs +++ b/src/syntax/token.rs @@ -55,14 +55,15 @@ pub enum Token { #[token("≥") ] //___, #[token(">=")] GtEqu, - #[token("match")] Match, + #[token("switch")] Switch, #[token("else")] Else, #[token("loop")] Loop, + #[token("continue")] Continue, + #[token("break")] Break, + #[token("ret")] Ret, #[token("const")] Const, #[token("var")] Var, #[token("func")] Func, - // Modules aren't real here ondra just variables with imported functions - #[token("module")] Module, #[regex( r"\p{XID_Start}\p{XID_Continue}*",