Files
rlox/src/frontend/ast.rs
T

314 lines
10 KiB
Rust
Raw Normal View History

use crate::frontend::{
source_registry::SourceSlice,
tokens::{LiteralValue, TokenType},
};
use std::fmt::{Debug, Display};
/*
* grammar:
* program -> statement* EOF
* statement -> expression_statement
* | print_statement
* | var_statement
* | block_statement
* | assignment_statement
* | if_statement
*
* expression_statement -> expression ";"
* print_statement -> "print" expression ";"
* var_statement -> "var" IDENTIFIER ("=" expression)? ";"
* assignment_statement -> IDENTIFIER "=" expression ";"
* block_statement -> "do" statement* "end"
* if_statement -> "if" expression "then" statement ("elif" expression "then" statement)* ("else" statement)? "end"
* while_statement -> "while" expression "do" statement "end"
*
* expression -> assignment
* assignment -> IDENTIFIER "=" assignment | logical_or
* logical_or -> logical_and (("or" logical_and)*
* logical_and -> equality (("and" equality)*
* equality -> comparison (("==" | "!=") comparison)*
* comparison -> term ((">" | ">=" | "<" | "<=") term)*
* term -> factor (("+" | "-") factor)*
* factor -> unary (("*" | "/") unary)*
* unary -> ("!" | "-") unary | primary
* primary -> NUMBER | STRING | "true" | "false" | "nil" | "(" expression ")" | IDENTIFIER
*/
#[derive(Clone)]
pub enum Expr {
Literal {
value: LiteralValue,
},
Binary {
2025-10-04 19:02:33 +02:00
left: Box<AstNode<Expr>>,
operator: TokenType,
2025-10-04 19:02:33 +02:00
right: Box<AstNode<Expr>>,
},
Unary {
operator: TokenType,
2025-10-04 19:02:33 +02:00
operand: Box<AstNode<Expr>>,
},
Grouping {
2025-10-04 19:02:33 +02:00
expression: Box<AstNode<Expr>>,
},
Variable {
name: String,
},
}
// Implementazione Display per Expr (per debugging)
impl std::fmt::Display for Expr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Expr::Literal { value } => write!(f, "Literal {}", value),
Expr::Binary {
left,
operator,
right,
2025-10-04 19:02:33 +02:00
} => write!(f, "Binary ({} {} {})", left.node, operator, right.node),
Expr::Unary { operator, operand } => write!(f, "Unary ({} {})", operator, operand.node),
Expr::Grouping { expression } => write!(f, "Grouping (group {})", expression.node),
Expr::Variable { name } => write!(f, "Variable (variable {})", name),
}
}
}
impl Debug for Expr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Expr::Literal { value } => write!(f, "{:?}", value),
Expr::Binary {
left,
operator,
right,
2025-10-04 19:02:33 +02:00
} => write!(f, "({:?} {:?} {:?})", operator, left.node, right.node),
Expr::Unary { operator, operand } => write!(f, "({:?} {:?})", operator, operand.node),
Expr::Grouping { expression } => write!(f, "(group {:?})", expression.node),
Expr::Variable { name } => write!(f, "(variable {:?})", name),
}
}
}
#[derive(Clone)]
pub enum Stmt {
Expression {
2025-10-04 19:02:33 +02:00
expression: Box<AstNode<Expr>>,
},
Print {
2025-10-04 19:02:33 +02:00
expression: Box<AstNode<Expr>>,
},
Stmt {
2025-10-04 19:02:33 +02:00
expression: Box<AstNode<Expr>>,
},
Var {
name: String,
2025-10-04 19:02:33 +02:00
initializer: Option<Box<AstNode<Expr>>>,
},
Assign {
name: String,
2025-10-04 19:02:33 +02:00
value: Box<AstNode<Expr>>,
},
Return {
2025-10-04 19:02:33 +02:00
expression: Box<AstNode<Expr>>,
},
Block {
2025-10-04 19:02:33 +02:00
statements: Box<Vec<AstNode<Stmt>>>,
},
If {
2025-10-04 19:02:33 +02:00
condition: Box<AstNode<Expr>>,
then_branch: Box<AstNode<Stmt>>,
elif_branch: Vec<(Box<AstNode<Expr>>, Box<AstNode<Stmt>>)>,
else_branch: Option<Box<AstNode<Stmt>>>,
},
While {
2025-10-04 19:02:33 +02:00
condition: Box<AstNode<Expr>>,
body: Box<AstNode<Stmt>>,
},
For {
2025-10-04 19:02:33 +02:00
variable: Box<AstNode<Expr>>,
iterable: Box<AstNode<Expr>>,
body: Box<AstNode<Stmt>>,
},
}
impl Display for Stmt {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
2025-10-04 19:02:33 +02:00
Stmt::Expression { expression } => write!(f, "Expression ({})", expression.node),
Stmt::If {
condition,
then_branch,
elif_branch,
else_branch,
} => {
2025-10-04 19:02:33 +02:00
let mut result = format!("IF ({}) {{\n{}\n}}", condition.node, then_branch.node);
for (condition, branch) in elif_branch {
2025-10-04 19:02:33 +02:00
result.push_str(&format!(
" ELIF ({}) {{\n{}\n}}",
condition.node, branch.node
));
}
if let Some(else_branch) = else_branch {
2025-10-04 19:02:33 +02:00
result.push_str(&format!(" ELSE {{\n{}\n}}", else_branch.node));
}
write!(f, "IfStmt {}", result)
}
2025-10-04 19:02:33 +02:00
Stmt::Print { expression } => write!(f, "Print({});", expression.node),
Stmt::Stmt { expression } => write!(f, "Stmt({});", expression.node),
Stmt::Var { name, initializer } => match initializer {
Some(init) => write!(f, "Var({} = {});", name, init.node),
None => write!(f, "Var({});", name),
},
Stmt::Assign { name, value } => write!(f, "Assign({} = {});", name, value.node),
Stmt::Return { expression } => write!(f, "Return({});", expression.node),
Stmt::Block { statements } => write!(
f,
"Block([\n{}\n])",
statements
.iter()
2025-10-04 19:02:33 +02:00
.map(|stmt| format!("\t \t{}", stmt.node))
.collect::<Vec<_>>()
.join("\n")
),
2025-10-04 19:02:33 +02:00
Stmt::While { condition, body } => {
write!(f, "While({}) {{\n{}\n}}", condition.node, body.node)
}
Stmt::For {
variable,
iterable,
body,
2025-10-04 19:02:33 +02:00
} => write!(
f,
"For({} in {}) {{\n{}\n}}",
variable.node, iterable.node, body.node
),
}
}
}
impl Debug for Stmt {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
2025-10-04 19:02:33 +02:00
Stmt::Expression { expression } => write!(f, " Expression ({:?})", expression.node),
Stmt::If {
condition,
then_branch,
elif_branch,
else_branch,
} => {
2025-10-04 19:02:33 +02:00
let mut result =
format!("IF ({:?}) {{\n{:?}\n}}", condition.node, then_branch.node);
for (condition, branch) in elif_branch {
2025-10-04 19:02:33 +02:00
result.push_str(&format!(
" ELIF ({:?}) {{\n{:?}\n}}",
condition.node, branch.node
));
}
if let Some(else_branch) = else_branch {
2025-10-04 19:02:33 +02:00
result.push_str(&format!(" ELSE {{\n{:?}\n}}", else_branch.node));
}
write!(f, "IfStmt {:?}", result)
}
2025-10-04 19:02:33 +02:00
Stmt::Print { expression } => write!(f, "Print({:?});", expression.node),
Stmt::Stmt { expression } => write!(f, "Stmt({:?});", expression.node),
Stmt::Var { name, initializer } => match initializer {
Some(init) => write!(f, "Var({:?} = {:?});", name, init.node),
None => write!(f, "Var({:?});", name),
},
Stmt::Assign { name, value } => write!(f, "Assign({:?} = {:?});", name, value.node),
Stmt::Return { expression } => write!(f, "Return({:?});", expression.node),
Stmt::Block { statements } => write!(
f,
"Block([\n{:?}\n])",
statements
.iter()
2025-10-04 19:02:33 +02:00
.map(|stmt| format!("{:?}", stmt.node))
.collect::<Vec<_>>()
.join("\t\t\n")
),
2025-10-04 19:02:33 +02:00
Stmt::While { condition, body } => {
write!(f, "While({:?}) {{\n{:?}\n}}", condition.node, body.node)
}
Stmt::For {
variable,
iterable,
body,
2025-10-04 19:02:33 +02:00
} => write!(
f,
"For({:?} in {:?}) {{\n{:?}\n}}",
variable.node, iterable.node, body.node
),
}
}
}
pub trait AstNodeKind {
fn kind(&self) -> &'static str;
}
impl AstNodeKind for Expr {
fn kind(&self) -> &'static str {
match self {
Expr::Literal { value: _ } => "literal",
Expr::Binary {
left: _,
operator: _,
right: _,
} => "binary expression",
Expr::Unary {
operator: _,
operand: _,
} => "unary expression",
Expr::Grouping { expression: _ } => "grouping expression",
Expr::Variable { name: _ } => "variable expression",
}
}
}
impl AstNodeKind for Stmt {
fn kind(&self) -> &'static str {
match self {
Stmt::Expression { .. } => "expression",
Stmt::Var { .. } => "variable declaration",
Stmt::Assign { .. } => "assignment",
Stmt::Return { .. } => "return statement",
Stmt::Block { .. } => "block statement",
Stmt::If { .. } => "if statement",
Stmt::Print { .. } => "print statement",
Stmt::Stmt { .. } => "statement",
Stmt::While { .. } => "while statement",
Stmt::For { .. } => "for statement",
}
}
}
#[derive(Clone, PartialEq)]
pub struct AstNode<T: AstNodeKind + Debug + Display> {
pub node: T,
pub source_slice: SourceSlice,
}
impl<T: AstNodeKind + Debug + Display> Display for AstNode<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"AstNode \n{{ \n\tnode: {},\n\tsource_slice: {}, \n}}",
self.node, self.source_slice
)
}
}
impl<T: AstNodeKind + Debug + Display> Debug for AstNode<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"AstNode \n{{ \n\tnode: {:?},\n\tsource_slice: {:?}, \n}}",
self.node, self.source_slice
)
}
}
impl<T: AstNodeKind + Debug + Display> AstNode<T> {
pub fn new(node: T, source_slice: SourceSlice) -> Self {
AstNode { node, source_slice }
}
}