Actually just three programming languages in a trenchcoat
1use super::*;
2use crate::Parser;
3use trilogy_scanner::{Token, TokenType::*};
4
5#[derive(Clone, Debug, Spanned)]
6pub enum HandlerStrategy {
7 Cancel { cancel: Token, body: Expression },
8 Resume { resume: Token, body: Expression },
9 Yield(Token),
10 Bare(FollowingExpression),
11}
12
13impl HandlerStrategy {
14 pub(crate) fn parse(parser: &mut Parser) -> SyntaxResult<Self> {
15 let token = match parser.check([KwCancel, KwResume, KwThen, KwYield, OBrace]) {
16 Ok(token) => token,
17 Err(token) => {
18 let token = token.clone();
19 return Err(parser.expected(
20 token,
21 "expected `cancel`, `resume`, `then`, `yield`, or a block in handler",
22 ));
23 }
24 };
25
26 match token.token_type {
27 KwCancel => Ok(Self::Cancel {
28 cancel: parser.expect(KwCancel).unwrap(),
29 body: Expression::parse(parser)?,
30 }),
31 KwResume => Ok(Self::Resume {
32 resume: parser.expect(KwResume).unwrap(),
33 body: Expression::parse(parser)?,
34 }),
35 KwYield => Ok(Self::Yield(parser.expect(KwYield).unwrap())),
36 KwThen | OBrace => Ok(Self::Bare(FollowingExpression::parse(parser)?)),
37 _ => unreachable!(),
38 }
39 }
40}
41
42#[cfg(test)]
43mod test {
44 use super::*;
45
46 test_parse!(handler_strategy_yield: "yield" => HandlerStrategy::parse => HandlerStrategy::Yield(..));
47 test_parse!(handler_strategy_cancel: "cancel 3" => HandlerStrategy::parse => HandlerStrategy::Cancel { .. });
48 test_parse!(handler_strategy_then: "then cancel resume 5" => HandlerStrategy::parse => HandlerStrategy::Bare(..));
49 test_parse!(handler_strategy_block: "{ cancel resume 5 }" => HandlerStrategy::parse => HandlerStrategy::Bare(..));
50 test_parse!(handler_strategy_resume: "resume 4" => HandlerStrategy::parse => HandlerStrategy::Resume { .. });
51}