Parseur d'expression et affichage du résultat avec l'ASTPrinter en arborescence.

This commit is contained in:
2024-05-19 22:28:49 +02:00
parent b4d2170eb4
commit 19562ba46e
3 changed files with 49 additions and 28 deletions

View File

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

View File

@@ -30,43 +30,43 @@ pub enum Expr {
} }
pub trait ExprVisitor { pub trait ExprVisitor {
fn visit_binary(&self, b: &Binary); fn visit_binary(&mut self, b: &Binary);
fn visit_grouping(&self, g: &Grouping); fn visit_grouping(&mut self, g: &Grouping);
fn visit_literal(&self, l: &Literal); fn visit_literal(&mut self, l: &Literal);
fn visit_unary(&self, u: &Unary); fn visit_unary(&mut self, u: &Unary);
fn visit_expr(&self, e: &Expr); fn visit_expr(&mut self, e: &Expr);
} }
pub trait VisitableExpr { pub trait VisitableExpr {
fn accept(&self, visitor: &impl ExprVisitor); fn accept(&self, visitor: &mut impl ExprVisitor);
} }
impl VisitableExpr for Binary { impl VisitableExpr for Binary {
fn accept(&self, visitor: &impl ExprVisitor) { fn accept(&self, visitor: &mut impl ExprVisitor) {
visitor.visit_binary(self); visitor.visit_binary(self);
} }
} }
impl VisitableExpr for Grouping { impl VisitableExpr for Grouping {
fn accept(&self, visitor: &impl ExprVisitor) { fn accept(&self, visitor: &mut impl ExprVisitor) {
visitor.visit_grouping(self); visitor.visit_grouping(self);
} }
} }
impl VisitableExpr for Literal { impl VisitableExpr for Literal {
fn accept(&self, visitor: &impl ExprVisitor) { fn accept(&self, visitor: &mut impl ExprVisitor) {
visitor.visit_literal(self); visitor.visit_literal(self);
} }
} }
impl VisitableExpr for Unary { impl VisitableExpr for Unary {
fn accept(&self, visitor: &impl ExprVisitor) { fn accept(&self, visitor: &mut impl ExprVisitor) {
visitor.visit_unary(self); visitor.visit_unary(self);
} }
} }
impl VisitableExpr for Expr { impl VisitableExpr for Expr {
fn accept(&self, visitor: &impl ExprVisitor) { fn accept(&self, visitor: &mut impl ExprVisitor) {
visitor.visit_expr(self); visitor.visit_expr(self);
} }
} }

View File

@@ -48,8 +48,9 @@ impl RLoxInterpreter {
let mut parser = Parser::new( scanner.tokens ); let mut parser = Parser::new( scanner.tokens );
match parser.parse() { match parser.parse() {
Some(expr) => { Some(expr) => {
let printer = ASTPrinter; let mut printer = ASTPrinter { depth: 0 };
printer.visit_expr(&expr); printer.visit_expr(&expr);
println!();
}, },
None => println!("An error occurred while parsing expression.") None => println!("An error occurred while parsing expression.")
} }