let statement parsing

This commit is contained in:
YannAhlgrim
2026-06-01 16:52:45 +02:00
parent 4accaa2edc
commit 0b4223e509
3 changed files with 123 additions and 29 deletions
+13 -13
View File
@@ -1,17 +1,17 @@
use crate::token; use crate::token;
trait NodeTrait { pub trait NodeTrait {
fn token_literal(&self) -> String; fn token_literal(&self) -> String;
} }
trait StatementTrait: NodeTrait { pub trait StatementTrait: NodeTrait {
fn statement_node(&self); fn statement_node(&self);
} }
trait ExpressionTrait: NodeTrait { trait ExpressionTrait: NodeTrait {
fn expression_node(&self); fn expression_node(&self);
} }
struct Expression { pub struct Expression {
// //
} }
impl NodeTrait for Expression { impl NodeTrait for Expression {
@@ -20,7 +20,7 @@ impl NodeTrait for Expression {
} }
} }
struct Statement { pub struct Statement {
// //
} }
impl NodeTrait for Statement { impl NodeTrait for Statement {
@@ -34,12 +34,12 @@ impl StatementTrait for Statement {
} }
pub struct Program { pub struct Program {
statements: Vec<Statement>, pub statements: Vec<Box<dyn StatementTrait>>,
} }
impl NodeTrait for Program { impl NodeTrait for Program {
fn token_literal(&self) -> String { fn token_literal(&self) -> String {
if self.statements.is_empty() { if !self.statements.is_empty() {
self.statements[0].token_literal() self.statements[0].token_literal()
} else { } else {
String::new() String::new()
@@ -47,10 +47,10 @@ impl NodeTrait for Program {
} }
} }
struct LetStatement { pub struct LetStatement {
token: token::Token, pub token: token::Token,
name: Identifier, pub name: Identifier,
value: Expression, pub value: Expression,
} }
impl NodeTrait for LetStatement { impl NodeTrait for LetStatement {
@@ -65,9 +65,9 @@ impl StatementTrait for LetStatement {
} }
} }
struct Identifier { pub struct Identifier {
token: token::Token, pub token: token::Token,
value: String, pub value: String,
} }
impl NodeTrait for Identifier { impl NodeTrait for Identifier {
+102 -8
View File
@@ -1,21 +1,30 @@
use crate::{ use crate::{
ast, ast::{self},
lexer::{self, LexerTraits}, lexer::{self, LexerTraits},
token, token::{self, EOF},
}; };
pub struct Parser { pub struct Parser {
lexer: lexer::Lexer, lexer: lexer::Lexer,
cur_token: token::Token, cur_token: token::Token,
peek_token: token::Token, peek_token: token::Token,
errors: Vec<String>,
} }
trait PaserTrait { pub trait ParserTrait {
fn next_token(&mut self); fn next_token(&mut self);
fn parse_program(&self) -> ast::Program; fn parse_program(&mut self) -> ast::Program;
fn parse_statement(&mut self) -> Option<Box<dyn ast::StatementTrait>>;
fn parse_let_statement(&mut self) -> Option<Box<dyn ast::StatementTrait>>;
fn cur_token_is(&self, t: String) -> bool;
fn peek_token_is(&self, t: String) -> bool;
fn expect_peek(&mut self, t: String) -> bool;
fn errors(&self) -> &Vec<String>;
fn peek_error(&mut self, t: String);
} }
pub fn new(l: lexer::Lexer) -> Parser { pub fn new_parser(l: lexer::Lexer) -> Parser {
let mut p: Parser = Parser { let mut p: Parser = Parser {
lexer: l, lexer: l,
cur_token: token::Token { cur_token: token::Token {
@@ -26,13 +35,14 @@ pub fn new(l: lexer::Lexer) -> Parser {
literal: String::new(), literal: String::new(),
type_: String::new(), type_: String::new(),
}, },
errors: Vec::new(),
}; };
p.next_token(); p.next_token();
p.next_token(); p.next_token();
p p
} }
impl PaserTrait for Parser { impl ParserTrait for Parser {
fn next_token(&mut self) { fn next_token(&mut self) {
self.cur_token = token::Token { self.cur_token = token::Token {
literal: String::from(&self.peek_token.literal), literal: String::from(&self.peek_token.literal),
@@ -41,7 +51,91 @@ impl PaserTrait for Parser {
self.peek_token = self.lexer.next_token(); self.peek_token = self.lexer.next_token();
} }
fn parse_program(&self) -> ast::Program { fn parse_program(&mut self) -> ast::Program {
todo!() let mut program = ast::Program {
statements: Vec::new(),
};
while &self.cur_token.type_ != EOF {
if let Some(stmt) = self.parse_statement() {
program.statements.push(stmt);
}
self.next_token();
}
program
}
fn parse_statement(&mut self) -> Option<Box<dyn ast::StatementTrait>> {
match self.cur_token.type_.as_str() {
token::LET => self.parse_let_statement(),
_ => None,
}
}
fn cur_token_is(&self, t: String) -> bool {
self.cur_token.type_ == t
}
fn peek_token_is(&self, t: String) -> bool {
self.peek_token.type_ == t
}
fn expect_peek(&mut self, t: String) -> bool {
if self.peek_token_is(t) {
self.next_token();
true
} else {
false
}
}
fn parse_let_statement(&mut self) -> Option<Box<dyn ast::StatementTrait>> {
let mut stmt = ast::LetStatement {
token: token::Token {
literal: String::from(&self.cur_token.literal),
type_: String::from(&self.cur_token.type_),
},
name: ast::Identifier {
token: token::Token {
literal: String::new(),
type_: String::new(),
},
value: String::new(),
},
value: ast::Expression {},
};
if !self.expect_peek(token::IDENT.to_string()) {
return None;
}
stmt.name = ast::Identifier {
token: token::Token {
literal: String::from(&self.cur_token.literal),
type_: String::from(&self.cur_token.type_),
},
value: String::from(&self.cur_token.literal),
};
if !self.expect_peek(token::ASSIGN.to_string()) {
return None;
}
while !self.cur_token_is(token::SEMICOLON.to_string()) {
self.next_token();
}
Some(Box::from(stmt))
}
fn errors(&self) -> &Vec<String> {
&self.errors
}
fn peek_error(&mut self, t: String) {
let msg = format!(
"expected next token to be {}, got {} instead",
t, self.peek_token.type_
);
self.errors.push(msg);
} }
} }
+8 -8
View File
@@ -1,5 +1,7 @@
use crate::lexer::LexerTraits;
use crate::lexer::new; use crate::lexer::new;
use crate::parser::Parser;
use crate::parser::ParserTrait;
use crate::parser::new_parser;
const PROMPT: &str = ">> "; const PROMPT: &str = ">> ";
@@ -15,13 +17,11 @@ pub fn start_repl() {
if input == "exit" { if input == "exit" {
break; break;
} }
let mut lexer = new(input.to_string()); let lexer = new(input.to_string());
loop { let mut parser: Parser = new_parser(lexer);
let token = lexer.next_token(); let program = parser.parse_program();
if token.type_ == "EOF" { for stmt in program.statements {
break; println!("{:?}", stmt.token_literal());
}
println!("Token: {:?}, Literal: {:?}", token.type_, token.literal);
} }
} }
} }