use nom::{ branch::alt, combinator::map, error::context, multi::separated_list1, sequence::{delimited, separated_pair, tuple}, }; use crate::parser::{ expression::{expression, Expression}, tokens::{token, TokenKind as tk, TokenSpan}, IResult, }; #[derive(Debug, Clone)] pub enum BlockExpr<'a> { IfElse(IfElseBlock), Match(MatchBlock<'a>), Block(Vec>), } // 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 { separated_pair(expression, token(tk::FatArrow), expression)(input) } fn match_block(input: TokenSpan) -> IResult { 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 block_expr(input: TokenSpan) -> IResult { alt((map(match_block, BlockExpr::Match),))(input) }