Actually just three programming languages in a trenchcoat
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}