From b0606195f5e2b231b8992ac9a706f8683d5e7046 Mon Sep 17 00:00:00 2001 From: Araozu Date: Mon, 18 Mar 2024 08:57:28 -0500 Subject: [PATCH] Use val/var again instead of let/mut --- CHANGELOG.md | 2 +- src/lexic/scanner/identifier.rs | 16 +++++++------- src/lexic/token.rs | 4 ++-- src/semantic/impls.rs | 4 ++-- src/syntax/binding.rs | 37 ++++++++++++++++----------------- src/syntax/grammar.md | 1 + src/syntax/mod.rs | 16 ++++++++++++++ src/syntax/statement.rs | 2 +- 8 files changed, 49 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c08eeca..40aa6e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,7 +41,7 @@ - [ ] Parse bindings and function declarations as top level constructs - [ ] Parse function declaration arguments (`Type id`) - [ ] Parse function return datatype (`fun f() -> Type`) -- [ ] Return parsing to variables to var/val +- [x] Return parsing to variables to var/val - [ ] Write tests diff --git a/src/lexic/scanner/identifier.rs b/src/lexic/scanner/identifier.rs index ae9420a..c426d77 100755 --- a/src/lexic/scanner/identifier.rs +++ b/src/lexic/scanner/identifier.rs @@ -4,8 +4,8 @@ use crate::lexic::{token::Token, utils, LexResult}; /// Checks if a String is a keyword, and returns its TokenType fn str_is_keyword(s: &String) -> Option { match s.as_str() { - "let" => Some(TokenType::LET), - "mut" => Some(TokenType::MUT), + "val" => Some(TokenType::VAL), + "var" => Some(TokenType::VAR), "fun" => Some(TokenType::FUN), _ => None, } @@ -141,23 +141,23 @@ mod tests { // Should scan keywords #[test] fn test_4() { - let input = str_to_vec("mut"); + let input = str_to_vec("var"); let start_pos = 0; if let LexResult::Some(token, next) = scan(*input.get(0).unwrap(), &input, start_pos) { assert_eq!(3, next); - assert_eq!(TokenType::MUT, token.token_type); - assert_eq!("mut", token.value); + assert_eq!(TokenType::VAR, token.token_type); + assert_eq!("var", token.value); assert_eq!(0, token.position); } else { panic!() } - let input = str_to_vec("let"); + let input = str_to_vec("val"); let start_pos = 0; if let LexResult::Some(token, next) = scan(*input.get(0).unwrap(), &input, start_pos) { assert_eq!(3, next); - assert_eq!(TokenType::LET, token.token_type); - assert_eq!("let", token.value); + assert_eq!(TokenType::VAL, token.token_type); + assert_eq!("val", token.value); assert_eq!(0, token.position); } else { panic!() diff --git a/src/lexic/token.rs b/src/lexic/token.rs index 6941508..074ddf1 100755 --- a/src/lexic/token.rs +++ b/src/lexic/token.rs @@ -16,8 +16,8 @@ pub enum TokenType { Comma, INDENT, DEDENT, - LET, - MUT, + VAL, + VAR, EOF, FUN, } diff --git a/src/semantic/impls.rs b/src/semantic/impls.rs index 636e31f..437a59f 100644 --- a/src/semantic/impls.rs +++ b/src/semantic/impls.rs @@ -32,7 +32,7 @@ impl SemanticCheck for TopLevelDeclaration<'_> { error_start: binding.identifier.position, error_end: binding.identifier.get_end_position(), reason: format!( - "Duplicated function: A function with name {} was already defined", + "Duplicated: A symbol with name {} was already defined", binding_name ), }; @@ -72,7 +72,7 @@ impl SemanticCheck for TopLevelDeclaration<'_> { error_start: function.identifier.position, error_end: function.identifier.get_end_position(), reason: format!( - "Duplicated function: A function with name {} was already defined", + "Duplicated: A symbol with name {} was already defined", function_name ), }; diff --git a/src/syntax/binding.rs b/src/syntax/binding.rs index f0e7b5e..efd2a84 100644 --- a/src/syntax/binding.rs +++ b/src/syntax/binding.rs @@ -14,16 +14,15 @@ pub fn try_parse<'a>(tokens: &'a Vec, pos: usize) -> ParsingResult { - let mut_token = parse_token_type(tokens, next_let, TokenType::MUT); - match mut_token { - Ok((_mut_token, next_mut)) => (true, let_token, next_mut), - _ => (false, let_token, next_let), + match parse_token_type(tokens, current_pos, TokenType::VAL) { + Ok((val_token, next_pos)) => (false, val_token, next_pos), + _ => { + // If VAL is not found, search for VAR + match parse_token_type(tokens, current_pos, TokenType::VAR) { + Ok((var_token, next_pos)) => (true, var_token, next_pos), + _ => return Err(ParsingError::Unmatched), } } - _ => return Err(ParsingError::Unmatched), } }; current_pos = next_pos; @@ -112,7 +111,7 @@ mod tests { #[test] fn should_parse_val_binding() { - let tokens = get_tokens(&String::from("let identifier = 20")).unwrap(); + let tokens = get_tokens(&String::from("val identifier = 20")).unwrap(); let Ok((binding, _)) = try_parse(&tokens, 0) else { panic!() }; @@ -122,11 +121,11 @@ mod tests { #[test] fn should_parse_val() { - let tokens = get_tokens(&String::from("let")).unwrap(); - let (token, _) = parse_token_type(&tokens, 0, TokenType::LET).unwrap(); + let tokens = get_tokens(&String::from("val")).unwrap(); + let (token, _) = parse_token_type(&tokens, 0, TokenType::VAL).unwrap(); - assert_eq!(TokenType::LET, token.token_type); - assert_eq!("let", token.value); + assert_eq!(TokenType::VAL, token.token_type); + assert_eq!("val", token.value); } #[test] @@ -168,8 +167,8 @@ mod tests { #[test] fn should_return_correct_error() { - let tokens = get_tokens(&String::from("let")).unwrap(); - assert_eq!(TokenType::LET, tokens[0].token_type); + let tokens = get_tokens(&String::from("val")).unwrap(); + assert_eq!(TokenType::VAL, tokens[0].token_type); assert_eq!(0, tokens[0].position); let binding = try_parse(&tokens, 0); @@ -184,8 +183,8 @@ mod tests { #[test] fn should_return_error_when_identifier_is_wrong() { - let tokens = get_tokens(&String::from("let 322")).unwrap(); - assert_eq!(TokenType::LET, tokens[0].token_type); + let tokens = get_tokens(&String::from("val 322")).unwrap(); + assert_eq!(TokenType::VAL, tokens[0].token_type); assert_eq!(0, tokens[0].position); let binding = try_parse(&tokens, 0); @@ -197,7 +196,7 @@ mod tests { _ => panic!("Error expected"), } - let tokens = get_tokens(&String::from("let \"hello\"")).unwrap(); + let tokens = get_tokens(&String::from("val \"hello\"")).unwrap(); let binding = try_parse(&tokens, 0); match binding { @@ -211,7 +210,7 @@ mod tests { #[test] fn should_return_error_when_equal_op_is_wrong() { - let tokens = get_tokens(&String::from("let id \"error\"")).unwrap(); + let tokens = get_tokens(&String::from("val id \"error\"")).unwrap(); let binding = try_parse(&tokens, 0); match binding { diff --git a/src/syntax/grammar.md b/src/syntax/grammar.md index b1124ab..681b076 100644 --- a/src/syntax/grammar.md +++ b/src/syntax/grammar.md @@ -16,6 +16,7 @@ simple function calls, and then implement other features top down ```ebnf top level statement = expression | function declaration + | binding ``` diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index 44d3e77..20f1cc4 100755 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -81,6 +81,22 @@ fn next_construct<'a>( _ => {} } + // Try to parse a binding + match binding::try_parse(tokens, current_pos) { + Ok((binding, next_pos)) => return Ok((TopLevelDeclaration::Binding(binding), next_pos)), + Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)), + _ => {} + } + + // Try to parse an expression + match expression::try_parse(tokens, current_pos) { + Ok((expression, next_pos)) => { + return Ok((TopLevelDeclaration::Expression(expression), next_pos)) + } + Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)), + _ => {} + } + // No top level construct was found, return unmatched Err(ParsingError::Unmatched) } diff --git a/src/syntax/statement.rs b/src/syntax/statement.rs index 7d1a9da..097ec5c 100644 --- a/src/syntax/statement.rs +++ b/src/syntax/statement.rs @@ -49,7 +49,7 @@ mod tests { #[test] fn should_parse_binding() { - let input = String::from("let identifier = 20"); + let input = String::from("val identifier = 20"); let tokens = crate::lexic::get_tokens(&input).unwrap(); let statement = try_parse(&tokens, 0);