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>),
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)]

View file

@ -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)

View file

@ -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}*",