85 lines
2.3 KiB
Rust
85 lines
2.3 KiB
Rust
use nom::{
|
|
branch::alt,
|
|
combinator::map,
|
|
error::context,
|
|
multi::{many0, separated_list1},
|
|
sequence::{delimited, separated_pair, terminated, tuple},
|
|
};
|
|
|
|
use crate::parser::{
|
|
expression::{expression, Expression},
|
|
tokens::{token, Token, TokenKind as tk, TokenSpan},
|
|
IResult,
|
|
};
|
|
|
|
/// a block that is a single expression
|
|
#[derive(Debug, Clone)]
|
|
pub struct ExpressionBlock<'a> {
|
|
pub assignments: Vec<(Token<'a>, Token<'a>, Expression<'a>)>,
|
|
pub value: Expression<'a>,
|
|
}
|
|
|
|
/// an expression that contains a block
|
|
#[derive(Debug, Clone)]
|
|
pub enum BlockExpr<'a> {
|
|
IfElse(IfElseBlock),
|
|
Match(MatchBlock<'a>),
|
|
Block(ExpressionBlock<'a>),
|
|
}
|
|
|
|
// TODO: postponed because annoying to implement
|
|
#[derive(Debug, Clone)]
|
|
pub struct IfElseBlock {}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct MatchBlock<'a> {
|
|
pub expr: Expression<'a>,
|
|
pub arms: Vec<(Expression<'a>, Expression<'a>)>,
|
|
}
|
|
|
|
fn match_arm(input: TokenSpan) -> IResult<TokenSpan, (Expression, Expression)> {
|
|
separated_pair(expression, token(tk::FatArrow), expression)(input)
|
|
}
|
|
|
|
fn match_block(input: TokenSpan) -> IResult<TokenSpan, MatchBlock> {
|
|
context(
|
|
"match block",
|
|
map(
|
|
tuple((
|
|
token(tk::Match),
|
|
delimited(token(tk::LParen), expression, token(tk::RParen)),
|
|
delimited(
|
|
token(tk::LBrace),
|
|
separated_list1(token(tk::Comma), match_arm),
|
|
token(tk::RBrace),
|
|
),
|
|
)),
|
|
|(_, expr, arms)| MatchBlock { expr, arms },
|
|
),
|
|
)(input)
|
|
}
|
|
|
|
pub fn expression_block(input: TokenSpan) -> IResult<TokenSpan, ExpressionBlock> {
|
|
map(
|
|
tuple((
|
|
many0(tuple((
|
|
alt((token(tk::Let), token(tk::Reg), token(tk::Next))),
|
|
terminated(token(tk::Ident), token(tk::EqAssign)),
|
|
terminated(expression, token(tk::Semicolon)),
|
|
))),
|
|
expression,
|
|
)),
|
|
|(assignments, value)| ExpressionBlock { assignments, value },
|
|
)(input)
|
|
}
|
|
|
|
pub fn block_expr(input: TokenSpan) -> IResult<TokenSpan, BlockExpr> {
|
|
alt((
|
|
map(match_block, BlockExpr::Match),
|
|
map(
|
|
delimited(token(tk::LBrace), expression_block, token(tk::RBrace)),
|
|
BlockExpr::Block,
|
|
),
|
|
))(input)
|
|
}
|