Actually just three programming languages in a trenchcoat
at string-repr-callable 67 lines 3.0 kB view raw
1use super::*; 2use crate::{Parser, Spanned}; 3use source_span::Span; 4use trilogy_scanner::{Token, TokenType::*}; 5 6#[derive(Clone, Debug, PrettyPrintSExpr)] 7pub struct HandledExpression { 8 pub with: Token, 9 pub expression: Expression, 10 pub handlers: Vec<Handler>, 11 span: Span, 12} 13 14impl Spanned for HandledExpression { 15 fn span(&self) -> Span { 16 self.span 17 } 18} 19 20impl HandledExpression { 21 pub(crate) fn parse(parser: &mut Parser) -> SyntaxResult<Self> { 22 let with = parser 23 .expect(KwWith) 24 .map_err(|token| parser.expected(token, "expected `with`"))?; 25 26 let expression = Expression::parse(parser)?; 27 28 let mut handlers = vec![]; 29 loop { 30 if let Err(token) = parser.check([KwWhen, KwElse]) { 31 let error = SyntaxError::new( 32 token.span, 33 "expected `when`, or `else` to with an effect handler", 34 ); 35 parser.error(error.clone()); 36 return Err(error); 37 } 38 let handler = Handler::parse(parser)?; 39 let end = matches!(handler, Handler::Else(..)); 40 handlers.push(handler); 41 if end { 42 return Ok(Self { 43 span: with.span.union(handlers.last().unwrap().span()), 44 with, 45 expression, 46 handlers, 47 }); 48 } 49 } 50 } 51} 52 53#[cfg(test)] 54mod test { 55 use super::*; 56 57 test_parse!(handled_expr_else_yield: "with 3 else yield" => HandledExpression::parse => "(HandledExpression _ _ [(Handler::Else _)])"); 58 test_parse!(handled_expr_else_resume: "with 3 else resume 3" => HandledExpression::parse => "(HandledExpression _ _ [(Handler::Else _)])"); 59 test_parse!(handled_expr_else_cancel: "with 3 else cancel 3" => HandledExpression::parse => "(HandledExpression _ _ [(Handler::Else _)])"); 60 test_parse!(handled_expr_yield: "with 3 when 'x yield else yield" => HandledExpression::parse => "(HandledExpression _ _ [(Handler::When _) (Handler::Else _)])"); 61 test_parse_error!(handled_expr_resume_block: "with 3 when 'x resume {} else yield" => HandledExpression::parse); 62 test_parse_error!(handled_expr_cancel_block: "with 3 when 'x cancel {} else yield" => HandledExpression::parse); 63 test_parse!(handled_expr_resume_expr: "with 3 when 'x resume 3 else yield" => HandledExpression::parse => "(HandledExpression _ _ [(Handler::When _) (Handler::Else _)])"); 64 test_parse!(handled_expr_cancel_expr: "with 3 when 'x cancel 3 else yield" => HandledExpression::parse => "(HandledExpression _ _ [(Handler::When _) (Handler::Else _)])"); 65 test_parse!(handled_expr_multiple_yield: "with 3 when 'x yield when 'y yield else yield" => HandledExpression::parse => "(HandledExpression _ _ [(Handler::When _) (Handler::When _) (Handler::Else _)])"); 66 test_parse_error!(handled_expr_block: "with {} else yield" => HandledExpression::parse); 67}