mirror of
https://git.fddl.dev/fddl/fddl.git
synced 2024-12-25 21:50:31 +00:00
continued building out parser, connected parser to main
This commit is contained in:
parent
94ac0863bc
commit
513dddce85
6 changed files with 169 additions and 77 deletions
|
@ -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.
|
||||||
|
|
|
@ -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,
|
||||||
|
|
11
src/main.rs
11
src/main.rs
|
@ -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();
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#[allow(dead_code)]
|
||||||
|
|
||||||
pub enum Expression {
|
pub enum Expression {
|
||||||
Literal(Literal),
|
Literal(Literal),
|
||||||
Variable(String),
|
Variable(String),
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
// pub mod ast;
|
pub mod ast;
|
||||||
|
pub mod parser;
|
||||||
|
|
||||||
// pub use ast::*;
|
// pub use ast::*;
|
||||||
|
pub use parser::*;
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in a new issue