diff --git a/readme.md b/readme.md index 0d9646a..e4c1ec3 100644 --- a/readme.md +++ b/readme.md @@ -83,7 +83,8 @@ fddl is very much a work in progress, with lots of planned improvements and addi - [ ] Add support for more complex syntax and features. - **Parser**: - - [ ] Currently a placeholder. Implement parsing for function calls, expressions, etc. + - [ ] Working on building out functions to parse simple functionality in the language (if, while, for), and to read their expressions and values + - [ ] Implement parsing for function calls, expressions, checks, literally everything. - **Compiler**: - [ ] Currently a placeholder. Implement the compiler to compile parsed code. diff --git a/src/lexer/lexer.rs b/src/lexer/lexer.rs index 656968b..978a555 100644 --- a/src/lexer/lexer.rs +++ b/src/lexer/lexer.rs @@ -1,5 +1,7 @@ use crate::lexer::token::Token; +#[allow(dead_code)] + pub struct Lexer { source: Vec, start: usize, diff --git a/src/main.rs b/src/main.rs index 6337449..5fd0a80 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,20 +6,22 @@ use std::env; use std::fs; use std::io::{self, Write}; -use lexer::Lexer; +// use lexer::Lexer; +use fddl::lexer::Lexer; +use fddl::parser::Parser; fn main() { let args: Vec = env::args().collect(); + // runs file or REPL if args.len() > 1 { - // If a file is provided, run it run_file(&args[1]); } else { - // Otherwise start the REPL run_repl(); } } +// basic REPL fn run_repl() { println!("fddl REPL"); loop { @@ -36,11 +38,14 @@ fn run_repl() { run(buffer.clone()); } } + +// runs file fn run_file(path: &str) { let source = fs::read_to_string(path).expect("Failed to read source file"); run(source); } +// runs source code fn run(source: String) { let mut lexer = Lexer::new(source); let tokens = lexer.scan_tokens(); diff --git a/src/parser/ast.rs b/src/parser/ast.rs index c3c7eb1..21463ec 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -1,3 +1,5 @@ +#[allow(dead_code)] + pub enum Expression { Literal(Literal), Variable(String), diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 638d966..e59ec76 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1,3 +1,5 @@ -// pub mod ast; +pub mod ast; +pub mod parser; // pub use ast::*; +pub use parser::*; \ No newline at end of file diff --git a/src/parser/parser.rs b/src/parser/parser.rs index fe33702..cfe6737 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -1,84 +1,164 @@ -use crate::lexer::token::Token; + use crate::lexer::token::Token; + use crate::parser::ast::Expression; + use crate::parser::ast::Statement; + use crate::lexer::Lexer; -pub struct Parser { - tokens: Vec, - current: usize, -} - -impl Parser { - fn parse_statement(&mut self) -> Option { - if self.match_token(Token::Print) { - self.parse_print_statement() - } else if self.match_token(Token::Let) { - self.parse_variable_declaration() - } else if self.match_token(Token::If) { - self.parse_if_statement() - } else if self.match_token(Token::While) { - self.parse_while_statement() - } else if self.match_token(Token::For) { - self.parse_for_statement() - } else { - self.parse_expression_statement() - } + pub struct Parser { + tokens: Vec, + current: usize, } - fn parse_print_statement(&mut self) -> Option { - let value = self.parse.expression(); - if self.match_token(Token::Semicolon) { - Some(Statement::PrintStatement(value?)) - } else { + #[allow(dead_code)] + + impl Parser { + fn parse_statement(&mut self) -> Option { + if self.match_token(Token::Print) { + self.parse_print_statement() + } else if self.match_token(Token::Let) { + self.parse_variable_declaration() + } else if self.match_token(Token::If) { + self.parse_if_statement() + } else if self.match_token(Token::While) { + self.parse_while_statement() + } else if self.match_token(Token::For) { + self.parse_for_statement() + } else { + self.parse_expression_statement() + } + } + + fn parse_print_statement(&mut self) -> Option { + let value = self.parse_expression()?; + if self.match_token(Token::Semicolon) { + Some(Statement::PrintStatement(value)) + } else { + None + } + } + + fn parse_variable_declaration(&mut self) -> Option { + let token = self.advance().clone(); + + if let Token::Identifier(name) = token { + let has_initializer = self.match_token(Token::Equal); + + let initializer = if has_initializer { + self.parse_expression() + } else { + None + }; + + if self.match_token(Token::Semicolon) { + Some(Statement::VariableDeclaration(name, initializer)) + } else { + None + } + } else { + None + } + } + + fn parse_if_statement(&mut self) -> Option { + self.match_token(Token::LeftParen); + let condition = self.parse_expression()?; + self.match_token(Token::RightParen); + + let then_branch = Box::new(self.parse_statement()?); + let else_branch = if self.match_token(Token::Else) { + Some(Box::new(self.parse_statement()?)) + } else { + None + }; + + Some(Statement::IfStatement(condition, then_branch, else_branch)) + } + + fn parse_while_statement(&mut self) -> Option { + self.match_token(Token::LeftParen); + let condition = self.parse_expression()?; + self.match_token(Token::RightParen); + + let body = Box::new(self.parse_statement()?); + + Some(Statement::WhileStatement(condition, body)) + } + + fn parse_for_statement(&mut self) -> Option { + self.match_token(Token::LeftParen); + + let initializer = Box::new(self.parse_statement()?); + let condition = self.parse_expression()?; + self.match_token(Token::Semicolon); + let increment = Box::new(self.parse_statement()?); + + self.match_token(Token::RightParen); + let body = Box::new(self.parse_statement()?); + + Some(Statement::ForStatement(initializer, condition, increment, body)) + } + + fn parse_expression_statement(&mut self) -> Option { + let expr = self.parse_expression()?; + if self.match_token(Token::Semicolon) { + Some(Statement::ExpressionStatement(expr)) + } else { + None + } + } + + fn parse_expression(&mut self) -> Option { + // Placeholder for expression parsing logic None } - } - pub fn new(tokens: Vec) -> Self { - Parser { - tokens, - current: 0, + pub fn new(tokens: Vec) -> Self { + Parser { + tokens, + current: 0, + } + } + + fn current_token(&self) -> &Token { + &self.tokens[self.current] + } + + fn peek(&self) -> &Token { + &self.tokens[self.current + 1] + } + + fn is_at_end(&self) -> bool { + matches!(self.current_token(), Token::EOF) + } + + fn advance(&mut self) -> &Token { + if !self.is_at_end() { + self.current += 1; + } + self.current_token() + } + + fn match_token(&mut self, expected: Token) -> bool { + if self.current_token() == &expected { + self.advance(); + true + } else { + false + } + } + + fn previous_token(&self) -> &Token { + &self.tokens[self.current - 1] } } - fn current_token(&self) -> &Token { - &self.tokens[self.current] - } + fn main() { + let source = String::from("let x = 10;"); + let mut lexer = Lexer::new(source); + let tokens = lexer.scan_tokens(); + let mut parser = Parser::new(tokens); - fn peek(&self) -> &Token { - &self.tokens[self.current + 1] - } - - fn is_at_end(&self) -> bool { - matches!(self.current_token(), Token::EOF) - } - - fn advance(&mut self) -> &Token { - if !self.is_at_end() { - self.current += 1; - } - self.current_token() - } - - fn match_token(&mut self, expected: Token) -> bool { - if self.current_token() == &expected { - self.advance(); - true - } else { - false + while !parser.is_at_end() { + println!("{:?}", parser.current_token()); + parser.advance(); } } - - fn previous_token(&self) -> &Token { - &self.tokens[self.current - 1] - } -} - -fn main() { - let source = String::from("let x = 10;"); - let mut lexer = Lexer::new(source); - let tokens = lexer.scan_tokens(); - let mut parser = Parser::new(tokens); - - while !parser.is_at_end() { - println!("{:?}", parser.current_token()); - parser.advance(); - } -} \ No newline at end of file