rune/ast/
expr_match.rs

1use crate::ast::prelude::*;
2
3#[test]
4#[cfg(not(miri))]
5fn ast_parse() {
6    rt::<ast::ExprMatch>("match 0 { _ => 1, }");
7    let expr = rt::<ast::ExprMatch>("#[jit(always)] match 0 { _ => 1, }");
8    assert_eq!(expr.attributes.len(), 1);
9
10    rt::<ast::ExprMatchBranch>("1 => { foo }");
11}
12
13/// A match expression.
14///
15/// * `match <expr> { [arm]* }`.
16#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Spanned)]
17#[non_exhaustive]
18pub struct ExprMatch {
19    /// The attributes for the match expression
20    #[rune(iter)]
21    pub attributes: Vec<ast::Attribute>,
22    /// The `match` token.
23    pub match_: T![match],
24    /// The expression who's result we match over.
25    pub expr: Box<ast::Expr>,
26    /// The open brace of the match.
27    pub open: T!['{'],
28    /// Branches.
29    #[rune(iter)]
30    pub branches: Vec<(ExprMatchBranch, Option<T![,]>)>,
31    /// The close brace of the match.
32    pub close: T!['}'],
33}
34
35impl ExprMatch {
36    /// Parse the `match` expression attaching the given attributes
37    pub(crate) fn parse_with_attributes(
38        parser: &mut Parser<'_>,
39        attributes: Vec<ast::Attribute>,
40    ) -> Result<Self> {
41        let match_ = parser.parse()?;
42        let expr = ast::Expr::parse_without_eager_brace(parser)?;
43
44        let open = parser.parse()?;
45
46        let mut branches = Vec::new();
47
48        while !parser.peek::<ast::CloseBrace>()? {
49            let branch = parser.parse::<ExprMatchBranch>()?;
50            let comma = parser.parse::<Option<T![,]>>()?;
51            let is_end = ast::utils::is_block_end(&branch.body, comma.as_ref());
52            branches.try_push((branch, comma))?;
53
54            if is_end {
55                break;
56            }
57        }
58
59        let close = parser.parse()?;
60
61        Ok(ExprMatch {
62            attributes,
63            match_,
64            expr: Box::try_new(expr)?,
65            open,
66            branches,
67            close,
68        })
69    }
70}
71
72expr_parse!(Match, ExprMatch, "match expression");
73
74/// A match branch.
75#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Parse, Spanned)]
76#[non_exhaustive]
77pub struct ExprMatchBranch {
78    /// The pattern to match.
79    pub pat: ast::Pat,
80    /// The branch condition.
81    #[rune(iter)]
82    pub condition: Option<(T![if], ast::Expr)>,
83    /// The rocket token.
84    pub rocket: T![=>],
85    /// The body of the match.
86    pub body: ast::Expr,
87}