izanami/src/printer.rs
Seymur Bagirov 977fd9a8a8 fix: actually finish challeng #2(ch.6)
I didn't implement the scanner and the printer lol
2025-01-05 05:12:20 +04:00

97 lines
2.7 KiB
Rust

use crate::{ast::Expr, token::LiteralType};
pub fn pretty_print(expr: &Expr) -> String {
match expr {
Expr::Binary { left, op, right } => parenthesize(&op.lexeme, &[left, right]),
Expr::Grouping { expression } => parenthesize("group", &[expression]),
Expr::Literal { value } => match value {
Some(LiteralType::String(v)) => v.to_string(),
Some(LiteralType::Number(v)) => v.to_string(),
Some(LiteralType::Bool(v)) => v.to_string(),
Some(LiteralType::Nil) => "Nil".to_string(),
None => "None".to_string(),
},
Expr::Unary { op, right } => parenthesize(&op.lexeme, &[right]),
Expr::Ternary {
first,
first_op,
second,
second_op,
third,
} => parenthesize(
&format!("{}{}", first_op.lexeme, second_op.lexeme),
&[first, second, third],
),
}
}
fn parenthesize(name: &str, exprs: &[&Expr]) -> String {
let mut parenthesized = format!("({name}");
for expr in exprs {
parenthesized.push(' ');
parenthesized.push_str(&pretty_print(expr));
}
parenthesized.push(')');
parenthesized
}
#[cfg(test)]
mod test {
use crate::token::{Token, TokenType};
use super::*;
use Expr::*;
#[test]
fn equal_print_binary() {
use TokenType::*;
let expression = Binary {
left: Box::new(Literal {
value: Some(LiteralType::Number(10.2)),
}),
op: Token {
t_type: Plus,
lexeme: "+".to_string(),
literal: None,
line: 0,
},
right: Box::new(Literal {
value: Some(LiteralType::Number(10.2)),
}),
};
let actual = pretty_print(&expression);
let expected = "(+ 10.2 10.2)";
assert_eq!(actual, expected);
}
#[test]
// tests all cases
fn equal_test_whole() {
use TokenType::*;
let expression = Binary {
left: Box::new(Unary {
op: Token::new(Minus, "-", None, 0),
right: Box::new(Expr::Literal {
value: Some(LiteralType::number_literal(123.0)),
}),
}),
op: Token::new(Star, "*", None, 0),
right: Box::new(Grouping {
expression: Box::new(Literal {
value: Some(LiteralType::number_literal(45.67)),
}),
}),
};
let actual = pretty_print(&expression);
let expected = "(* (- 123) (group 45.67))";
assert_eq!(expected, actual);
}
}