Compare commits
1 commit
Author | SHA1 | Date | |
---|---|---|---|
Erin | c4fbc7a0c1 |
|
@ -26,20 +26,32 @@ pub enum Expr<'a> {
|
|||
Call(ExprRef<'a>, ExprList<'a>),
|
||||
Binary(Spanned<BinaryOperator>, ExprRef<'a>, ExprRef<'a>),
|
||||
Unary(Spanned<UnaryOperator>, ExprRef<'a>),
|
||||
BindLocal(Spanned<Pattern>, ExprRef<'a>, Option<ExprList<'a>>),
|
||||
BindIn(
|
||||
Spanned<Pattern>,
|
||||
ExprRef<'a>,
|
||||
ExprList<'a>,
|
||||
Option<ExprList<'a>>,
|
||||
),
|
||||
Def(DefKind, Spanned<Ident>, Option<Spanned<Type>>, ExprRef<'a>),
|
||||
Set(ExprRef<'a>, ExprRef<'a>),
|
||||
Match(ExprRef<'a>, &'a [(Spanned<Pattern>, SpanExpr<'a>)]),
|
||||
Func(&'a [(Spanned<Pattern>, Spanned<Type>)], Spanned<Type>, ExprRef<'a>),
|
||||
Switch(
|
||||
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>),
|
||||
Break(Option<ExprRef<'a>>),
|
||||
Return(Option<ExprRef<'a>>),
|
||||
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)]
|
||||
|
|
|
@ -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()); // <pat> := <expr>
|
||||
let else_ = just(Token::Else).ignore_then(block.clone()).or_not(); // else {…}
|
||||
|
||||
// <pat> := <expr> [else {…}]
|
||||
let local = start.clone().then(else_.clone()).map_with_state(
|
||||
|((pat, expr), else_), _, state| {
|
||||
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)
|
||||
};
|
||||
// (const/var) <ident> [:<type>] = <expr>
|
||||
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));
|
||||
|
||||
// <atom> ← <expr>
|
||||
let set = atom
|
||||
|
@ -188,25 +169,44 @@ where
|
|||
Expr::Set(state.arena.alloc(place), state.arena.alloc(expr))
|
||||
});
|
||||
|
||||
// <expr>.match { <pat> → <expr>, … }
|
||||
let match_ = atom
|
||||
// <atom>.switch { <pat> → <expr>, … }
|
||||
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)
|
||||
|
|
|
@ -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}*",
|
||||
|
|
Loading…
Reference in a new issue