This commit is contained in:
Tristan 2025-05-26 13:05:38 -04:00
parent 9f594e3775
commit 558cbbc0d2
5 changed files with 231 additions and 184 deletions

5
.kdev4/fddl.kdev4 Normal file
View File

@ -0,0 +1,5 @@
[Buildset]
BuildItems=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00\x00\x08\x00f\x00d\x00d\x00l)
[Project]
VersionControlSupport=kdevgit

4
fddl.kdev4 Normal file
View File

@ -0,0 +1,4 @@
[Project]
CreatedFrom=
Manager=KDevGenericManager
Name=fddl

View File

@ -60,18 +60,29 @@ impl Lexer {
} else {
Some(Token::Tilde)
}
},
},
'/' => {
if self.match_char('/') {
// Line comment starting with //
self.line_comment() // Generate Comment token
if self.match_char('/') { // For line comments //
// Consume the rest of the line
let mut comment_text = String::new();
while self.peek() != '\n' && !self.is_at_end() {
comment_text.push(self.advance());
}
Some(Token::Comment(comment_text)) // Or None if you want to skip comments
} else if self.match_char('*') { // For block comments /* ... */
self.consume_block_comment() // Call a new helper function
} else {
Some(Token::Slash)
Some(Token::Slash) // Division operator
}
},
'#' => {
// Line comment starting with #
self.line_comment() // Generate Comment token
let mut comment_text = String::new();
while self.peek() != '\n' && !self.is_at_end() {
comment_text.push(self.advance());
}
Some(Token::Comment(comment_text))
},
// One or two character tokens
@ -124,8 +135,34 @@ impl Lexer {
}
}
// Helper methods
// Consume the current character and return it
fn consume_block_comment(&mut self) -> Option<Token> {
let mut comment_text = String::new();
let start_line = self.line;
loop {
if self.is_at_end() {
eprintln!("Error (L{}): Unterminated block comment", start_line);
if !comment_text.is_empty() {
return Some(Token::Comment(comment_text));
}
return None;
}
let current_char = self.peek();
if current_char == '*' && self.peek_next() == '/' {
self.advance(); // Consume '*'
self.advance(); // Consume '/'
return Some(Token::Comment(comment_text));
} else {
if current_char == '\n' {
self.line += 1;
}
comment_text.push(self.advance());
}
}
}
fn advance(&mut self) -> char {
if self.is_at_end() {
return '\0';
@ -135,7 +172,6 @@ impl Lexer {
c
}
// Check if the current character matches the expected character
fn match_char(&mut self, expected: char) -> bool {
if self.is_at_end() {
return false;
@ -149,7 +185,6 @@ impl Lexer {
true
}
// Look at current character
fn peek(&self) -> char {
if self.is_at_end() {
'\0'
@ -158,7 +193,6 @@ impl Lexer {
}
}
// Look ahead by one character
fn peek_next(&self) -> char {
if self.current + 1 >= self.source.len() {
'\0'
@ -167,12 +201,10 @@ impl Lexer {
}
}
// Check if we have reached the end of the source
fn is_at_end(&self) -> bool {
self.current >= self.source.len()
}
// Function to handle string literals
fn string(&mut self) -> Option<Token> {
while self.peek() != '"' && !self.is_at_end() {
if self.peek() == '\n' {

View File

@ -17,7 +17,7 @@ impl Parser {
}
}
fn parse_for_statement(&mut self) -> Option<Statement> {
/* fn parse_for_statement(&mut self) -> Option<Statement> {
if !self.match_token(Token::LeftParen) {
eprintln!("Error: Expected '(' after 'for'.");
return None;
@ -59,7 +59,7 @@ impl Parser {
eprintln!("Warning: For statement AST structure might need review.");
None
}
} */
fn parse_expression_statement(&mut self) -> Option<Statement> {
let expr = self.parse_expression()?;
@ -309,7 +309,14 @@ impl Parser {
}
pub fn parse_statement(&mut self) -> Option<Statement> {
if self.check(&Token::Print) {
self.skip_comments();
if self.is_at_end() { return None; }
if self.check(&Token::For) {
self.parse_for_statement()
} else if self.check(&Token::Func) {
self.parse_function_declaration()
} else if self.check(&Token::Print) {
self.parse_print_statement()
} else if self.check(&Token::Let) {
self.parse_variable_declaration()
@ -319,13 +326,82 @@ impl Parser {
self.parse_if_statement()
} else if self.check(&Token::While) {
self.parse_while_statement()
} else if self.check(&Token::For) {
self.parse_for_statement()
} else {
self.parse_expression_statement()
}
}
fn parse_function_declaration(&mut self) -> Option<Statement> {
if !self.match_token(Token::Func) {
eprintln!("Internal parser error: Expected 'func' token in parse_function_declaration.");
return None;
}
let name = match self.peek_and_advance() {
Some(Token::Identifier(name_str)) => name_str,
_ => {
eprintln!("Error: Expected function name (identifier) after 'func'.");
return None;
}
};
if !self.match_token(Token::LeftParen) {
eprintln!("Error: Expected '(' after function name '{}'.", name);
return None;
}
let params = self.parse_parameters()?;
if !self.match_token(Token::RightParen) {
eprintln!("Error: Expected ')' after function parameters for function '{}'.", name);
return None;
}
if !self.check(&Token::LeftBrace) {
eprintln!("Error: Expected '{{' for function body of '{}'.", name);
return None;
}
let body_statement = self.parse_statement()?;
match body_statement {
Statement::Block(body_statements) => {
Some(Statement::FunctionDeclaration { name, params, body: body_statements })
}
_ => {
eprintln!("Error: Function body must be a block statement for function '{}'.", name);
None
}
}
}
fn parse_parameters(&mut self) -> Option<Vec<String>> {
let mut parameters = Vec::new();
if self.check(&Token::RightParen) {
return Some(parameters);
}
match self.peek_and_advance() {
Some(Token::Identifier(param_name)) => parameters.push(param_name),
_ => {
eprintln!("Error: Expected parameter name (identifier) in function parameter list.");
return None;
}
}
while self.match_token(Token::Comma) {
match self.peek_and_advance() {
Some(Token::Identifier(param_name)) => parameters.push(param_name),
_ => {
eprintln!("Error: Expected parameter name (identifier) after comma in function parameter list.");
return None;
}
}
}
Some(parameters)
}
fn parse_block_statement(&mut self) -> Option<Statement> {
if !self.match_token(Token::LeftBrace) {
eprintln!("Error: Expected '{{' to start a block.");
@ -388,7 +464,7 @@ impl Parser {
Some(Statement::IfStatement(condition, then_branch, else_branch_opt))
}
fn parse_while_statement(&mut self) -> Option<Statement> {
fn parse_while_statement(&mut self) -> Option<Statement> {
if !self.match_token(Token::While) {
eprintln!("Internal parser error: Expected 'while' token in parse_while_statement.");
return None;
@ -413,6 +489,94 @@ impl Parser {
Some(Statement::WhileStatement(condition, body))
}
fn parse_for_statement(&mut self) -> Option<Statement> {
if !self.match_token(Token::For) { return None; } // Consume 'for'
if !self.match_token(Token::LeftParen) {
eprintln!("Error: Expected '(' after 'for'.");
return None;
}
// 1. Initializer Statement
self.skip_comments(); // Skip comments before initializer part
let initializer: Box<Statement>;
if self.check(&Token::Let) {
self.advance(); // Consume 'let'
let var_name = match self.peek_and_advance() {
Some(Token::Identifier(name_str)) => name_str,
_ => {
eprintln!("Error: Expected variable name after 'let' in for-loop initializer.");
return None;
}
};
let var_initializer_expr: Option<Expression> = if self.match_token(Token::Equal) {
self.skip_comments(); // Skip comments before the expression value
self.parse_expression()
} else {
None
};
initializer = Box::new(Statement::VariableDeclaration(var_name, var_initializer_expr));
self.skip_comments(); // Skip comments before the semicolon separator
if !self.match_token(Token::Semicolon) {
eprintln!("Error: Expected ';' after 'let' declaration in for-loop initializer.");
return None;
}
} else if self.check(&Token::Semicolon) { // Check for ';' for empty initializer
self.advance(); // Consume the ';'
initializer = Box::new(Statement::ExpressionStatement(Expression::Literal(Literal::Nil)));
} else { // Expression initializer
let init_expr = self.parse_expression()?;
initializer = Box::new(Statement::ExpressionStatement(init_expr));
self.skip_comments(); // Skip comments before the semicolon separator
if !self.match_token(Token::Semicolon) {
eprintln!("Error: Expected ';' after for-loop initializer expression.");
return None;
}
}
// 2. Condition Expression
self.skip_comments(); // Skip comments before condition part
let condition: Expression;
if self.check(&Token::Semicolon) { // Check for ';' for empty condition
self.advance(); // Consume the ';'
condition = Expression::Literal(Literal::Boolean(true)); // Default to true
} else {
condition = self.parse_expression()?;
self.skip_comments(); // Skip comments before the semicolon separator
if !self.match_token(Token::Semicolon) {
eprintln!("Error: Expected ';' after for-loop condition.");
return None;
}
}
// 3. Increment Statement
self.skip_comments(); // <--- CRUCIAL FIX: Skip comments before increment part
let increment: Box<Statement>;
if self.check(&Token::RightParen) { // Empty increment (if ')' is next)
increment = Box::new(Statement::ExpressionStatement(Expression::Literal(Literal::Nil)));
} else {
let incr_expr = self.parse_expression()?; // Now this will see past the comment
increment = Box::new(Statement::ExpressionStatement(incr_expr));
}
self.skip_comments(); // Skip comments before ')'
if !self.match_token(Token::RightParen) {
eprintln!("Error: Expected ')' after for-loop clauses.");
return None;
}
// 4. Body Statement (must be a block)
self.skip_comments(); // Skip comments before '{'
if !self.check(&Token::LeftBrace) {
eprintln!("Error: Expected '{{' for for-loop body.");
return None;
}
// parse_statement() already calls skip_comments() at its beginning
let body = Box::new(self.parse_statement()?);
Some(Statement::ForStatement(initializer, condition, increment, body))
}
fn parse_print_statement(&mut self) -> Option<Statement> {
if !self.match_token(Token::Print) { return None; }
let value = self.parse_expression()?;
@ -479,6 +643,12 @@ impl Parser {
}
}
fn skip_comments(&mut self) {
while !self.is_at_end() && matches!(self.current_token(), Token::Comment(_)) {
self.advance();
}
}
fn match_token(&mut self, expected: Token) -> bool {
let current_matches = match (self.current_token(), &expected) {
(Token::LeftParen, Token::LeftParen) => true,

View File

@ -1,164 +0,0 @@
use crate::lexer::token::Token;
use crate::parser::ast::Expression;
use crate::parser::ast::Statement;
use crate::lexer::Lexer;
pub struct Parser {
tokens: Vec<Token>,
current: usize,
}
#[allow(dead_code)]
impl Parser {
fn parse_statement(&mut self) -> Option<Statement> {
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<Statement> {
let value = self.parse_expression()?;
if self.match_token(Token::Semicolon) {
Some(Statement::PrintStatement(value))
} else {
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 {
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 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();
}
}