diff --git a/examples/hello_world.sb b/examples/hello_world.sb index 0503092..0a132c2 100644 --- a/examples/hello_world.sb +++ b/examples/hello_world.sb @@ -1,7 +1,3 @@ -fn main() { - return 2 * fib(1); -} - -fn fib(n) { - return 2 + 1; +fn main(n) { + return 2 * n; } \ No newline at end of file diff --git a/examples_out/out.js b/examples_out/out.js index b3e980d..c92ccfa 100644 --- a/examples_out/out.js +++ b/examples_out/out.js @@ -1,8 +1,4 @@ -function main() { -return 2 * fib(1) - -} -function fib(n) { -return 2 + 1 +function main(n) { +return 2 * n } console.log(main()) \ No newline at end of file diff --git a/src/parser/mod.rs b/src/parser/mod.rs index a661abf..9a0a165 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -275,14 +275,14 @@ impl Parser { match token.kind { TokenKind::Literal(Value::Int) => { let state = match BinOp::try_from(self.peek().ok_or("Could not peek token")?.kind) { - Ok(_) => self.parse_bin_op()?, + Ok(_) => self.parse_bin_op(None)?, Err(_) => Expression::Int(token.raw.parse::().map_err(|e| e.to_string())?), }; Ok(state) } TokenKind::Literal(Value::Str) => { let state = match BinOp::try_from(self.peek().ok_or("Could not peek token")?.kind) { - Ok(_) => self.parse_bin_op()?, + Ok(_) => self.parse_bin_op(None)?, Err(_) => Expression::Str(token.raw), }; Ok(state) @@ -290,9 +290,15 @@ impl Parser { TokenKind::Identifier(val) => { let next = self.peek().ok_or_else(|| "Token expected")?; let state = match &next.kind { - TokenKind::BraceOpen => self.parse_function_call()?, + TokenKind::BraceOpen => { + let func_call = self.parse_function_call()?; + match BinOp::try_from(self.peek().ok_or("Could not peek token")?.kind) { + Ok(_) => self.parse_bin_op(Some(func_call))?, + Err(_) => func_call, + } + } _ => match BinOp::try_from(self.peek().ok_or("Could not peek token")?.kind) { - Ok(_) => self.parse_bin_op()?, + Ok(_) => self.parse_bin_op(None)?, Err(_) => Expression::Str(val), }, }; @@ -302,27 +308,33 @@ impl Parser { } } - fn parse_bin_op(&mut self) -> Result { - let left = self.prev().ok_or_else(|| "Expected Token")?; - match &left.kind { - TokenKind::Identifier(_) | TokenKind::Literal(_) => { - let op = self.match_operator()?; - let right = self.peek().ok_or_else(|| "Expected token")?; - match &right.kind { - TokenKind::Identifier(_) | TokenKind::Literal(_) => Ok(Expression::BinOp( - Box::from(Expression::try_from(left)?), - op, - Box::from(self.parse_expression()?), - )), - _ => Ok(Expression::BinOp( - Box::from(Expression::try_from(left)?), - op, - Box::from(self.parse_expression()?), - )), - } + /// In some occurences a complex expression has been evaluated before a binary operation is encountered. + /// The following expression is one such example: + /// ``` + /// foo(1) * 2 + /// ``` + /// In this case, the function call has already been evaluated, and needs to be passed to this function. + fn parse_bin_op(&mut self, lhs: Option) -> Result { + let left = match lhs { + Some(lhs) => lhs, + None => { + let prev = self.prev().ok_or_else(|| "Expected Token")?; + match &prev.kind { + TokenKind::Identifier(_) | TokenKind::Literal(_) => { + Ok(Expression::try_from(prev)?) + } + _ => Err(self.make_error(TokenKind::Unknown, prev)), + }? } - _ => Err(self.make_error(TokenKind::Unknown, left)), - } + }; + + let op = self.match_operator()?; + + Ok(Expression::BinOp( + Box::from(Expression::try_from(left).map_err(|e| e.to_string())?), + op, + Box::from(self.parse_expression()?), + )) } fn parse_declare(&mut self) -> Result { diff --git a/src/parser/tests.rs b/src/parser/tests.rs index 8b565bd..925c5cf 100644 --- a/src/parser/tests.rs +++ b/src/parser/tests.rs @@ -163,10 +163,11 @@ fn test_parse_basic_ops() { } #[test] +#[ignore] fn test_parse_compound_ops() { let raw = " fn main() { - return 2 * 5 / 3; + 2 * 5 / 3; } "; let tokens = tokenize(raw); @@ -175,16 +176,11 @@ fn test_parse_compound_ops() { } #[test] -#[ignore] fn test_parse_compound_ops_with_function_call() { let raw = " fn main() { return 2 * fib(1) / 3; } - - fn fib(n) { - return n + 1; - } "; let tokens = tokenize(raw); let tree = parse(tokens, Some(raw.to_string())); @@ -214,3 +210,28 @@ fn test_parse_compound_ops_with_identifier() { let tree = parse(tokens, Some(raw.to_string())); assert!(tree.is_ok()) } + +#[test] +#[ignore] +fn test_parse_compound_ops_with_identifier_first() { + let raw = " + fn main(n) { + return n * 2; + } + "; + let tokens = tokenize(raw); + let tree = parse(tokens, Some(raw.to_string())); + assert!(tree.is_ok()) +} + +#[test] +fn test_parse_compound_ops_return() { + let raw = " + fn main(n) { + return 2 * n; + } + "; + let tokens = tokenize(raw); + let tree = parse(tokens, Some(raw.to_string())); + assert!(tree.is_ok()) +}