From 8fe1e42c437a6c4b56638eb77b986ae7bb35d453 Mon Sep 17 00:00:00 2001 From: Garrit Franke Date: Wed, 9 Dec 2020 18:43:10 +0100 Subject: [PATCH] Add booleans --- examples/playground.sb | 6 ++++-- src/generator/js.rs | 2 ++ src/parser/node_type.rs | 8 +++++++- src/parser/rules.rs | 11 ++++++++++- src/parser/tests.rs | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 55 insertions(+), 4 deletions(-) diff --git a/examples/playground.sb b/examples/playground.sb index b10cc29..9c10151 100644 --- a/examples/playground.sb +++ b/examples/playground.sb @@ -1,6 +1,8 @@ fn main() { - let x = 5 * 2 - while x > 0 { + let x = true && false + let y = false && true || true + let z = x && true + while true && x { return x } } \ No newline at end of file diff --git a/src/generator/js.rs b/src/generator/js.rs index a7f0ab9..d2e6843 100644 --- a/src/generator/js.rs +++ b/src/generator/js.rs @@ -82,6 +82,7 @@ fn generate_expression(expr: Expression) -> String { Expression::Int(val) => val.to_string(), Expression::Variable(val) | Expression::Str(val) => val, Expression::Char(_) => todo!(), + Expression::Bool(b) => b.to_string(), Expression::FunctionCall(name, e) => generate_function_call(name, e), Expression::Assign(_, _) => todo!(), Expression::Array(els) => generate_array(els), @@ -157,6 +158,7 @@ fn generate_function_call(func: String, args: Vec) -> String { .map(|arg| match arg { Expression::Char(c) => c.to_string(), Expression::Int(i) => i.to_string(), + Expression::Bool(v) => v.to_string(), Expression::FunctionCall(n, a) => generate_function_call(n, a), Expression::Str(s) | Expression::Variable(s) => s, Expression::Assign(_, _) => todo!(), diff --git a/src/parser/node_type.rs b/src/parser/node_type.rs index 5abda20..b483395 100644 --- a/src/parser/node_type.rs +++ b/src/parser/node_type.rs @@ -49,6 +49,7 @@ pub enum Expression { Int(u32), Str(String), Char(u8), + Bool(bool), Array(Vec), FunctionCall(String, Vec), Variable(String), @@ -69,8 +70,13 @@ impl TryFrom for Expression { .parse() .map_err(|_| "Int value could not be parsed")?, )), + TokenKind::Keyword(Keyword::Boolean) => match token.raw.as_ref() { + "true" => Ok(Expression::Bool(true)), + "false" => Ok(Expression::Bool(false)), + _ => Err("Boolean value could not be parsed".into()), + }, TokenKind::Literal(Value::Str) => Ok(Expression::Str(token.raw)), - _ => panic!("Value could not be parsed"), + _ => Err("Value could not be parsed".into()), } } } diff --git a/src/parser/rules.rs b/src/parser/rules.rs index 455ecc6..0037257 100644 --- a/src/parser/rules.rs +++ b/src/parser/rules.rs @@ -157,6 +157,15 @@ impl Parser { fn parse_expression(&mut self) -> Result { let token = self.next()?; match token.kind { + TokenKind::Keyword(Keyword::Boolean) => { + let state = match BinOp::try_from(self.peek()?.kind) { + Ok(_) => self.parse_bin_op(None)?, + Err(_) => { + Expression::Bool(token.raw.parse::().map_err(|e| e.to_string())?) + } + }; + Ok(state) + } TokenKind::Literal(Value::Int) => { let state = match BinOp::try_from(self.peek()?.kind) { Ok(_) => self.parse_bin_op(None)?, @@ -269,7 +278,7 @@ impl Parser { None => { let prev = self.prev().ok_or_else(|| "Expected Token")?; match &prev.kind { - TokenKind::Identifier(_) | TokenKind::Literal(_) => { + TokenKind::Identifier(_) | TokenKind::Literal(_) | TokenKind::Keyword(_) => { Ok(Expression::try_from(prev)?) } _ => Err(self.make_error(TokenKind::Unknown, prev)), diff --git a/src/parser/tests.rs b/src/parser/tests.rs index 139f8d6..633a16d 100644 --- a/src/parser/tests.rs +++ b/src/parser/tests.rs @@ -391,3 +391,35 @@ fn test_basic_while_loop() { let tree = parse(tokens, Some(raw.to_string())); assert!(tree.is_ok()) } + +#[test] +fn test_while_loop_boolean_expression() { + let raw = " + fn main() { + let x = 5 * 2 + while true && x { + return x + } + } + "; + let tokens = tokenize(raw); + let tree = parse(tokens, Some(raw.to_string())); + assert!(tree.is_ok()) +} + +#[test] +fn test_boolean_arithmetic() { + let raw = " + fn main() { + let x = true && false + let y = false && true || true + let z = x && true + while true && x { + return x + } + } + "; + let tokens = tokenize(raw); + let tree = parse(tokens, Some(raw.to_string())); + assert!(tree.is_ok()) +}