From 08e660984e3d4e6ea5188f117c9ae69f1e0531cf Mon Sep 17 00:00:00 2001 From: Lucas Date: Wed, 12 Jun 2024 03:42:32 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20(parser):=20Add=20variable=20declar?= =?UTF-8?q?ations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit semver: minor --- src/main.rs | 2 +- src/parser/lookup.rs | 34 +++++++++++++++------------------- src/parser/mod.rs | 2 ++ src/parser/statement.rs | 41 ++++++++++++++++++++++++++++++++++------- src/transpiler/bend.rs | 4 ++++ 5 files changed, 56 insertions(+), 27 deletions(-) diff --git a/src/main.rs b/src/main.rs index 1c90287..39e6dd2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,7 +15,7 @@ pub mod scanner; pub mod transpiler; fn main() -> Result<()> { - let code = "1 * (2 + 3); 'aaaaa'; a + 1 + 2; b * ( a + 3);"; + let code = "var x = 1 * (2 + 3); 'aaaaa'; a + 1 + 2; b * ( a + 3);"; let file = SimpleFile::new("main", code); let tokens = scanner::Scanner::new(code.to_owned()).collect::>(); diff --git a/src/parser/lookup.rs b/src/parser/lookup.rs index c343ad5..8d9ff16 100644 --- a/src/parser/lookup.rs +++ b/src/parser/lookup.rs @@ -1,13 +1,11 @@ -use crate::scanner::lexeme::{Lexeme, TokenType, TokenValue}; -use core::panic; -use std::collections::HashMap; - use super::{ ast::{BinaryOperation, Expression, Statement}, macros::{expect_expression, expect_token}, - statement::parse_variable_declaration, - Diagnostic, Parser, + statement, Diagnostic, Parser, }; +use crate::scanner::lexeme::{Lexeme, TokenType, TokenValue}; +use core::panic; +use std::collections::HashMap; #[derive(Debug, PartialEq, PartialOrd)] pub enum BindingPower { @@ -70,8 +68,8 @@ impl Default for Lookup { TokenType::Plus, BindingPower::Additive, |parser, cursor, lhs, _binding| { - let (rhs, cursor) = - super::expression::parse(parser, cursor + 1, &BindingPower::Additive)?; + let (_, cursor) = expect_token!(parser, cursor, TokenType::Plus)?; + let (rhs, cursor) = expect_expression!(parser, cursor, &BindingPower::Additive)?; Ok(( Expression::Binary(Box::new(lhs), BinaryOperation::Plus, Box::new(rhs)), cursor, @@ -83,8 +81,8 @@ impl Default for Lookup { TokenType::Minus, BindingPower::Additive, |parser, cursor, lhs, _binding| { - let (rhs, cursor) = - super::expression::parse(parser, cursor + 1, &BindingPower::Additive)?; + let (_, cursor) = expect_token!(parser, cursor, TokenType::Minus)?; + let (rhs, cursor) = expect_expression!(parser, cursor, &BindingPower::Additive)?; Ok(( Expression::Binary(Box::new(lhs), BinaryOperation::Minus, Box::new(rhs)), cursor, @@ -97,8 +95,9 @@ impl Default for Lookup { TokenType::Star, BindingPower::Multiplicative, |parser, cursor, lhs, _binding| { + let (_, cursor) = expect_token!(parser, cursor, TokenType::Star)?; let (rhs, cursor) = - super::expression::parse(parser, cursor + 1, &BindingPower::Multiplicative)?; + expect_expression!(parser, cursor, &BindingPower::Multiplicative)?; Ok(( Expression::Binary(Box::new(lhs), BinaryOperation::Times, Box::new(rhs)), cursor, @@ -110,8 +109,9 @@ impl Default for Lookup { TokenType::Slash, BindingPower::Multiplicative, |parser, cursor, lhs, _binding| { + let (_, cursor) = expect_token!(parser, cursor, TokenType::Slash)?; let (rhs, cursor) = - super::expression::parse(parser, cursor + 1, &BindingPower::Multiplicative)?; + expect_expression!(parser, cursor, &BindingPower::Multiplicative)?; Ok(( Expression::Binary(Box::new(lhs), BinaryOperation::Divide, Box::new(rhs)), cursor, @@ -160,20 +160,16 @@ impl Default for Lookup { panic!("expect_token! should return a valid token and handle the error case"); }); - lookup.add_statement_handler(TokenType::Semicolon, |parser, cursor| { - let (expression, cursor) = expression::parse(parser, cursor, &BindingPower::Primary)?; - let (_, cursor) = expect_token!(parser, cursor, TokenType::Semicolon)?; - Ok((Statement::Expression(expression), cursor)) - }); - lookup.add_expression_handler(TokenType::ParenOpen, |parser, cursor| { let (_, cursor) = expect_token!(parser, cursor, TokenType::ParenOpen)?; - let (expression, cursor) = expression::parse(parser, cursor, &BindingPower::None)?; + let (expression, cursor) = expect_expression!(parser, cursor, &BindingPower::None)?; let (_, cursor) = expect_token!(parser, cursor, TokenType::ParenClose)?; Ok((Expression::Grouping(Box::new(expression)), cursor)) }); + lookup.add_statement_handler(TokenType::Var, statement::parse_declaration); + lookup } } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 5b28790..0695c60 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -62,6 +62,7 @@ impl Iterator for Parser { } Err(diagnostic) => { self.cursor += 1; + // TODO: Diagnostic::combine here? Some(Err(diagnostic)) } } @@ -82,6 +83,7 @@ impl Diagnostic { } } + #[allow(dead_code)] fn combine(diagnostics: Vec) -> Diagnostic { let min_range = diagnostics .iter() diff --git a/src/parser/statement.rs b/src/parser/statement.rs index e33244c..65ac662 100644 --- a/src/parser/statement.rs +++ b/src/parser/statement.rs @@ -1,4 +1,6 @@ -use crate::scanner::lexeme::{Lexeme, Range, TokenType}; +use core::panic; + +use crate::scanner::lexeme::{Lexeme, Range, TokenType, TokenValue}; use super::{ expression, lookup::BindingPower, macros::expect_token, Diagnostic, Parser, Statement, @@ -19,14 +21,39 @@ pub fn parse(parser: &Parser, cursor: usize) -> Result<(Statement, usize), Diagn let lexeme = lexeme.unwrap(); - if let Lexeme::Invalid(_) = lexeme { - return Err(Diagnostic::error(lexeme.range(), "Invalid token")); - } + let token = match lexeme { + Lexeme::Valid(token) => token, + Lexeme::Invalid(_) => return Err(Diagnostic::error(lexeme.range(), "Invalid token")), + }; - let (expression, new_cursor) = expression::parse(parser, cursor, &BindingPower::None)?; + let statement_handler = parser.lookup.statement_lookup.get(&token.token_type); - // Expect a semicolon - let (_, cursor) = expect_token!(parser, new_cursor, TokenType::Semicolon)?; + match statement_handler { + Some(statement_handler) => statement_handler(parser, cursor), + None => parse_expression(parser, cursor), + } +} + +pub fn parse_expression(parser: &Parser, cursor: usize) -> Result<(Statement, usize), Diagnostic> { + let (expression, cursor) = expression::parse(parser, cursor, &BindingPower::None)?; + let (_, cursor) = expect_token!(parser, cursor, TokenType::Semicolon)?; Ok((Statement::Expression(expression), cursor)) } + +pub fn parse_declaration(parser: &Parser, cursor: usize) -> Result<(Statement, usize), Diagnostic> { + let (_, cursor) = expect_token!(parser, cursor, TokenType::Var)?; + let (identifier, cursor) = expect_token!(parser, cursor, TokenType::Identifier)?; + let identifier = match &identifier.value { + TokenValue::Identifier(identifier) => identifier, + _ => panic!("expect_token! should return a valid token and handle the error case"), + }; + let (_, cursor) = expect_token!(parser, cursor, TokenType::Equal)?; + let (expression, cursor) = expression::parse(parser, cursor, &BindingPower::None)?; + let (_, cursor) = expect_token!(parser, cursor, TokenType::Semicolon)?; + + Ok(( + Statement::Declaration(identifier.clone(), expression), + cursor, + )) +} diff --git a/src/transpiler/bend.rs b/src/transpiler/bend.rs index 7b940f8..5be729a 100644 --- a/src/transpiler/bend.rs +++ b/src/transpiler/bend.rs @@ -62,5 +62,9 @@ fn transpile_statement(statement: &Statement) -> String { let expression = transpile_expression(expression); format!("{};\n", expression) } + Statement::Declaration(identifier, expression) => { + let expression = transpile_expression(expression); + format!("let {} = {};\n", identifier, expression) + } } }