1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
use crate::ast; use crate::parsing::Opaque; use crate::{Id, Parse, ParseError, Parser, Spanned, ToTokens}; /// A block of expressions. /// /// ```rust /// use rune::{testing, ast}; /// /// let expr = testing::roundtrip::<ast::ExprBlock>("{}"); /// assert_eq!(expr.block.statements.len(), 0); /// /// let expr = testing::roundtrip::<ast::ExprBlock>("{ 42 }"); /// assert_eq!(expr.block.statements.len(), 1); /// /// let expr = testing::roundtrip::<ast::ExprBlock>("#[retry] { 42 }"); /// assert_eq!(expr.block.statements.len(), 1); /// assert_eq!(expr.attributes.len(), 1); /// ``` #[derive(Debug, Clone, PartialEq, Eq, ToTokens, Spanned)] pub struct Block { /// The unique identifier for the block expression. #[rune(id)] pub id: Option<Id>, /// The close brace. pub open: T!['{'], /// Statements in the block. pub statements: Vec<ast::Stmt>, /// The close brace. pub close: T!['}'], } impl Opaque for Block { fn id(&self) -> Option<Id> { self.id } } impl Block { /// Test if the block produces nothing. pub fn produces_nothing(&self) -> bool { let mut it = self.statements.iter(); while let Some(ast::Stmt::Expr(_, semi)) = it.next_back() { return semi.is_some(); } true } } /// Parse implementation for a block. /// /// # Examples /// /// ```rust /// use rune::{testing, ast}; /// /// let block = testing::roundtrip::<ast::Block>("{}"); /// assert_eq!(block.statements.len(), 0); /// assert!(block.produces_nothing()); /// /// let block = testing::roundtrip::<ast::Block>("{ foo }"); /// assert_eq!(block.statements.len(), 1); /// assert!(!block.produces_nothing()); /// /// let block = testing::roundtrip::<ast::Block>("{ foo; }"); /// assert_eq!(block.statements.len(), 1); /// assert!(block.produces_nothing()); /// /// let block = testing::roundtrip::<ast::Block>(r#" /// { /// let foo = 42; /// let bar = "string"; /// baz /// } /// "#); /// /// assert_eq!(block.statements.len(), 3); /// ``` impl Parse for Block { fn parse(parser: &mut Parser<'_>) -> Result<Self, ParseError> { let mut statements = Vec::new(); let open = parser.parse()?; while !parser.peek::<T!['}']>()? { statements.push(parser.parse()?); } let close = parser.parse()?; Ok(Block { id: Default::default(), open, statements, close, }) } }