mirror of
https://github.com/urinalcaketopper/fddl.git
synced 2025-06-07 05:34:47 +00:00
for
This commit is contained in:
parent
9f594e3775
commit
558cbbc0d2
5
.kdev4/fddl.kdev4
Normal file
5
.kdev4/fddl.kdev4
Normal 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
4
fddl.kdev4
Normal file
@ -0,0 +1,4 @@
|
||||
[Project]
|
||||
CreatedFrom=
|
||||
Manager=KDevGenericManager
|
||||
Name=fddl
|
@ -61,17 +61,28 @@ impl Lexer {
|
||||
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' {
|
||||
|
@ -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.");
|
||||
@ -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,
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user