rustidy_ast/expr/with_block/
block.rs1use {
5 crate::{
6 attr::BracedWithInnerAttributes,
7 expr::ExpressionWithoutBlock,
8 stmt::{
9 ExpressionStatement,
10 ExpressionStatementWithBlock,
11 ExpressionStatementWithoutBlock,
12 Statement,
13 },
14 token,
15 },
16 rustidy_ast_util::NotFollows,
17 rustidy_format::{Format, Formattable, WhitespaceFormat},
18 rustidy_parse::{Parse, ParseError, Parser, ParserError, ParserTag},
19 rustidy_print::Print,
20 rustidy_util::{ArenaIdx, Whitespace, decl_arena},
21};
22
23#[derive(PartialEq, Eq, Clone, Debug)]
25#[derive(serde::Serialize, serde::Deserialize)]
26#[derive(Parse, Formattable, Format, Print)]
27#[parse(name = "a block expression")]
28#[parse(skip_if_tag = ParserTag::SkipBlockExpression)]
29pub struct BlockExpression(pub ArenaIdx<BracedWithInnerAttributes<Statements>>);
30
31#[derive(PartialEq, Eq, Clone, Debug)]
33#[derive(serde::Serialize, serde::Deserialize)]
34#[derive(Formattable, Format, Print)]
35pub struct Statements {
36 #[format(args = rustidy_format::vec::args_prefix_ws(Whitespace::INDENT))]
37 pub stmts: Vec<Statement>,
38 #[format(prefix_ws(expr = Whitespace::INDENT, if_ = !self.stmts.is_empty()))]
39 pub trailing_expr: Option<ExpressionWithoutBlock>,
40}
41
42decl_arena! { BracedWithInnerAttributes<Statements> }
43
44impl Parse for Statements {
45 type Error = StatementsError;
46
47 #[coverage(on)]
48 fn parse_from(parser: &mut Parser) -> Result<Self, Self::Error> {
49 let mut stmts = vec![];
50 let trailing_expr = loop {
51 if let Ok((expr, ..)) = parser
56 .try_parse::<(ExpressionStatementWithBlock, NotFollows<token::Dot>, NotFollows<token::Question>,)>()? {
57 stmts.push(
58 Statement::Expression(ExpressionStatement::WithBlock(expr))
59 );
60 continue;
61 }
62
63 match parser
64 .peek::<(ExpressionWithoutBlock, Option<token::Semi>)>()? {
65 Ok(((expr, semi), peek_expr_state)) => match semi {
66 Some(semi) => {
67 parser.set_peeked(peek_expr_state);
68 stmts.push(Statement::Expression(
69 ExpressionStatement::WithoutBlock(ExpressionStatementWithoutBlock { expr, semi },)
70 ));
71 },
72 None => match parser.with_tag(
73 ParserTag::SkipExpressionWithoutBlock,
74 Parser::peek::<Statement>
75 )? {
76 Ok((stmt, peek_stmt_state)) if peek_stmt_state
81 .ahead_of_or_equal(&peek_expr_state) => {
82 parser.set_peeked(peek_stmt_state);
83 stmts.push(stmt);
84 },
85 _ => {
86 parser.set_peeked(peek_expr_state);
87 break Some(expr);
88 },
89 },
90 },
91 Err(_) => match parser.with_tag(
92 ParserTag::SkipExpressionWithoutBlock,
93 Parser::try_parse::<Statement>
94 )? {
95 Ok(stmt) => stmts.push(stmt),
96 Err(_) => break None,
97 },
98 }
99 };
100
101 Ok(Self { stmts, trailing_expr })
102 }
103}
104
105#[derive(derive_more::Debug, derive_more::From, ParseError)]
106pub enum StatementsError {
107 #[parse_error(transparent)]
108 ExpressionStatementWithBlock(
109 ParserError<(ExpressionStatementWithBlock, NotFollows<token::Dot>, NotFollows<token::Question>,)>,
110 ),
111
112 #[parse_error(transparent)]
113 ExpressionWithoutBlock(ParserError<(ExpressionWithoutBlock, Option<token::Semi>)>),
114
115 #[parse_error(transparent)]
116 Statement(ParserError<Statement>),
117}