diff --git a/src/astprinter.rs b/src/astprinter.rs new file mode 100644 index 0000000..bc1c9a0 --- /dev/null +++ b/src/astprinter.rs @@ -0,0 +1,42 @@ +use crate::expr::{Binary, Expr, ExprVisitor, Grouping, Literal, Unary, VisitableExpr}; + +pub struct ASTPrinter; + +impl ExprVisitor for ASTPrinter { + fn visit_binary(&self, b: &Binary) { + print!("( {}", b.operator.literal); + b.left.accept(self); + b.right.accept(self); + print!(")"); + } + + fn visit_grouping(&self, g: &Grouping) { + print!("( group "); + g.expression.accept(self); + print!(")"); + } + + fn visit_literal(&self, l: &Literal) { + match l { + Literal::LiteralNumber(i) => print!("{}", i), + Literal::LiteralString(s) => print!("{}", s), + Literal::LiteralBool(b) => print!("{}", b), + Literal::LiteralNil => print!("nil"), + } + } + + fn visit_unary(&self, u: &Unary) { + print!("( {}", u.operator.literal); + u.right.accept(self); + print!(")"); + } + + fn visit_expr(&self, e: &Expr) { + match e { + Expr::BinaryExpr(b) => { b.accept(self); } + Expr::GroupingExpr(g) => { g.accept(self); } + Expr::LiteralExpr(l) => { l.accept(self); } + Expr::UnaryExpr(u) => { u.accept(self); } + } + } +} \ No newline at end of file diff --git a/src/expr.rs b/src/expr.rs index 07c0e6c..6da9c08 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -29,53 +29,44 @@ pub enum Expr { UnaryExpr(Unary), } -pub trait Visitable { - fn visit(&self); +pub trait ExprVisitor { + fn visit_binary(&self, b: &Binary); + fn visit_grouping(&self, g: &Grouping); + fn visit_literal(&self, l: &Literal); + fn visit_unary(&self, u: &Unary); + fn visit_expr(&self, e: &Expr); } -impl Visitable for Binary { - fn visit(&self) { - print!("( {}",&self.operator.literal); - &self.left.visit(); - &self.right.visit(); - print!(")"); +pub trait VisitableExpr { + fn accept(&self, visitor: &impl ExprVisitor); +} + +impl VisitableExpr for Binary { + fn accept(&self, visitor: &impl ExprVisitor) { + visitor.visit_binary(self); } } -impl Visitable for Grouping { - fn visit(&self) { - print!("( group "); - &self.expression.visit(); - print!(")"); +impl VisitableExpr for Grouping { + fn accept(&self, visitor: &impl ExprVisitor) { + visitor.visit_grouping(self); } } -impl Visitable for Literal { - fn visit(&self) { - match &self { - Literal::LiteralNumber(i) => print!("{}", i), - Literal::LiteralString(s) => print!("{}", s), - Literal::LiteralBool(b) => print!("{}", b), - Literal::LiteralNil => print!("nil"), - } +impl VisitableExpr for Literal { + fn accept(&self, visitor: &impl ExprVisitor) { + visitor.visit_literal(self); } } -impl Visitable for Unary { - fn visit(&self) { - print!("( {}",&self.operator.literal); - &self.right.visit(); - print!(")"); +impl VisitableExpr for Unary { + fn accept(&self, visitor: &impl ExprVisitor) { + visitor.visit_unary(self); } } -impl Visitable for Expr { - fn visit(&self) { - match &self { - Expr::BinaryExpr(b) => { b.visit(); } - Expr::GroupingExpr(g) => { g.visit(); } - Expr::LiteralExpr(l) => { l.visit(); } - Expr::UnaryExpr(u) => { u.visit(); } - } +impl VisitableExpr for Expr { + fn accept(&self, visitor: &impl ExprVisitor) { + visitor.visit_expr(self); } } diff --git a/src/main.rs b/src/main.rs index 59cbee5..51ad7cc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,17 +1,20 @@ use std::env; use std::process; -use crate::expr::{Binary, Expr, Grouping, Literal, Unary, Visitable}; -use crate::expr::Expr::LiteralExpr; mod rlox_interpreter; + mod scanner; mod token; mod token_type; mod expr; +mod astprinter; use crate::rlox_interpreter::RLoxInterpreter; use crate::token::Token; use crate::token_type::TokenType; +use crate::expr::{Binary, Expr, Grouping, Literal, Unary, VisitableExpr}; +use crate::expr::Expr::LiteralExpr; +use crate::astprinter::ASTPrinter; // Exit codes from #include const EX_OK: i32 = 0; @@ -44,7 +47,7 @@ fn essai_visitor() { line: 0, literal: String::from("-") }, - right: Box::new(Expr::LiteralExpr(Literal::LiteralNumber(123.0))) + right: Box::new(Expr::LiteralExpr(Literal::LiteralNumber(456.0))) })), operator: Token { token_type: TokenType::Star, @@ -57,7 +60,8 @@ fn essai_visitor() { })) }); - expression.visit(); + let a = ASTPrinter{}; + expression.accept(&a); }