use crate::expr::{Binary, Expr, ExprVisitor, Grouping, Literal, Unary}; use crate::stmt::{ExpressionStatement, PrintStatement, StatementVisitor}; pub struct ASTPrinter { pub(crate) depth: u32 } impl ASTPrinter { fn ast_tab(&self) -> String { (0..self.depth).map(|_| " ").collect::() } } impl ExprVisitor<()> for ASTPrinter { fn visit_binary(&mut self, b: &Binary) { println!("{}BINARY",self.ast_tab()); println!("{}op='{}'", self.ast_tab(), b.operator.lexeme); println!("{}left=(", self.ast_tab()); self.depth+=1; self.visit_expr(&*b.left); self.depth-=1; println!("{})", self.ast_tab()); println!("{}right=(", self.ast_tab()); self.depth+=1; self.visit_expr(&*b.right); self.depth-=1; println!("{})", self.ast_tab()); } fn visit_grouping(&mut self, g: &Grouping) { println!("{}GROUPING(", self.ast_tab()); self.depth+=1; self.visit_expr(&*g.expression); self.depth-=1; print!(") "); } fn visit_literal(&mut self, l: &Literal) { match l { Literal::LiteralNumber(i) => print!("{}NUMBER={}", self.ast_tab(), i), Literal::LiteralString(s) => print!("{}STRING='{}'", self.ast_tab(), s), Literal::LiteralBool(b) => print!("{}BOOL={}", self.ast_tab(), b), Literal::LiteralNil => print!("{}NIL", self.ast_tab()), } } fn visit_unary(&mut self, u: &Unary) { println!("{}UNARY(op='{}'", self.ast_tab(), u.operator.lexeme); self.depth+=1; self.visit_expr(&*u.right); self.depth-=1; print!(") "); } fn visit_expr(&mut self, e: &Expr) { match e { Expr::BinaryExpr(b) => { self.visit_binary(b); } Expr::GroupingExpr(g) => { self.visit_grouping(g); } Expr::LiteralExpr(l) => { self.visit_literal(l); } Expr::UnaryExpr(u) => { self.visit_unary(u); } } } } impl StatementVisitor<()> for ASTPrinter { fn visit_expr_stmt(&mut self, e: &ExpressionStatement) -> () { println!("{} EXPR_STMT(", self.ast_tab()); self.depth+=1; self.visit_expr(&e.expr); self.depth-=1; print!(") "); } fn visit_print(&mut self, p: &PrintStatement) -> () { println!("{} EXPR_STMT(", self.ast_tab()); self.depth+=1; self.visit_expr(&p.expr); self.depth-=1; print!(") "); } }