continued building out parser, connected parser to main

This commit is contained in:
Tristan Smith 2024-09-21 00:19:56 -04:00
parent 94ac0863bc
commit 513dddce85
6 changed files with 169 additions and 77 deletions

View file

@ -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. - [ ] Add support for more complex syntax and features.
- **Parser**: - **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**: - **Compiler**:
- [ ] Currently a placeholder. Implement the compiler to compile parsed code. - [ ] Currently a placeholder. Implement the compiler to compile parsed code.

View file

@ -1,5 +1,7 @@
use crate::lexer::token::Token; use crate::lexer::token::Token;
#[allow(dead_code)]
pub struct Lexer { pub struct Lexer {
source: Vec<char>, source: Vec<char>,
start: usize, start: usize,

View file

@ -6,20 +6,22 @@ use std::env;
use std::fs; use std::fs;
use std::io::{self, Write}; use std::io::{self, Write};
use lexer::Lexer; // use lexer::Lexer;
use fddl::lexer::Lexer;
use fddl::parser::Parser;
fn main() { fn main() {
let args: Vec<String> = env::args().collect(); let args: Vec<String> = env::args().collect();
// runs file or REPL
if args.len() > 1 { if args.len() > 1 {
// If a file is provided, run it
run_file(&args[1]); run_file(&args[1]);
} else { } else {
// Otherwise start the REPL
run_repl(); run_repl();
} }
} }
// basic REPL
fn run_repl() { fn run_repl() {
println!("fddl REPL"); println!("fddl REPL");
loop { loop {
@ -36,11 +38,14 @@ fn run_repl() {
run(buffer.clone()); run(buffer.clone());
} }
} }
// runs file
fn run_file(path: &str) { fn run_file(path: &str) {
let source = fs::read_to_string(path).expect("Failed to read source file"); let source = fs::read_to_string(path).expect("Failed to read source file");
run(source); run(source);
} }
// runs source code
fn run(source: String) { fn run(source: String) {
let mut lexer = Lexer::new(source); let mut lexer = Lexer::new(source);
let tokens = lexer.scan_tokens(); let tokens = lexer.scan_tokens();

View file

@ -1,3 +1,5 @@
#[allow(dead_code)]
pub enum Expression { pub enum Expression {
Literal(Literal), Literal(Literal),
Variable(String), Variable(String),

View file

@ -1,3 +1,5 @@
// pub mod ast; pub mod ast;
pub mod parser;
// pub use ast::*; // pub use ast::*;
pub use parser::*;

View file

@ -1,10 +1,15 @@
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 { pub struct Parser {
tokens: Vec<Token>, tokens: Vec<Token>,
current: usize, current: usize,
} }
#[allow(dead_code)]
impl Parser { impl Parser {
fn parse_statement(&mut self) -> Option<Statement> { fn parse_statement(&mut self) -> Option<Statement> {
if self.match_token(Token::Print) { if self.match_token(Token::Print) {
@ -23,14 +28,89 @@ impl Parser {
} }
fn parse_print_statement(&mut self) -> Option<Statement> { fn parse_print_statement(&mut self) -> Option<Statement> {
let value = self.parse.expression(); let value = self.parse_expression()?;
if self.match_token(Token::Semicolon) { if self.match_token(Token::Semicolon) {
Some(Statement::PrintStatement(value?)) Some(Statement::PrintStatement(value))
} else { } else {
None None
} }
} }
fn parse_variable_declaration(&mut self) -> Option<Statement> {
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<Statement> {
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<Statement> {
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<Statement> {
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<Statement> {
let expr = self.parse_expression()?;
if self.match_token(Token::Semicolon) {
Some(Statement::ExpressionStatement(expr))
} else {
None
}
}
fn parse_expression(&mut self) -> Option<Expression> {
// Placeholder for expression parsing logic
None
}
pub fn new(tokens: Vec<Token>) -> Self { pub fn new(tokens: Vec<Token>) -> Self {
Parser { Parser {
tokens, tokens,