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 (":" IDENTIFIER)? (("=" expression)? ";")| function_declaration * function_declaration -> "::" "(" parameters? ")" ("->" IDENTIFIER)? block_statement * parameters -> ( IDENTIFIER (":" IDENTIFIER)? ("," IDENTIFIER (":" IDENTIFIER)? )* ) * 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 | call * call -> primary ("(" arguments ")")* * arguments -> expression ("," expression)* * primary -> NUMBER | STRING | "true" | "false" | "nil" | "(" expression ")" | IDENTIFIER */ #[derive(Clone, PartialEq)] pub enum Expr { Literal { value: LiteralValue, }, Binary { left: Box>, operator: TokenType, right: Box>, }, Unary { operator: TokenType, operand: Box>, }, Grouping { expression: Box>, }, Identifier { name: String, }, Call { callee: Box>, arguments: Vec>, }, } // 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.node, operator, right.node), Expr::Unary { operator, operand } => write!(f, "Unary ({} {})", operator, operand.node), Expr::Grouping { expression } => write!(f, "Grouping (group {})", expression.node), Expr::Identifier { name } => write!(f, "Identifier (variable {})", name), Expr::Call { callee, arguments } => write!( f, "Call ({}({}))", callee.node, arguments .iter() .map(|arg| arg.node.to_string()) .collect::>() .join(", ") ), } } } 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.node, right.node), Expr::Unary { operator, operand } => write!(f, "({:?} {:?})", operator, operand.node), Expr::Grouping { expression } => write!(f, "(group {:?})", expression.node), Expr::Identifier { name } => write!(f, "(variable {:?})", name), Expr::Call { callee, arguments } => write!( f, "Call ({}({}))", callee.node, arguments .iter() .map(|arg| arg.node.to_string()) .collect::>() .join(", ") ), } } } #[derive(Clone, PartialEq)] pub enum Stmt { Expression { expression: Box>, }, Print { expression: Box>, }, Stmt { expression: Box>, }, VarDeclaration { name: String, initializer: Option>>, }, VarAssigment { 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>, condition: Box>, increment: 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.node), Stmt::If { condition, then_branch, elif_branch, else_branch, } => { let mut result = format!("IF ({}) {{\n{}\n}}", condition.node, then_branch.node); for (condition, branch) in elif_branch { result.push_str(&format!( " ELIF ({}) {{\n{}\n}}", condition.node, branch.node )); } if let Some(else_branch) = else_branch { result.push_str(&format!(" ELSE {{\n{}\n}}", else_branch.node)); } write!(f, "IfStmt {}", result) } Stmt::Print { expression } => write!(f, "Print({});", expression.node), Stmt::Stmt { expression } => write!(f, "Stmt({});", expression.node), Stmt::VarDeclaration { name, initializer } => match initializer { Some(init) => write!(f, "Var({} = {});", name, init.node), None => write!(f, "Var({});", name), }, Stmt::VarAssigment { 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() .map(|stmt| format!("\t \t{}", stmt.node)) .collect::>() .join("\n") ), Stmt::While { condition, body } => { write!(f, "While({}) {{\n{}\n}}", condition.node, body.node) } Stmt::For { variable, condition, increment, body, } => write!( f, "For({} = {} in {}) {{\n{}\n}}", variable.node, condition.node, increment.node, body.node ), } } } impl Debug for Stmt { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Stmt::Expression { expression } => write!(f, " Expression ({:?})", expression.node), Stmt::If { condition, then_branch, elif_branch, else_branch, } => { let mut result = format!("IF ({:?}) {{\n{:?}\n}}", condition.node, then_branch.node); for (condition, branch) in elif_branch { result.push_str(&format!( " ELIF ({:?}) {{\n{:?}\n}}", condition.node, branch.node )); } if let Some(else_branch) = else_branch { result.push_str(&format!(" ELSE {{\n{:?}\n}}", else_branch.node)); } write!(f, "IfStmt {:?}", result) } Stmt::Print { expression } => write!(f, "Print({:?});", expression.node), Stmt::Stmt { expression } => write!(f, "Stmt({:?});", expression.node), Stmt::VarDeclaration { name, initializer } => match initializer { Some(init) => write!(f, "Var({:?} = {:?});", name, init.node), None => write!(f, "Var({:?});", name), }, Stmt::VarAssigment { 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() .map(|stmt| format!("{:?}", stmt.node)) .collect::>() .join("\t\t\n") ), Stmt::While { condition, body } => { write!(f, "While({:?}) {{\n{:?}\n}}", condition.node, body.node) } Stmt::For { variable, condition, increment, body, } => write!( f, "For({:?} = {:?} in {:?}) {{\n{:?}\n}}", variable.node, condition.node, increment.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 { .. } => "unary expression", Expr::Grouping { .. } => "grouping expression", Expr::Identifier { .. } => "variable expression", Expr::Call { .. } => "call expression", } } } impl AstNodeKind for Stmt { fn kind(&self) -> &'static str { match self { Stmt::Expression { .. } => "expression", Stmt::VarDeclaration { .. } => "variable declaration", Stmt::VarAssigment { .. } => "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, Default)] 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 } } }