s_expr/
printer.rs

1use super::data::GroupKind;
2
3/// Simple printer
4#[derive(Clone)]
5pub struct Printer {
6    buf: String,
7    prev: PrinterState,
8}
9
10#[derive(Clone, PartialEq, Eq)]
11pub enum PrinterState {
12    Group,
13    Text,
14}
15
16impl Default for Printer {
17    fn default() -> Self {
18        Self {
19            buf: String::new(),
20            prev: PrinterState::Group,
21        }
22    }
23}
24
25impl Printer {
26    /// Create a new group
27    pub fn open(&mut self, grp: GroupKind) {
28        if self.prev == PrinterState::Text {
29            self.buf.push(' ');
30        }
31        let c = match grp {
32            GroupKind::Paren => '(',
33            GroupKind::Bracket => '[',
34            GroupKind::Brace => '{',
35        };
36        self.prev = PrinterState::Group;
37        self.buf.push(c);
38    }
39
40    /// Close a group
41    pub fn close(&mut self, grp: GroupKind) {
42        let c = match grp {
43            GroupKind::Paren => ')',
44            GroupKind::Bracket => ']',
45            GroupKind::Brace => '}',
46        };
47        self.prev = PrinterState::Group;
48        self.buf.push(c);
49    }
50
51    /// Add text
52    pub fn text(&mut self, s: &str) {
53        if self.prev == PrinterState::Text {
54            self.buf.push(' ');
55        }
56        self.prev = PrinterState::Text;
57        self.buf.push_str(s)
58    }
59
60    pub fn to_string(self) -> String {
61        self.buf
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68
69    #[test]
70    fn t1() {
71        let mut p = Printer::default();
72        p.open(GroupKind::Paren);
73        p.close(GroupKind::Paren);
74        let out = p.to_string();
75        assert_eq!(out, "()");
76    }
77
78    #[test]
79    fn t2() {
80        let mut p = Printer::default();
81        p.open(GroupKind::Paren);
82        p.text("let");
83        p.text("x");
84        p.text("=");
85        p.text("1");
86        p.close(GroupKind::Paren);
87        let out = p.to_string();
88        assert_eq!(out, "(let x = 1)");
89    }
90
91    #[test]
92    fn t3() {
93        let mut p = Printer::default();
94        p.open(GroupKind::Paren);
95        p.text("let");
96        p.text("x");
97        p.text("=");
98        p.open(GroupKind::Paren);
99        p.text("+");
100        p.text("1");
101        p.text("0xabc");
102        p.close(GroupKind::Paren);
103        p.close(GroupKind::Paren);
104        let out = p.to_string();
105        assert_eq!(out, "(let x = (+ 1 0xabc))");
106    }
107}