Syntactic changes

This commit is contained in:
Erin 2023-09-15 23:22:45 +02:00 committed by ondra05
parent 850696a7ab
commit c4fbc7a0c1
3 changed files with 65 additions and 53 deletions

View file

@ -26,20 +26,32 @@ pub enum Expr<'a> {
Call(ExprRef<'a>, ExprList<'a>), Call(ExprRef<'a>, ExprList<'a>),
Binary(Spanned<BinaryOperator>, ExprRef<'a>, ExprRef<'a>), Binary(Spanned<BinaryOperator>, ExprRef<'a>, ExprRef<'a>),
Unary(Spanned<UnaryOperator>, ExprRef<'a>), Unary(Spanned<UnaryOperator>, ExprRef<'a>),
BindLocal(Spanned<Pattern>, ExprRef<'a>, Option<ExprList<'a>>), Def(DefKind, Spanned<Ident>, Option<Spanned<Type>>, ExprRef<'a>),
BindIn(
Spanned<Pattern>,
ExprRef<'a>,
ExprList<'a>,
Option<ExprList<'a>>,
),
Set(ExprRef<'a>, ExprRef<'a>), Set(ExprRef<'a>, ExprRef<'a>),
Match(ExprRef<'a>, &'a [(Spanned<Pattern>, SpanExpr<'a>)]), Switch(
Func(&'a [(Spanned<Pattern>, Spanned<Type>)], Spanned<Type>, ExprRef<'a>), ExprRef<'a>,
&'a [(Spanned<Pattern>, SpanExpr<'a>)],
Option<ExprRef<'a>>,
),
Loop(ExprList<'a>),
Func(
&'a [(Spanned<Ident>, Spanned<Type>)],
Spanned<Type>,
ExprRef<'a>,
),
Block(ExprList<'a>), Block(ExprList<'a>),
Break(Option<ExprRef<'a>>),
Return(Option<ExprRef<'a>>),
Continue,
Unit, Unit,
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DefKind {
Const,
Var,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Type { pub enum Type {
Ident(Ident), Ident(Ident),
@ -50,7 +62,6 @@ pub enum Type {
pub enum Pattern { pub enum Pattern {
Ident(Ident), Ident(Ident),
Literal(Literal), Literal(Literal),
None,
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]

View file

@ -1,8 +1,8 @@
use super::ast::Type; use super::ast::DefKind;
use { use {
super::{ super::{
ast::{BinaryOperator, Expr, Literal, Pattern, SpanExpr, Spanned, UnaryOperator}, ast::{BinaryOperator, Expr, Literal, Pattern, SpanExpr, Spanned, Type, UnaryOperator},
token::Token, token::Token,
}, },
crate::utils::Pipe, crate::utils::Pipe,
@ -35,13 +35,6 @@ where
Token::String(a) => Literal::String(a) 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]) let type_ = just([Token::LeftParen, Token::RightParen])
.to(Type::Unit) .to(Type::Unit)
.or(ident.map(Type::Ident)) .or(ident.map(Type::Ident))
@ -56,8 +49,9 @@ where
let func = just(Token::Func) let func = just(Token::Func)
.ignore_then( .ignore_then(
pattern ident
.then_ignore(just(Token::Colon)) .map_with_span(Spanned::new)
.then_ignore(just(Token::RArrow))
.then(type_) .then(type_)
.separated_by(just(Token::Comma)) .separated_by(just(Token::Comma))
.allow_trailing() .allow_trailing()
@ -158,26 +152,13 @@ where
}, },
); );
let bind = { // (const/var) <ident> [:<type>] = <expr>
let start = pattern.then_ignore(just(Token::Colon)).then(expr.clone()); // <pat> := <expr> let def = equivmap!(Token, DefKind, [Var, Const])
let else_ = just(Token::Else).ignore_then(block.clone()).or_not(); // else {…} .then(ident.map_with_span(Spanned::new))
.then(just(Token::Colon).ignore_then(type_).or_not())
// <pat> := <expr> [else {…}] .then_ignore(just(Token::Equ))
let local = start.clone().then(else_.clone()).map_with_state( .then(expr.clone().pipe(arena_box))
|((pat, expr), else_), _, state| { .map(|(((kind, ident), type_), expr)| Expr::Def(kind, ident, type_, expr));
Expr::BindLocal(pat, &*state.arena.alloc(expr), else_)
},
);
// <pat> := <expr> {…} 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)
};
// <atom> ← <expr> // <atom> ← <expr>
let set = atom let set = atom
@ -188,25 +169,44 @@ where
Expr::Set(state.arena.alloc(place), state.arena.alloc(expr)) Expr::Set(state.arena.alloc(place), state.arena.alloc(expr))
}); });
// <expr>.match { <pat> → <expr>, … } // <atom>.switch { <pat> → <expr>, … }
let match_ = atom let switch = atom
.clone() .clone()
.then_ignore(just([Token::Dot, Token::Match])) .then_ignore(just([Token::Dot, Token::Switch]))
.then( .then(
pattern ident
.map(Pattern::Ident)
.or(literal.map(Pattern::Literal))
.map_with_span(Spanned::new)
.then_ignore(just(Token::RArrow)) .then_ignore(just(Token::RArrow))
.then(expr) .then(expr.clone())
.separated_by(just(Token::Comma)) .separated_by(just(Token::Comma))
.allow_trailing() .allow_trailing()
.pipe(arena_collect) .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)), .delimited_by(just(Token::LeftCurly), just(Token::RightCurly)),
) )
.map_with_state(|(expr, branches), _, state| { .map_with_state(|(expr, (branches, else_)), _, state| {
Expr::Match(state.arena.alloc(expr), branches) Expr::Switch(state.arena.alloc(expr), branches, else_)
}); });
bind.or(set) let loop_ = just(Token::Loop).ignore_then(block.clone()).map(Expr::Loop);
.or(match_) 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)) .or(block.map(Expr::Block))
.map_with_span(Spanned::new) .map_with_span(Spanned::new)
.or(binary) .or(binary)

View file

@ -55,14 +55,15 @@ pub enum Token {
#[token("") ] //___, #[token("") ] //___,
#[token(">=")] GtEqu, #[token(">=")] GtEqu,
#[token("match")] Match, #[token("switch")] Switch,
#[token("else")] Else, #[token("else")] Else,
#[token("loop")] Loop, #[token("loop")] Loop,
#[token("continue")] Continue,
#[token("break")] Break,
#[token("ret")] Ret,
#[token("const")] Const, #[token("const")] Const,
#[token("var")] Var, #[token("var")] Var,
#[token("func")] Func, #[token("func")] Func,
// Modules aren't real here ondra just variables with imported functions
#[token("module")] Module,
#[regex( #[regex(
r"\p{XID_Start}\p{XID_Continue}*", r"\p{XID_Start}\p{XID_Continue}*",