Compare commits
1 commit
Author | SHA1 | Date | |
---|---|---|---|
Erin | c4fbc7a0c1 |
|
@ -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)]
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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}*",
|
||||||
|
|
Loading…
Reference in a new issue