use crate::ast::prelude::*;
#[test]
#[cfg(not(miri))]
fn ast_parse() {
rt::<ast::ExprMatch>("match 0 { _ => 1, }");
let expr = rt::<ast::ExprMatch>("#[jit(always)] match 0 { _ => 1, }");
assert_eq!(expr.attributes.len(), 1);
rt::<ast::ExprMatchBranch>("1 => { foo }");
}
#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Spanned)]
#[non_exhaustive]
pub struct ExprMatch {
#[rune(iter)]
pub attributes: Vec<ast::Attribute>,
pub match_: T![match],
pub expr: Box<ast::Expr>,
pub open: T!['{'],
#[rune(iter)]
pub branches: Vec<(ExprMatchBranch, Option<T![,]>)>,
pub close: T!['}'],
}
impl ExprMatch {
pub(crate) fn parse_with_attributes(
parser: &mut Parser<'_>,
attributes: Vec<ast::Attribute>,
) -> Result<Self> {
let match_ = parser.parse()?;
let expr = ast::Expr::parse_without_eager_brace(parser)?;
let open = parser.parse()?;
let mut branches = Vec::new();
while !parser.peek::<ast::CloseBrace>()? {
let branch = parser.parse::<ExprMatchBranch>()?;
let comma = parser.parse::<Option<T![,]>>()?;
let is_end = ast::utils::is_block_end(&branch.body, comma.as_ref());
branches.try_push((branch, comma))?;
if is_end {
break;
}
}
let close = parser.parse()?;
Ok(ExprMatch {
attributes,
match_,
expr: Box::try_new(expr)?,
open,
branches,
close,
})
}
}
expr_parse!(Match, ExprMatch, "match expression");
#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Parse, Spanned)]
#[non_exhaustive]
pub struct ExprMatchBranch {
pub pat: ast::Pat,
#[rune(iter)]
pub condition: Option<(T![if], ast::Expr)>,
pub rocket: T![=>],
pub body: ast::Expr,
}