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