From 0795e76ae45b0479289acb2ee4be5ab29980f7a2 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 28 Apr 2024 13:45:11 +0200 Subject: rebel-parse: implement validation for statements --- crates/rebel-parse/src/ast.rs | 41 +++++++++++++++++++++++++++++++- crates/rebel-parse/src/grammar/recipe.rs | 4 ++-- 2 files changed, 42 insertions(+), 3 deletions(-) (limited to 'crates/rebel-parse') diff --git a/crates/rebel-parse/src/ast.rs b/crates/rebel-parse/src/ast.rs index 1dcbdd9..e3b93ba 100644 --- a/crates/rebel-parse/src/ast.rs +++ b/crates/rebel-parse/src/ast.rs @@ -18,7 +18,34 @@ pub enum RecipeStmt<'a> { }, } -pub type Body<'a> = Vec>; +impl<'a> RecipeStmt<'a> { + pub fn validate(&self) -> Result<(), ValidationError> { + match self { + RecipeStmt::BodyStmt(stmt) => stmt.validate(), + RecipeStmt::Fetch { name: _, body } => body.validate(), + RecipeStmt::Task { + name: _, + params: _, + body, + } => { + // TODO: Validate params? + body.validate() + } + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Body<'a>(pub Vec>); + +impl<'a> Body<'a> { + pub fn validate(&self) -> Result<(), ValidationError> { + for stmt in &self.0 { + stmt.validate()?; + } + Ok(()) + } +} #[derive(Debug, Clone, PartialEq, Eq)] pub enum BodyStmt<'a> { @@ -40,6 +67,18 @@ impl<'a> BodyStmt<'a> { None => BodyStmt::Assign { dest, expr }, } } + + pub fn validate(&self) -> Result<(), ValidationError> { + match self { + BodyStmt::Assign { dest, expr } => { + // TODO: Extend destination validation + dest.expr.validate()?; + expr.validate() + } + BodyStmt::Expr { expr } => expr.validate(), + BodyStmt::Empty => Ok(()), + } + } } #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/crates/rebel-parse/src/grammar/recipe.rs b/crates/rebel-parse/src/grammar/recipe.rs index 71c2733..393b12c 100644 --- a/crates/rebel-parse/src/grammar/recipe.rs +++ b/crates/rebel-parse/src/grammar/recipe.rs @@ -13,7 +13,7 @@ peg::parser! { pub rule recipe_stmt() -> ast::RecipeStmt<'a> = keyword_fetch() name:ident() p('{') body:body() p('}') { - ast::RecipeStmt::Fetch { name, body: Vec::new() } + ast::RecipeStmt::Fetch { name, body: ast::Body(Vec::new()) } } / keyword_task() name:ident() p('(') params:func_params() p(')') p('{') body:body() p('}') { @@ -24,7 +24,7 @@ peg::parser! { } pub rule body() -> ast::Body<'a> - = body:body_stmt() ++ p(';') { body } + = body:body_stmt() ++ p(';') { ast::Body(body) } pub rule body_stmt() -> ast::BodyStmt<'a> = dest:typed_expr() op:assign_op() expr:expr() { -- cgit v1.2.3