use crate::IndexKey;
use ascii_tree::{write_tree, Tree};
use std::fmt::Write;
#[derive(Debug)]
pub enum AstNode {
And(
Box<AstNode>,
Box<AstNode>,
),
Eq(
Box<AstNode>,
Box<AstNode>,
),
Ge(
Box<AstNode>,
Box<AstNode>,
),
Gt(
Box<AstNode>,
Box<AstNode>,
),
If(
Box<AstNode>,
Box<AstNode>,
Box<AstNode>,
),
Le(
Box<AstNode>,
Box<AstNode>,
),
Lt(
Box<AstNode>,
Box<AstNode>,
),
Or(
Box<AstNode>,
Box<AstNode>,
),
Null,
Number(IndexKey),
Nq(
Box<AstNode>,
Box<AstNode>,
),
}
impl ToString for AstNode {
fn to_string(&self) -> String {
ast_to_tree(self)
}
}
pub fn ast_to_tree(root: &AstNode) -> String {
let mut ascii_tree = String::new();
let tree = ast_node_to_tree(root);
let _ = write_tree(&mut ascii_tree, &tree);
let mut tree = String::new();
for line in ascii_tree.lines() {
let _ = write!(&mut tree, "\n {}", line);
}
format!("{}\n ", tree)
}
fn ast_node_to_tree(node: &AstNode) -> Tree {
match node {
AstNode::And(lhs, rhs) => node_2("And", lhs, rhs),
AstNode::Eq(lhs, rhs) => node_2("Eq", lhs, rhs),
AstNode::Ge(lhs, rhs) => node_2("Ge", lhs, rhs),
AstNode::Gt(lhs, rhs) => node_2("Gt", lhs, rhs),
AstNode::If(lhs, mid, rhs) => node_3("If", lhs, mid, rhs),
AstNode::Le(lhs, rhs) => node_2("Le", lhs, rhs),
AstNode::Lt(lhs, rhs) => node_2("Lt", lhs, rhs),
AstNode::Null => leaf("Null"),
AstNode::Number(lhs) => node_and_leaf("Number", &format!("`{}`", lhs)),
AstNode::Or(lhs, rhs) => node_2("Or", lhs, rhs),
AstNode::Nq(lhs, rhs) => node_2("Nq", lhs, rhs),
}
}
fn node_2(name: &str, lhs: &AstNode, rhs: &AstNode) -> Tree {
Tree::Node(name.to_string(), vec![ast_node_to_tree(lhs), ast_node_to_tree(rhs)])
}
fn node_3(name: &str, lhs: &AstNode, mid: &AstNode, rhs: &AstNode) -> Tree {
Tree::Node(name.to_string(), vec![ast_node_to_tree(lhs), ast_node_to_tree(mid), ast_node_to_tree(rhs)])
}
fn node_and_leaf(name: &str, leaf: &str) -> Tree {
Tree::Node(name.to_string(), vec![Tree::Leaf(vec![leaf.to_string()])])
}
fn leaf(leaf: &str) -> Tree {
Tree::Leaf(vec![leaf.to_string()])
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_to_string() {
assert_eq!(
r#"
Null
"#,
AstNode::Null.to_string()
)
}
}