diff --git a/examples/hello_world.sb b/examples/hello_world.sb index 486984c..3f65a9e 100644 --- a/examples/hello_world.sb +++ b/examples/hello_world.sb @@ -1,3 +1,4 @@ -fn main(n) { - n * 2; -} \ No newline at end of file +main :: (n) { + return 2 * n; +} + diff --git a/examples_out/out.js b/examples_out/out.js index 25e652e..c92ccfa 100644 --- a/examples_out/out.js +++ b/examples_out/out.js @@ -1,3 +1,4 @@ function main(n) { -n * 2} +return 2 * n +} console.log(main()) \ No newline at end of file diff --git a/src/lexer/mod.rs b/src/lexer/mod.rs index a971e4a..fff6fd4 100644 --- a/src/lexer/mod.rs +++ b/src/lexer/mod.rs @@ -53,6 +53,8 @@ pub enum TokenKind { Slash, /// ":" Colon, + /// "::" + DoubleColon, /// ";" SemiColon, /// "," @@ -97,7 +99,7 @@ pub enum Keyword { If, Else, Return, - Function, + FunctionDecl, Boolean, Unknown, } @@ -170,7 +172,13 @@ impl Cursor<'_> { '=' => Equals, _ => Assign, }, - ':' => Colon, + ':' => match self.first() { + ':' => { + self.bump(); + DoubleColon + } + _ => Colon, + }, ';' => SemiColon, ',' => Comma, '<' => LessThan, @@ -250,7 +258,6 @@ impl Cursor<'_> { match original { c if c == "if" => Keyword::If, c if c == "else" => Keyword::Else, - c if c == "fn" => Keyword::Function, c if c == "true" || c == "false" => Keyword::Boolean, c if c == "let" => Keyword::Let, c if c == "return" => Keyword::Return, diff --git a/src/lexer/tests.rs b/src/lexer/tests.rs index b3ed511..94ece8f 100644 --- a/src/lexer/tests.rs +++ b/src/lexer/tests.rs @@ -160,18 +160,46 @@ mod tests { #[test] fn test_functions() { - let mut tokens = tokenize("fn fib() {}").into_iter(); + let mut tokens = tokenize("fib :: () {}").into_iter(); + + assert_eq!( + tokens.nth(0).unwrap(), + Token { + len: 3, + kind: TokenKind::Identifier("fib".into()), + raw: "fib".to_owned(), + pos: Position { + raw: 2, + line: 1, + offset: 2 + } + } + ); + + assert_eq!( + tokens.nth(0).unwrap(), + Token { + len: 1, + kind: TokenKind::Whitespace, + raw: " ".to_owned(), + pos: Position { + raw: 3, + line: 1, + offset: 3 + } + } + ); assert_eq!( tokens.nth(0).unwrap(), Token { len: 2, - kind: TokenKind::Keyword(Keyword::Function), - raw: "fn".to_owned(), + kind: TokenKind::DoubleColon, + raw: "::".to_owned(), pos: Position { - raw: 1, + raw: 5, line: 1, - offset: 1 + offset: 5 } } ); @@ -181,7 +209,7 @@ mod tests { fn test_comments() { let mut tokens = tokenize( "// foo -fn fib() {} +fib :: () {} ", ) .into_iter() @@ -205,16 +233,30 @@ fn fib() {} } ); + assert_eq!( + tokens.nth(0).unwrap(), + Token { + len: 3, + kind: TokenKind::Identifier("fib".into()), + raw: "fib".to_owned(), + pos: Position { + raw: 9, + line: 2, + offset: 3 + } + } + ); + assert_eq!( tokens.nth(0).unwrap(), Token { len: 2, - kind: TokenKind::Keyword(Keyword::Function), - raw: "fn".to_owned(), + kind: TokenKind::DoubleColon, + raw: "::".to_owned(), pos: Position { - raw: 8, + raw: 12, line: 2, - offset: 2 + offset: 6 } } ); diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 1670119..a70a7cd 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -48,6 +48,8 @@ impl Parser { self.peeked.pop() }; + dbg!(&item); + self.current = item.to_owned(); item } @@ -149,9 +151,8 @@ impl Parser { } fn parse_function(&mut self) -> Result { - self.match_keyword(Keyword::Function)?; let name = self.match_identifier()?; - + self.match_token(TokenKind::DoubleColon)?; self.match_token(TokenKind::BraceOpen)?; let arguments: Vec = match self.peek() { diff --git a/src/parser/tests.rs b/src/parser/tests.rs index 90293e9..ec3aeac 100644 --- a/src/parser/tests.rs +++ b/src/parser/tests.rs @@ -3,7 +3,7 @@ use crate::parser::*; #[test] fn test_parse_empty_function() { - let raw = "fn main() {}"; + let raw = "main :: () {}"; let tokens = tokenize(raw); let tree = parse(tokens, Some(raw.to_string())); assert!(tree.is_ok()) @@ -12,7 +12,7 @@ fn test_parse_empty_function() { #[test] fn test_parse_function_with_return() { let raw = " - fn main() { + main :: () { return 1; } "; @@ -24,7 +24,7 @@ fn test_parse_function_with_return() { #[test] fn test_parse_missing_semicolon() { let raw = " - fn main() { + main :: () { return 1 } "; @@ -46,12 +46,12 @@ fn test_parse_no_function_context() { #[test] fn test_parse_multiple_functions() { let raw = " - fn foo() { + foo :: () { let x = 2; return x; } - fn bar() { + bar :: () { let y = 5; return y; } @@ -64,7 +64,7 @@ fn test_parse_multiple_functions() { #[test] fn test_parse_variable_declaration() { let raw = " - fn main() { + main :: () { let x = 1; return x; } @@ -77,7 +77,7 @@ fn test_parse_variable_declaration() { #[test] fn test_parse_function_with_args() { let raw = " - fn main(foo) { + main :: (foo) { return foo; } "; @@ -89,11 +89,11 @@ fn test_parse_function_with_args() { #[test] fn test_parse_function_call() { let raw = " - fn main(foo) { + main :: (foo) { foo(); } - fn foo() { + foo :: () { foo(2); } "; @@ -105,11 +105,11 @@ fn test_parse_function_call() { #[test] fn test_parse_return_function_call() { let raw = " - fn main() { + main :: () { return fib(2); } - fn fib() { + fib :: () { return fib(2); } "; @@ -121,11 +121,11 @@ fn test_parse_return_function_call() { #[test] fn test_parse_function_call_multiple_arguments() { let raw = " - fn main() { + main :: () { fib(1, 2, 3); } - fn fib() { + fib :: () { return 2; } "; @@ -137,11 +137,11 @@ fn test_parse_function_call_multiple_arguments() { #[test] fn test_parse_nexted_function_call() { let raw = " - fn main() { + main :: () { fib(fib(2), 2); } - fn fib(n) { + fib :: (n) { return 2; } "; @@ -153,7 +153,7 @@ fn test_parse_nexted_function_call() { #[test] fn test_parse_basic_ops() { let raw = " - fn main() { + main :: () { return 2 * 5; } "; @@ -165,7 +165,7 @@ fn test_parse_basic_ops() { #[test] fn test_parse_compound_ops() { let raw = " - fn main() { + main :: () { 2 * 5 / 3; } "; @@ -177,7 +177,7 @@ fn test_parse_compound_ops() { #[test] fn test_parse_compound_ops_with_function_call() { let raw = " - fn main() { + main :: () { return 2 * fib(1) / 3; } "; @@ -189,7 +189,7 @@ fn test_parse_compound_ops_with_function_call() { #[test] fn test_parse_compound_ops_with_strings() { let raw = " - fn main() { + main :: () { return 2 * \"Hello\"; } "; @@ -201,7 +201,7 @@ fn test_parse_compound_ops_with_strings() { #[test] fn test_parse_compound_ops_with_identifier() { let raw = " - fn main(n) { + main :: (n) { return 2 * n; } "; @@ -214,7 +214,7 @@ fn test_parse_compound_ops_with_identifier() { #[ignore] fn test_parse_compound_ops_with_identifier_first() { let raw = " - fn main(n) { + main :: (n) { return n * 2; } "; @@ -226,7 +226,7 @@ fn test_parse_compound_ops_with_identifier_first() { #[test] fn test_parse_compound_ops_return() { let raw = " - fn main(n) { + main :: (n) { return 2 * n; } ";