simple_shunting/
rpnprint.rs

1use crate::parser::RPNExpr;
2use lexers::MathToken;
3use std::fmt;
4
5#[derive(Debug, Clone)]
6enum AST<'a> {
7    Leaf(&'a MathToken),
8    Node(&'a MathToken, Vec<AST<'a>>),
9}
10
11impl RPNExpr {
12    fn build_ast(&self) -> AST {
13        let mut ops = Vec::new();
14        for token in &self.0 {
15            match token {
16                MathToken::Number(_) | MathToken::Variable(_) =>
17                    ops.push(AST::Leaf(token)),
18                MathToken::Function(_, arity) => {
19                    let children = ops.split_off(ops.len() - arity);
20                    ops.push(AST::Node(token, children));
21                },
22                MathToken::BOp(_) => {
23                    let children = ops.split_off(ops.len() - 2);
24                    ops.push(AST::Node(token, children));
25                },
26                MathToken::UOp(_) => {
27                    let children = ops.split_off(ops.len() - 1);
28                    ops.push(AST::Node(token, children));
29                },
30                _ => unreachable!(),
31            }
32        }
33        ops.pop().unwrap()
34    }
35}
36
37impl fmt::Display for RPNExpr {
38    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39        fn print_helper(root: &AST, indent: &str, out: &mut String) {
40            match root {
41                AST::Leaf(tok) => *out += &format!("\u{2500}{:?}\n", tok),
42                AST::Node(tok, children) => {
43                    // Print current node
44                    *out += &format!("\u{252c}{:?}\n", tok);
45                    // Print its children
46                    if let Some((last_node, rest)) = children.split_last() {
47                        for mid_node in rest {
48                            *out += &format!("{}\u{251c}", indent);
49                            print_helper(mid_node, &format!("{}\u{2502}", indent), out);
50                        }
51                        *out += &format!("{}\u{2570}", indent);
52                        print_helper(last_node, &format!("{} ", indent), out);
53                    }
54                }
55            }
56        }
57        let mut output = String::new();
58        print_helper(&self.build_ast(), "", &mut output);
59        write!(f, "{}", output)
60    }
61}