From b5a9dad9908f12d805d433cc31b9d1b27dcddc9f Mon Sep 17 00:00:00 2001 From: Louis Capitanchik <contact@louiscap.co> Date: Tue, 16 May 2023 00:12:15 +0100 Subject: [PATCH] Support empty conditionals, assignment, variable declarations, ident-as-value --- forge-script-lang/src/parser/ast.rs | 12 +++++++++++ forge-script-lang/src/parser/grammar.rs | 20 ++++++++++++++----- .../src/runtime/executor/printer.rs | 3 +++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/forge-script-lang/src/parser/ast.rs b/forge-script-lang/src/parser/ast.rs index f6b8f55..739cacb 100644 --- a/forge-script-lang/src/parser/ast.rs +++ b/forge-script-lang/src/parser/ast.rs @@ -18,7 +18,18 @@ pub struct ExpressionList { pub expressions: Vec<Expression>, pub is_void: bool, } +impl Default for ExpressionList { + fn default() -> Self { + ExpressionList::empty() + } +} impl ExpressionList { + pub fn empty() -> Self { + ExpressionList { + expressions: Vec::new(), + is_void: true, + } + } pub fn production(expressions: Vec<Expression>) -> Self { ExpressionList { expressions, @@ -155,6 +166,7 @@ pub enum ValueExpression { DeclareIdentifier(DeclareIdent), Assignment(Assignment), ConditionalBlock(Conditional), + Identifier(Identifier), } #[derive(Clone)] diff --git a/forge-script-lang/src/parser/grammar.rs b/forge-script-lang/src/parser/grammar.rs index 9e5fdba..30cbd86 100644 --- a/forge-script-lang/src/parser/grammar.rs +++ b/forge-script-lang/src/parser/grammar.rs @@ -29,19 +29,26 @@ peg::parser! { rule value_expression() -> ValueExpression = "(" ex:value_expression() ")" { ValueExpression::Grouped(GroupedExpression { inner: Box::new(ex) }) } / co:conditional() { ValueExpression::ConditionalBlock(co) } + / decl:declare_variable() { ValueExpression::DeclareIdentifier(decl) } / left:value_expression() op:binary_operator() right:value_expression() { ValueExpression::Binary { lhs: Box::new(left), rhs: Box::new(right), operator: op } } / op:unary_operator() operand:value_expression() { ValueExpression::Unary { operator: op, operand: Box::new(operand) } } + / ident:bare_identifier() { ValueExpression::Identifier(ident) } / li:literal() { ValueExpression::Literal(li) } rule print() -> Print = "print" ex:value_expression() { ex.into() } + rule declare_variable() -> DeclareIdent + = "let" assign:assignment() { DeclareIdent::WithValue(assign) } + / "let" ident:bare_identifier() { DeclareIdent::WithoutValue(ident) } + rule condition_loop() -> ConditionalLoop - = "while" guard:value_expression() "{" block:expression_list() "}" { ConditionalLoop { block: GuardedBlock { guard: Box::new(guard), block}, fallback: None } } - / "while" guard:value_expression() "{" block:expression_list() "}" "else" "{" fallback:expression_list() "}" - { ConditionalLoop { block: GuardedBlock { guard: Box::new(guard), block}, fallback: Some(fallback) } } + = "while" guard:value_expression() "{" block:expression_list()? "}" + { ConditionalLoop { block: GuardedBlock { guard: Box::new(guard), block: block.unwrap_or_default() }, fallback: None } } + / "while" guard:value_expression() "{" block:expression_list()? "}" "else" "{" fallback:expression_list()? "}" + { ConditionalLoop { block: GuardedBlock { guard: Box::new(guard), block: block.unwrap_or_default() }, fallback } } rule conditional() -> Conditional // = bl:guarded_block() { Conditional { fallback: None, blocks: vec![bl] } } @@ -54,8 +61,11 @@ peg::parser! { / blocks:(guarded_block() ++ "else") { Conditional { fallback: None, blocks, } } rule guarded_block() -> GuardedBlock - = "if" guard:value_expression() "{" block:expression_list() "}" - { GuardedBlock { block, guard: Box::new(guard) } } + = "if" guard:value_expression() "{" block:expression_list()? "}" + { GuardedBlock { block: block.unwrap_or_default(), guard: Box::new(guard) } } + + rule assignment() -> Assignment + = ident:bare_identifier() "=" expr:value_expression() { Assignment { ident, value: Box::new(expr) } } rule binary_operator() -> BinaryOp = "+" { BinaryOp::Add } diff --git a/forge-script-lang/src/runtime/executor/printer.rs b/forge-script-lang/src/runtime/executor/printer.rs index 7431492..0c05b5d 100644 --- a/forge-script-lang/src/runtime/executor/printer.rs +++ b/forge-script-lang/src/runtime/executor/printer.rs @@ -140,6 +140,9 @@ impl Visitor for TreePrinter { self.evaluate_value_expression(inner.as_ref()); self.write(")"); } + ValueExpression::Identifier(ident) => { + self.write(ident); + } } } -- GitLab