diff --git a/src/codegen/function_declaration.rs b/src/codegen/function_declaration.rs index 835fdc5..c18905f 100644 --- a/src/codegen/function_declaration.rs +++ b/src/codegen/function_declaration.rs @@ -17,7 +17,10 @@ mod tests { use super::*; use crate::{ lexic::get_tokens, - syntax::{ast::ModuleMembers, build_ast}, + syntax::{ + ast::{ModuleMembers, Statement}, + build_ast, + }, }; #[test] @@ -28,13 +31,12 @@ mod tests { let fun_dec = result.productions.get(0).unwrap(); match fun_dec { - ModuleMembers::Binding(_) => panic!("Expected function declaration"), - ModuleMembers::FunctionDeclaration(fun_decl) => { + ModuleMembers::Stmt(Statement::FnDecl(fun_decl)) => { let transpiled = fun_decl.transpile(); assert_eq!("function id() {\n\n}", transpiled); } - _ => panic!("Not implemented: Expression at top level"), + _ => panic!("Expected a function declaration"), } } } diff --git a/src/codegen/module_ast.rs b/src/codegen/module_ast.rs index 0b14565..3aafd9d 100644 --- a/src/codegen/module_ast.rs +++ b/src/codegen/module_ast.rs @@ -20,7 +20,7 @@ mod tests { use super::*; use crate::{ lexic::token::{Token, TokenType}, - syntax::ast::{var_binding::VariableBinding, Expression, ModuleMembers}, + syntax::ast::{var_binding::VariableBinding, Expression, ModuleMembers, Statement}, }; #[test] @@ -40,7 +40,7 @@ mod tests { }; let module = ModuleAST { - productions: vec![ModuleMembers::Binding(binding)], + productions: vec![ModuleMembers::Stmt(Statement::Binding(binding))], }; let result = module.transpile(); diff --git a/src/codegen/statement.rs b/src/codegen/statement.rs index 6daa8b9..f169a5f 100644 --- a/src/codegen/statement.rs +++ b/src/codegen/statement.rs @@ -6,7 +6,7 @@ impl Transpilable for Statement<'_> { fn transpile(&self) -> String { let stmt = match self { Statement::FnDecl(f) => f.transpile(), - Statement::VarBinding(b) => b.transpile(), + Statement::Binding(b) => b.transpile(), }; format!("{stmt};") diff --git a/src/codegen/top_level_construct.rs b/src/codegen/top_level_construct.rs index dac3b52..6b44fbb 100644 --- a/src/codegen/top_level_construct.rs +++ b/src/codegen/top_level_construct.rs @@ -1,13 +1,13 @@ -use crate::syntax::ast::ModuleMembers; +use crate::syntax::ast::{ModuleMembers, Statement}; use super::Transpilable; impl Transpilable for ModuleMembers<'_> { fn transpile(&self) -> String { match self { - ModuleMembers::Binding(binding) => binding.transpile(), - ModuleMembers::FunctionDeclaration(fun) => fun.transpile(), - _ => panic!("Not implemented: Expression at top level"), + ModuleMembers::Stmt(Statement::Binding(b)) => b.transpile(), + ModuleMembers::Stmt(Statement::FnDecl(f)) => f.transpile(), + _ => todo!("Not implemented: Transpilable for Expression"), } } } diff --git a/src/semantic/checks/function_declaration.rs b/src/semantic/checks/function_declaration.rs index 605c2bb..ad22ba5 100644 --- a/src/semantic/checks/function_declaration.rs +++ b/src/semantic/checks/function_declaration.rs @@ -40,7 +40,9 @@ impl SemanticCheck for FunctionDeclaration<'_> { return Err(err); } } - Statement::FunctionCall(_) => panic!("FunctionCall semantic check not implemented"), + Statement::FnDecl(_) => { + todo!("Function declaration: semantic check not implemented") + } } } diff --git a/src/semantic/checks/top_level_declaration.rs b/src/semantic/checks/top_level_declaration.rs index 39e13ae..e878b0a 100644 --- a/src/semantic/checks/top_level_declaration.rs +++ b/src/semantic/checks/top_level_declaration.rs @@ -1,4 +1,8 @@ -use crate::{semantic::impls::SemanticCheck, syntax::ast::ModuleMembers}; +use crate::{ + error_handling::MistiError, + semantic::{impls::SemanticCheck, symbol_table::SymbolTable}, + syntax::ast::{Expression, ModuleMembers, Statement}, +}; impl SemanticCheck for ModuleMembers<'_> { fn check_semantics( @@ -6,9 +10,25 @@ impl SemanticCheck for ModuleMembers<'_> { scope: &crate::semantic::symbol_table::SymbolTable, ) -> Result<(), crate::error_handling::MistiError> { match self { - ModuleMembers::Binding(binding) => binding.check_semantics(scope), - ModuleMembers::FunctionDeclaration(function) => function.check_semantics(scope), - _ => panic!("Not implemented"), + ModuleMembers::Stmt(statement) => statement.check_semantics(scope), + ModuleMembers::Expr(expression) => expression.check_semantics(scope), } } } + +// TODO: Move to its own file +impl SemanticCheck for Statement<'_> { + fn check_semantics(&self, scope: &SymbolTable) -> Result<(), MistiError> { + match self { + Statement::Binding(b) => b.check_semantics(scope), + Statement::FnDecl(f) => f.check_semantics(scope), + } + } +} + +// TODO: Move to its own file +impl SemanticCheck for Expression<'_> { + fn check_semantics(&self, scope: &SymbolTable) -> Result<(), MistiError> { + todo!("Check semantics for expression") + } +} diff --git a/src/syntax/ast/mod.rs b/src/syntax/ast/mod.rs index db3cb23..121b5b0 100644 --- a/src/syntax/ast/mod.rs +++ b/src/syntax/ast/mod.rs @@ -23,7 +23,7 @@ pub enum ModuleMembers<'a> { #[derive(Debug)] pub enum Statement<'a> { - VarBinding(VariableBinding<'a>), + Binding(VariableBinding<'a>), FnDecl(FunctionDeclaration<'a>), } diff --git a/src/syntax/block.rs b/src/syntax/block.rs index 7691378..0f2de9e 100644 --- a/src/syntax/block.rs +++ b/src/syntax/block.rs @@ -72,6 +72,8 @@ mod tests { use super::*; use crate::lexic::get_tokens; + // TODO: rewrite, refactor + /* #[test] fn test_parse_block() { let tokens = get_tokens(&String::from("{f()}")).unwrap(); @@ -112,4 +114,5 @@ mod tests { assert_eq!(block.statements.len(), 1); } + */ } diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index 266b535..0a54f49 100755 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -1,4 +1,4 @@ -use crate::error_handling::{MistiError, SyntaxError}; +use crate::error_handling::MistiError; mod binding; mod block; @@ -11,97 +11,48 @@ mod utils; pub mod ast; -use crate::lexic::token::{Token, TokenType}; +use crate::lexic::token::Token; use ast::ModuleAST; -use self::ast::ModuleMembers; -use self::parseable::{ParsingError, ParsingResult}; +use self::parseable::{Parseable, ParsingError, ParsingResult}; -/// Constructs the Misti AST from a vector of tokens +/// Builds the Misti AST from a vector of tokens pub fn build_ast<'a>(tokens: &'a Vec) -> Result { - let mut top_level_declarations = Vec::new(); - let token_amount = tokens.len(); - let mut current_pos = 0; - - // Minus one because the last token is always EOF - while current_pos < token_amount - 1 { - // Ignore newlines - if tokens[current_pos].token_type == TokenType::NewLine { - current_pos += 1; - continue; - } - - match next_construct(tokens, current_pos) { - Ok((module, next_pos)) => { - top_level_declarations.push(module); - current_pos = next_pos; - } - Err(ParsingError::Err(err)) => return Err(MistiError::Syntax(err)), - _ => { - return Err(MistiError::Syntax(SyntaxError { - reason: String::from("PARSER couldn't parse any construction"), - // FIXME: This should get the position of the _token_ that current_pos points to - error_start: current_pos, - error_end: current_pos, - })); - } + match ModuleAST::try_parse(tokens, 0) { + Ok((module, _)) => Ok(module), + Err(ParsingError::Err(error)) => Err(MistiError::Syntax(error)), + _ => { + // This shouldn't happen. The module parser returns an error if it finds nothing to parse. + unreachable!("Illegal state during parsing: The Module parse should always return a result or error") } } - - Ok(ModuleAST { - productions: top_level_declarations, - }) -} - -fn next_construct<'a>(tokens: &'a Vec, current_pos: usize) -> ParsingResult { - todo!(); - // Try to parse a function declaration - match functions::function_declaration::try_parse(tokens, current_pos) { - Ok((declaration, next_pos)) => { - return Ok((ModuleMembers::Stmt(FnDecl(declaration), next_pos))) - } - Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)), - _ => {} - } - - // Try to parse a binding - match binding::try_parse(tokens, current_pos) { - Ok((binding, next_pos)) => return Ok((ModuleMembers::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((ModuleMembers::Expr(expression), next_pos)), - Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)), - _ => {} - } - - // No top level construct was found, return unmatched - Err(ParsingError::Unmatched) } #[cfg(test)] mod tests { use super::*; + use crate::lexic::get_tokens; + use ast::ModuleMembers; + use tests::ast::Statement; + // TODO: Reenable when statement parsing is rewritten + /* #[test] fn should_parse_top_level_construct_with_trailing_newline() { let input = String::from(" fun f1(){}\n"); - let tokens = crate::lexic::get_tokens(&input).unwrap(); - let declarations = build_ast(&tokens).unwrap().productions; + let tokens = get_tokens(&input).unwrap(); + let productions = build_ast(&tokens).unwrap().productions; - assert_eq!(declarations.len(), 1); + assert_eq!(productions.len(), 1); - match declarations.get(0).unwrap() { - ModuleMembers::Binding(_) => panic!("Expected a function declaration"), - ModuleMembers::FunctionDeclaration(_f) => { + match productions.get(0).unwrap() { + ModuleMembers::Stmt(Statement::FnDecl(_f)) => { assert!(true) } - _ => panic!("Not implemented: Expression at top level"), + _ => panic!("Expected a function declaration"), } } + */ #[test] fn should_parse_2_top_level_construct() { @@ -112,19 +63,17 @@ mod tests { assert_eq!(declarations.len(), 2); match declarations.get(0).unwrap() { - ModuleMembers::Binding(_) => panic!("Expected a function declaration"), - ModuleMembers::FunctionDeclaration(_f) => { + ModuleMembers::Stmt(Statement::FnDecl(_f)) => { assert!(true) } - _ => panic!("Not implemented: Expression at top level"), + _ => panic!("Expected a function declaration as first production"), } match declarations.get(1).unwrap() { - ModuleMembers::Binding(_) => panic!("Expected a function declaration"), - ModuleMembers::FunctionDeclaration(_f) => { + ModuleMembers::Stmt(Statement::FnDecl(_f)) => { assert!(true) } - _ => panic!("Not implemented: Expression at top level"), + _ => panic!("Expected a function declaration as first production"), } } } diff --git a/src/syntax/parsers/module.rs b/src/syntax/parsers/module.rs index 79adf30..d6c1570 100644 --- a/src/syntax/parsers/module.rs +++ b/src/syntax/parsers/module.rs @@ -39,7 +39,6 @@ impl<'a> Parseable<'a> for ModuleAST<'a> { }; // Attempt to parse an expression - // If this fails the whole thing fails match Expression::try_parse(tokens, current_pos) { Ok((prod, next_pos)) => { productions.push(ModuleMembers::Expr(prod)); @@ -53,7 +52,7 @@ impl<'a> Parseable<'a> for ModuleAST<'a> { } // If we reached this point we didn't match any productions and fail - let t = tokens[current_pos]; + let t = &tokens[current_pos]; return Err(ParsingError::Err(SyntaxError { error_start: t.position, diff --git a/src/syntax/parsers/statement.rs b/src/syntax/parsers/statement.rs index 95aa624..00d5c9c 100644 --- a/src/syntax/parsers/statement.rs +++ b/src/syntax/parsers/statement.rs @@ -1,4 +1,6 @@ -use crate::syntax::{ast::Statement, parseable::Parseable}; +use crate::syntax::{ + ast::Statement, binding, functions::function_declaration, parseable::Parseable, +}; impl<'a> Parseable<'a> for Statement<'a> { type Item = Statement<'a>; @@ -7,6 +9,29 @@ impl<'a> Parseable<'a> for Statement<'a> { tokens: &'a Vec, current_pos: usize, ) -> crate::syntax::parseable::ParsingResult<'a, Self::Item> { - todo!() + // Try to parse a variable binding + // TODO: Rewrite function_declaration to use Parseable + match binding::try_parse(tokens, current_pos) { + Ok((prod, next)) => { + return Ok((Statement::Binding(prod), next)); + } + Err(_) => { + // TODO + } + } + + // Try to parse a function declaration + // TODO: Rewrite function_declaration to use Parseable + match function_declaration::try_parse(tokens, current_pos) { + Ok((prod, next)) => { + return Ok((Statement::FnDecl(prod), next)); + } + Err(_) => { + // TODO + } + } + + // Here nothing was parsed. Should fail + todo!("Nothing was parsed. Should fail") } } diff --git a/src/syntax/statement.rs b/src/syntax/statement.rs index 56e6836..0b0ecd8 100644 --- a/src/syntax/statement.rs +++ b/src/syntax/statement.rs @@ -1,11 +1,6 @@ use crate::lexic::token::Token; -use super::{ - ast::{Expression, Statement}, - binding, - expression::function_call_expr, - ParsingError, ParsingResult, -}; +use super::{ast::Statement, binding, ParsingError, ParsingResult}; pub fn try_parse<'a>(tokens: &'a Vec, pos: usize) -> ParsingResult { // Try to parse a binding @@ -15,12 +10,15 @@ pub fn try_parse<'a>(tokens: &'a Vec, pos: usize) -> ParsingResult {} } + // A function call is an expression, not a statement. Remove // Try to parse a function call + /* match function_call_expr::try_parse(tokens, pos) { Ok((Expression::FunctionCall(f), next)) => return Ok((Statement::FunctionCall(f), next)), Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)), _ => {} }; + */ // Return unmatched Err(ParsingError::Unmatched) @@ -30,23 +28,6 @@ pub fn try_parse<'a>(tokens: &'a Vec, pos: usize) -> ParsingResult s, - _ => panic!("Expected a statement"), - }; - - match statement { - Statement::FunctionCall(_) => assert!(true), - _ => panic!("Expected a function call"), - } - } - #[test] fn should_parse_binding() { let input = String::from("val identifier = 20");