rune/ast/
block.rs
1use crate::ast::prelude::*;
2
3#[test]
4#[cfg(not(miri))]
5fn ast_parse() {
6 let expr = rt::<ast::ExprBlock>("{}");
7 assert_eq!(expr.block.statements.len(), 0);
8
9 let expr = rt::<ast::ExprBlock>("{ 42 }");
10 assert_eq!(expr.block.statements.len(), 1);
11
12 let block = rt::<ast::Block>("{ foo }");
13 assert_eq!(block.statements.len(), 1);
14
15 let block = rt::<ast::Block>("{ foo; }");
16 assert_eq!(block.statements.len(), 1);
17
18 let expr = rt::<ast::ExprBlock>("#[retry] { 42 }");
19 assert_eq!(expr.block.statements.len(), 1);
20 assert_eq!(expr.attributes.len(), 1);
21
22 let block = rt::<ast::Block>(
23 r#"
24 {
25 let foo = 42;
26 let bar = "string";
27 baz
28 }
29 "#,
30 );
31
32 assert_eq!(block.statements.len(), 3);
33
34 let block = rt::<ast::EmptyBlock>(
35 r#"
36 let foo = 42;
37 let bar = "string";
38 baz
39 "#,
40 );
41
42 assert_eq!(block.statements.len(), 3);
43}
44
45#[derive(Debug, TryClone, PartialEq, Eq, ToTokens, Spanned)]
49#[non_exhaustive]
50pub struct Block {
51 pub open: T!['{'],
53 #[rune(iter)]
55 pub statements: Vec<ast::Stmt>,
56 pub close: T!['}'],
58 #[rune(skip)]
60 pub(crate) id: ItemId,
61}
62
63impl Parse for Block {
64 fn parse(parser: &mut Parser<'_>) -> Result<Self> {
65 let mut statements = Vec::new();
66
67 let open = parser.parse()?;
68
69 while !parser.peek::<T!['}']>()? {
70 statements.try_push(parser.parse()?)?;
71 }
72
73 let close = parser.parse()?;
74
75 Ok(Self {
76 open,
77 statements,
78 close,
79 id: ItemId::ROOT,
80 })
81 }
82}
83
84#[derive(Debug, TryClone, PartialEq, Eq, ToTokens)]
88#[non_exhaustive]
89pub struct EmptyBlock {
90 pub statements: Vec<ast::Stmt>,
92 #[rune(skip)]
94 pub(crate) id: ItemId,
95}
96
97impl Parse for EmptyBlock {
98 fn parse(parser: &mut Parser<'_>) -> Result<Self> {
99 let mut statements = Vec::new();
100
101 while !parser.is_eof()? {
102 statements.try_push(parser.parse()?)?;
103 }
104
105 Ok(Self {
106 statements,
107 id: ItemId::ROOT,
108 })
109 }
110}