Parseur d'expression et affichage du résultat avec l'ASTPrinter en arborescence.
This commit is contained in:
@@ -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);
|
||||||
print!(")");
|
self.depth-=1;
|
||||||
|
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);
|
||||||
print!(")");
|
self.depth-=1;
|
||||||
|
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); }
|
||||||
|
|||||||
22
src/expr.rs
22
src/expr.rs
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user