From 4e7e7ad07be149e441549023640b3c9e07da723a Mon Sep 17 00:00:00 2001 From: bog Date: Fri, 1 Mar 2024 18:44:16 +0100 Subject: [PATCH] :sparkles: array values. --- doc/grammar.bnf | 5 +++- src/ast/lexer.rs | 27 +++++++++++++++++++++- src/ast/node.rs | 3 +++ src/ast/parser.rs | 53 ++++++++++++++++++++++++++++++++++--------- src/eval/evaluator.rs | 42 +++++++++++++++++++++++++++++++--- src/eval/value.rs | 3 ++- 6 files changed, 116 insertions(+), 17 deletions(-) diff --git a/doc/grammar.bnf b/doc/grammar.bnf index bfb5024..312c5a2 100644 --- a/doc/grammar.bnf +++ b/doc/grammar.bnf @@ -1,8 +1,11 @@ MODULE ::= INSTR* INSTR ::= EXPR semicolon -EXPR ::= BUILTIN +EXPR ::= LITERAL +LITERAL ::= BUILTIN | ARRAY BUILTIN ::= | bool | float | int | string + +ARRAY ::= osquare EXPR* csquare diff --git a/src/ast/lexer.rs b/src/ast/lexer.rs index b1e2666..efa88bb 100644 --- a/src/ast/lexer.rs +++ b/src/ast/lexer.rs @@ -19,7 +19,7 @@ impl Lexer { line: 1, text: String::from(""), separators: vec![ - ';' + ';', '[', ']' ] } } @@ -242,6 +242,7 @@ impl Lexer { self.cursor += 1; } + self.skip_spaces(); } } @@ -254,6 +255,16 @@ impl Iterator for Lexer { self.skip_spaces(); self.skip_comments(); + if let Some(token) = self.scan_text("[") { + self.cursor = token.position; + return Some(Node::OSquare); + } + + if let Some(token) = self.scan_text("]") { + self.cursor = token.position; + return Some(Node::CSquare); + } + if let Some(token) = self.scan_keyword("true") { self.cursor = token.position; return Some(Node::Bool(token.value == "true")); @@ -417,4 +428,18 @@ mod test { Ok(()) } + + #[test] + fn test_arrays() -> Result<(), error::AstError> { + let mut lex = Lexer::new(); + + let res = lexer_run(&mut lex, + " [ ] ")?; + + assert_eq!(2, res.len()); + assert_eq!(Node::OSquare, *res.get(0).unwrap()); + assert_eq!(Node::CSquare, *res.get(1).unwrap()); + + Ok(()) + } } diff --git a/src/ast/node.rs b/src/ast/node.rs index 437fb96..1b87916 100644 --- a/src/ast/node.rs +++ b/src/ast/node.rs @@ -6,6 +6,9 @@ pub enum Node { Int(i32), Float(f64), String(String), + OSquare, + CSquare, + Array(Vec), Semicolon } diff --git a/src/ast/parser.rs b/src/ast/parser.rs index 8313f73..8bbdd84 100644 --- a/src/ast/parser.rs +++ b/src/ast/parser.rs @@ -62,34 +62,49 @@ impl Parser { } fn parse_expr(&mut self) -> ParseResult { - self.parse_builtin() + self.parse_literal() } - - fn parse_builtin(&mut self) -> ParseResult { + fn parse_literal(&mut self) -> ParseResult { match self.lexer.next() { - Some(Node::Int(value)) + Some(Node::OSquare) => self.parse_array(), + Some(node) => self.parse_builtin(node), + None => Ok(None) + } + } + + fn parse_builtin(&mut self, node: Node) -> ParseResult { + match node { + Node::Int(value) => Ok(Some(Node::Int(value))), - Some(Node::Float(value)) + Node::Float(value) => Ok(Some(Node::Float(value))), - Some(Node::Bool(value)) + Node::Bool(value) => Ok(Some(Node::Bool(value))), - Some(Node::String(value)) + Node::String(value) => Ok(Some(Node::String(value))), - Some(other) => { + _ => { Err(error::AstError { - msg: String::from(format!("unexpected {:?}", other)), + msg: String::from(format!("unexpected {:?}", node)), line: self.lexer.line() }) } - - None => Ok(None) } } + + fn parse_array(&mut self) -> ParseResult { + let mut elements: Vec = vec![]; + + while let Ok(Some(expr)) = self.parse_expr() { + elements.push(expr); + } + + Ok(Some(Node::Array(elements))) + } } #[cfg(test)] @@ -179,4 +194,20 @@ mod test { Ok(()) } + + #[test] + fn arrays() -> TestResult { + test_parser( + Node::Module("mod".to_owned(), vec![ + Node::Array(vec![ + Node::Int(2), + Node::Float(3.2), + Node::Bool(true) + ]) + ]), + " [2 3.2 true]; " + )?; + + Ok(()) + } } diff --git a/src/eval/evaluator.rs b/src/eval/evaluator.rs index 2bc0995..e3309ec 100644 --- a/src/eval/evaluator.rs +++ b/src/eval/evaluator.rs @@ -29,11 +29,32 @@ impl Evaluator { Ok(res) }, - + Node::Bool(value) => Ok(Some(Value::Bool(*value))), Node::Int(value) => Ok(Some(Value::Int(*value))), Node::Float(value) => Ok(Some(Value::Float(*value))), - Node::String(value) => Ok(Some(Value::String(value.clone()))), + Node::String(value) + => Ok(Some(Value::String(value.clone()))), + Node::Array(nodes) => { + let mut values: Vec = vec![]; + + for node in nodes { + match self.run(node) { + Ok(Some(value)) => { + values.push(value); + }, + + _ => { + return Err(EvalError { + msg: String::from("invalid array element"), + line: 0 + }); + } + } + } + + Ok(Some(Value::Array(values))) + } _ => Ok(None) } @@ -98,9 +119,24 @@ mod test { #[test] fn strings() -> TestResult { - test_eval_value(Value::String(String::from(" pizzza!!!")), + test_eval_value(Value::String(String::from(" pizzza!!!")), " \" pizzza!!!\"; ")?; Ok(()) } + + #[test] + fn arrays() -> TestResult { + test_eval_value( + Value::Array( + vec![ + Value::Int(2), + Value::Int(4), + Value::Float(6.1) + ] + ), + " [2 4 6.1]; ")?; + + Ok(()) + } } diff --git a/src/eval/value.rs b/src/eval/value.rs index a6af228..8577d58 100644 --- a/src/eval/value.rs +++ b/src/eval/value.rs @@ -4,6 +4,7 @@ pub enum Value { Bool(bool), Int(i32), Float(f64), - String(String) + String(String), + Array(Vec) }