2025-10-03 19:07:12 +02:00
|
|
|
use crate::frontend::{
|
2025-10-04 21:05:00 +02:00
|
|
|
source_registry::SourceSlice,
|
2025-10-03 19:07:12 +02:00
|
|
|
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"
|
2025-10-03 19:40:25 +02:00
|
|
|
* while_statement -> "while" expression "do" statement "end"
|
2025-10-03 19:07:12 +02:00
|
|
|
*
|
|
|
|
|
* 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>>,
|
2025-10-03 19:07:12 +02:00
|
|
|
operator: TokenType,
|
2025-10-04 19:02:33 +02:00
|
|
|
right: Box<AstNode<Expr>>,
|
2025-10-03 19:07:12 +02:00
|
|
|
},
|
|
|
|
|
Unary {
|
|
|
|
|
operator: TokenType,
|
2025-10-04 19:02:33 +02:00
|
|
|
operand: Box<AstNode<Expr>>,
|
2025-10-03 19:07:12 +02:00
|
|
|
},
|
|
|
|
|
Grouping {
|
2025-10-04 19:02:33 +02:00
|
|
|
expression: Box<AstNode<Expr>>,
|
2025-10-03 19:07:12 +02:00
|
|
|
},
|
|
|
|
|
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),
|
2025-10-03 19:07:12 +02:00
|
|
|
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),
|
2025-10-03 19:07:12 +02:00
|
|
|
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>>,
|
2025-10-03 19:07:12 +02:00
|
|
|
},
|
|
|
|
|
Print {
|
2025-10-04 19:02:33 +02:00
|
|
|
expression: Box<AstNode<Expr>>,
|
2025-10-03 19:07:12 +02:00
|
|
|
},
|
|
|
|
|
Stmt {
|
2025-10-04 19:02:33 +02:00
|
|
|
expression: Box<AstNode<Expr>>,
|
2025-10-03 19:07:12 +02:00
|
|
|
},
|
|
|
|
|
Var {
|
|
|
|
|
name: String,
|
2025-10-04 19:02:33 +02:00
|
|
|
initializer: Option<Box<AstNode<Expr>>>,
|
2025-10-03 19:07:12 +02:00
|
|
|
},
|
|
|
|
|
Assign {
|
|
|
|
|
name: String,
|
2025-10-04 19:02:33 +02:00
|
|
|
value: Box<AstNode<Expr>>,
|
2025-10-03 19:07:12 +02:00
|
|
|
},
|
|
|
|
|
Return {
|
2025-10-04 19:02:33 +02:00
|
|
|
expression: Box<AstNode<Expr>>,
|
2025-10-03 19:07:12 +02:00
|
|
|
},
|
|
|
|
|
Block {
|
2025-10-04 19:02:33 +02:00
|
|
|
statements: Box<Vec<AstNode<Stmt>>>,
|
2025-10-03 19:07:12 +02:00
|
|
|
},
|
|
|
|
|
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>>>,
|
2025-10-03 19:07:12 +02:00
|
|
|
},
|
2025-10-03 19:40:25 +02:00
|
|
|
While {
|
2025-10-04 19:02:33 +02:00
|
|
|
condition: Box<AstNode<Expr>>,
|
|
|
|
|
body: Box<AstNode<Stmt>>,
|
2025-10-03 19:40:25 +02:00
|
|
|
},
|
|
|
|
|
For {
|
2025-10-04 19:02:33 +02:00
|
|
|
variable: Box<AstNode<Expr>>,
|
|
|
|
|
iterable: Box<AstNode<Expr>>,
|
|
|
|
|
body: Box<AstNode<Stmt>>,
|
2025-10-03 19:40:25 +02:00
|
|
|
},
|
2025-10-03 19:07:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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),
|
2025-10-03 19:07:12 +02:00
|
|
|
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);
|
2025-10-03 19:07:12 +02:00
|
|
|
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
|
|
|
|
|
));
|
2025-10-03 19:07:12 +02:00
|
|
|
}
|
|
|
|
|
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));
|
2025-10-03 19:07:12 +02:00
|
|
|
}
|
|
|
|
|
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),
|
2025-10-03 19:07:12 +02:00
|
|
|
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))
|
2025-10-03 19:07:12 +02:00
|
|
|
.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)
|
|
|
|
|
}
|
2025-10-03 19:40:25 +02:00
|
|
|
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
|
|
|
|
|
),
|
2025-10-03 19:07:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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),
|
2025-10-03 19:07:12 +02:00
|
|
|
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);
|
2025-10-03 19:07:12 +02:00
|
|
|
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
|
|
|
|
|
));
|
2025-10-03 19:07:12 +02:00
|
|
|
}
|
|
|
|
|
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));
|
2025-10-03 19:07:12 +02:00
|
|
|
}
|
|
|
|
|
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),
|
2025-10-03 19:07:12 +02:00
|
|
|
Stmt::Block { statements } => write!(
|
|
|
|
|
f,
|
|
|
|
|
"Block([\n{:?}\n])",
|
|
|
|
|
statements
|
|
|
|
|
.iter()
|
2025-10-04 19:02:33 +02:00
|
|
|
.map(|stmt| format!("{:?}", stmt.node))
|
2025-10-03 19:07:12 +02:00
|
|
|
.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)
|
|
|
|
|
}
|
2025-10-03 19:40:25 +02:00
|
|
|
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
|
|
|
|
|
),
|
2025-10-03 19:07:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 {
|
2025-10-04 21:05:00 +02:00
|
|
|
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",
|
2025-10-03 19:07:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[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 }
|
|
|
|
|
}
|
|
|
|
|
}
|