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#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Spanned)]
17#[non_exhaustive]
18pub struct ExprMatch {
19 #[rune(iter)]
21 pub attributes: Vec<ast::Attribute>,
22 pub match_: T![match],
24 pub expr: Box<ast::Expr>,
26 pub open: T!['{'],
28 #[rune(iter)]
30 pub branches: Vec<(ExprMatchBranch, Option<T![,]>)>,
31 pub close: T!['}'],
33}
34
35impl ExprMatch {
36 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#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Parse, Spanned)]
76#[non_exhaustive]
77pub struct ExprMatchBranch {
78 pub pat: ast::Pat,
80 #[rune(iter)]
82 pub condition: Option<(T![if], ast::Expr)>,
83 pub rocket: T![=>],
85 pub body: ast::Expr,
87}