summaryrefslogtreecommitdiffstats
path: root/crates/rebel-parse
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2024-05-04 13:45:43 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2024-05-04 20:14:47 +0200
commit318a842241fccef0184c69e31a7d08306799c6c6 (patch)
tree74ac021a78a06f4f253793c98c87149d705ec675 /crates/rebel-parse
parent50443fbd17651861a738d940d8ebd2883f6f2651 (diff)
downloadrebel-318a842241fccef0184c69e31a7d08306799c6c6.tar
rebel-318a842241fccef0184c69e31a7d08306799c6c6.zip
rebel-parse, rebel-lang: implement if-else expressions
Diffstat (limited to 'crates/rebel-parse')
-rw-r--r--crates/rebel-parse/src/ast/expr.rs17
-rw-r--r--crates/rebel-parse/src/grammar/recipe.rs15
2 files changed, 29 insertions, 3 deletions
diff --git a/crates/rebel-parse/src/ast/expr.rs b/crates/rebel-parse/src/ast/expr.rs
index 2e8d750..3994296 100644
--- a/crates/rebel-parse/src/ast/expr.rs
+++ b/crates/rebel-parse/src/ast/expr.rs
@@ -34,6 +34,10 @@ pub enum Expr<'a> {
field: Ident<'a>,
},
Block(Block<'a>),
+ IfElse {
+ if_blocks: Vec<(Expr<'a>, Block<'a>)>,
+ else_block: Option<Box<Block<'a>>>,
+ },
Paren(Box<Expr<'a>>),
Path(Path<'a>),
Literal(Literal<'a>),
@@ -129,6 +133,19 @@ impl<'a> Expr<'a> {
}
Ok(())
}
+ Expr::IfElse {
+ if_blocks,
+ else_block,
+ } => {
+ for (cond, block) in if_blocks {
+ cond.validate()?;
+ block.validate()?;
+ }
+ if let Some(block) = else_block {
+ block.validate()?;
+ }
+ Ok(())
+ }
Expr::Paren(expr) => expr.validate(),
Expr::Path(_) => Ok(()),
Expr::Literal(lit) => lit.validate(),
diff --git a/crates/rebel-parse/src/grammar/recipe.rs b/crates/rebel-parse/src/grammar/recipe.rs
index 11f1ce6..1ada80c 100644
--- a/crates/rebel-parse/src/grammar/recipe.rs
+++ b/crates/rebel-parse/src/grammar/recipe.rs
@@ -133,15 +133,24 @@ peg::parser! {
}
base:@ p('.') field:field() { Expr::field(base, field) }
--
- p('(') e:expr() p(')') { Expr::paren(e) }
- p('{') block:block() p('}') { Expr::Block(block) }
e:atom() { e }
}
rule atom() -> Expr<'a>
- = lit:literal() { Expr::Literal(lit) }
+ = p('(') e:expr() p(')') { Expr::paren(e) }
+ / [Token::Keyword(Keyword::If)]
+ if_blocks:(cond_block() ++ ([Token::Keyword(Keyword::Else)] [Token::Keyword(Keyword::If)]))
+ else_block:([Token::Keyword(Keyword::Else)] p('{') block:block() p('}') { Box::new(block) })?
+ {
+ Expr::IfElse { if_blocks, else_block }
+ }
+ / p('{') block:block() p('}') { Expr::Block(block) }
+ / lit:literal() { Expr::Literal(lit) }
/ path:path() { Expr::Path(path) }
+ rule cond_block() -> (Expr<'a>, ast::Block<'a>)
+ = cond:expr() p('{') block:block() p('}') { (cond, block) }
+
rule call_params() -> Vec<expr::Expr<'a>>
= args:delimited(<expr()>, <p(',')>) { args }