use crate::frontend::{ source_registry::{SourceId, SourcePosition, 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 { left: Box, operator: TokenType, right: Box, }, Unary { operator: TokenType, operand: Box, }, Grouping { expression: Box, }, Variable { name: String, }, } pub trait ExprPrint { fn print(&self) -> String; } impl ExprPrint for Expr { fn print(&self) -> String { match self { Expr::Literal { value } => format!("Literal {}", value), Expr::Binary { left, operator, right, } => { format!("Binary ({} {} {})", left, operator, right) } Expr::Unary { operator, operand } => { format!("Unary ({} {})", operator, operand) } Expr::Grouping { expression } => { format!("Grouping (group {})", expression) } Expr::Variable { name } => { format!("Variable (variable {})", name) } } } } // 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, } => write!(f, "Binary ({} {} {})", left, operator, right), Expr::Unary { operator, operand } => write!(f, "Unary ({} {})", operator, operand), Expr::Grouping { expression } => write!(f, "Grouping (group {})", expression), 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, } => write!(f, "({:?} {:?} {:?})", operator, left, right), Expr::Unary { operator, operand } => write!(f, "({:?} {:?})", operator, operand), Expr::Grouping { expression } => write!(f, "(group {:?})", expression), Expr::Variable { name } => write!(f, "(variable {:?})", name), } } } #[derive(Clone)] pub enum Stmt { Expression { expression: Box, }, Print { expression: Box, }, Stmt { expression: Box, }, Var { name: String, initializer: Option>, }, Assign { name: String, value: Box, }, Return { expression: Box, }, Block { statements: Box>, }, If { condition: Box, then_branch: Box, elif_branch: Vec<(Box, Box)>, else_branch: Option>, }, While { condition: Box, body: Box, }, For { variable: Box, iterable: Box, body: Box, }, } impl Display for Stmt { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Stmt::Expression { expression } => write!(f, "Expression ({})", expression), Stmt::If { condition, then_branch, elif_branch, else_branch, } => { let mut result = format!("IF ({}) {{\n{}\n}}", condition, then_branch); for (condition, branch) in elif_branch { result.push_str(&format!(" ELIF ({}) {{\n{}\n}}", condition, branch)); } if let Some(else_branch) = else_branch { result.push_str(&format!(" ELSE {{\n{}\n}}", else_branch)); } write!(f, "IfStmt {}", result) } Stmt::Print { expression } => write!(f, "Print({});", expression), Stmt::Stmt { expression } => write!(f, "Stmt({});", expression), Stmt::Var { name, initializer } => { write!(f, "Var({} = {:?});", name, initializer) } Stmt::Assign { name, value } => write!(f, "Assign({} = {});", name, value), Stmt::Return { expression } => write!(f, "Return({});", expression), Stmt::Block { statements } => write!( f, "Block([\n{}\n])", statements .iter() .map(|stmt| format!("\t \t{}", stmt)) .collect::>() .join("\n") ), Stmt::While { condition, body } => todo!(), Stmt::For { variable, iterable, body, } => todo!(), } } } impl Debug for Stmt { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Stmt::Expression { expression } => write!(f, " Expression ({:?})", expression), Stmt::If { condition, then_branch, elif_branch, else_branch, } => { let mut result = format!("IF ({:?}) {{\n{:?}\n}}", condition, then_branch); for (condition, branch) in elif_branch { result.push_str(&format!(" ELIF ({:?}) {{\n{:?}\n}}", condition, branch)); } if let Some(else_branch) = else_branch { result.push_str(&format!(" ELSE {{\n{:?}\n}}", else_branch)); } write!(f, "IfStmt {:?}", result) } Stmt::Print { expression } => write!(f, "Print({:?});", expression), Stmt::Stmt { expression } => write!(f, "Stmt({:?});", expression), Stmt::Var { name, initializer } => { write!(f, "Var({:?} = {:?});", name, initializer) } Stmt::Assign { name, value } => write!(f, "Assign({:?} = {:?});", name, value), Stmt::Return { expression } => write!(f, "Return({:?});", expression), Stmt::Block { statements } => write!( f, "Block([\n{:?}\n])", statements .iter() .map(|stmt| format!("{:?}", stmt)) .collect::>() .join("\t\t\n") ), Stmt::While { condition, body } => todo!(), Stmt::For { variable, iterable, body, } => todo!(), } } } 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: _ } => "expression", Stmt::Var { name: _, initializer: _, } => "variable declaration", Stmt::Assign { name: _, value: _ } => "assignment", Stmt::Return { expression: _ } => "return statement", Stmt::Block { statements: _ } => "block statement", Stmt::If { condition: _, then_branch: _, elif_branch: _, else_branch: _, } => "if statement", Stmt::Print { expression: _ } => "print statement", Stmt::Stmt { expression: _ } => "statement", Stmt::While { condition, body } => todo!(), Stmt::For { variable, iterable, body, } => todo!(), } } } #[derive(Clone, PartialEq)] pub struct AstNode { pub node: T, pub source_slice: SourceSlice, } impl Display for AstNode { 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 Debug for AstNode { 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 AstNode { pub fn new(node: T, source_slice: SourceSlice) -> Self { AstNode { node, source_slice } } }