1use crate::token::{Sub, SubMethod, Token, TokenType};
8
9pub trait Monitor {
10 fn to_string(&self, n: usize) -> String;
13}
14
15impl Monitor for Token {
17 fn to_string(&self, n: usize) -> String {
18 let mut lit: String;
19 let mut space: String = String::new();
20
21 let nest: usize = n;
22 if self.typ != TokenType::SUBEXP {
23 lit = format!("({})", self.literal);
24 } else {
25 lit = String::new();
26 for t in self.sub.tokens.iter().map(|t| t.to_string(nest + 1)) {
27 lit.push_str(format!("\n{t}").as_str())
28 }
29 }
30
31 for _ in 0..nest {
32 space.push_str(" ");
33 }
34
35 let mut typstr = self.typ.to_string(0);
36 if self.is_sub_exp() {
37 typstr.push_str(format!(" -> {{{}}}", self.sub.to_string(0)).as_str());
38 }
39
40 format!("{}{}{}", space.as_str(), typstr, lit)
41 }
42}
43
44impl Monitor for TokenType {
46 fn to_string(&self, _n: usize) -> String {
47 let data = match self {
48 TokenType::NUMBER => "NUMBER",
49 TokenType::IDENTIFIER => "IDENTIFIER",
50 TokenType::ASSIGN => "ASSIGN",
51 TokenType::ILLEGAL => "ILLEGAL",
52 TokenType::SUBEXP => "SUB-EXPRESSION",
53 TokenType::LPAREN => "LEFT-PARENTHESES",
54 TokenType::RPAREN => "RIGHT-PARENTHESES",
55 TokenType::POINTER => "POINTER",
56 TokenType::PLUS => "PLUS",
57 TokenType::MINUS => "MINUS",
58 TokenType::PRODUCT => "PRODUCT",
59 TokenType::DIVIDE => "DIVIDE",
60 TokenType::PERCENTAGE => "PERCENTAGE",
61 TokenType::POWER => "POWER",
62 TokenType::FACTORIAL => "FACTORIAL",
63 TokenType::LABS => "LEFT-ABS",
64 TokenType::RABS => "RIGHT-ABS",
65 TokenType::SQRT => "SQRT",
66 TokenType::SIN => "SIN",
67 TokenType::COS => "COS",
68 TokenType::TAN => "TAN",
69 TokenType::LOG => "LOG",
70 TokenType::LN => "LN",
71 TokenType::EXP => "EXP",
72 TokenType::FLOOR => "FLOOR",
73 TokenType::CEIL => "CEIL",
74 TokenType::ROUND => "ROUND",
75 };
76
77 String::from(data)
78 }
79}
80
81impl Monitor for Sub {
83 fn to_string(&self, _n: usize) -> String {
84 let data = match &self.method {
85 SubMethod::ABS => "ABSOLUTE-VALUE",
86 SubMethod::PAREN => "PARENTHESES",
87 };
88
89 String::from(data)
90 }
91}
92
93impl Monitor for SubMethod {
95 fn to_string(&self, _n: usize) -> String {
96 let data = match self {
97 SubMethod::ABS => "ABSOLUTE-VALUE",
98 SubMethod::PAREN => "PARENTHESES",
99 };
100
101 String::from(data)
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108 use std::collections::HashMap;
109
110 #[test]
111 fn token_to_string() {
112 let test_data: HashMap<String, String> = HashMap::from([
113 (
114 Token::from(String::from("-25"), (0, 1)).to_string(0),
115 String::from("NUMBER(-25)"),
116 ),
117 (
118 Token::from(String::from("/"), (0, 0)).to_string(0),
119 String::from("DIVIDE(/)"),
120 ),
121 ]);
122
123 for (t, expected) in test_data {
124 assert_eq!(t, expected);
125 }
126 }
127
128 #[test]
129 fn token_type_to_string() {
130 let test_data: HashMap<String, &str> = HashMap::from([
131 (TokenType::NUMBER.to_string(0), "NUMBER"),
132 (TokenType::ILLEGAL.to_string(0), "ILLEGAL"),
133 (TokenType::SUBEXP.to_string(0), "SUB-EXPRESSION"),
134 (TokenType::LPAREN.to_string(0), "LEFT-PARENTHESES"),
135 (TokenType::RPAREN.to_string(0), "RIGHT-PARENTHESES"),
136 (TokenType::POINTER.to_string(0), "POINTER"),
137 (TokenType::PLUS.to_string(0), "PLUS"),
138 (TokenType::MINUS.to_string(0), "MINUS"),
139 (TokenType::PRODUCT.to_string(0), "PRODUCT"),
140 (TokenType::DIVIDE.to_string(0), "DIVIDE"),
141 (TokenType::PERCENTAGE.to_string(0), "PERCENTAGE"),
142 (TokenType::POWER.to_string(0), "POWER"),
143 (TokenType::LABS.to_string(0), "LEFT-ABS"),
144 (TokenType::RABS.to_string(0), "RIGHT-ABS"),
145 ]);
146
147 for (tt, expected) in test_data {
148 assert_eq!(tt, expected);
149 }
150 }
151
152 #[test]
153 fn sub_to_string() {
154 let test_data: HashMap<String, &str> = HashMap::from([
155 (
156 Sub::new(Vec::new(), SubMethod::PAREN).to_string(0),
157 "PARENTHESES",
158 ),
159 (
160 Sub::new(Vec::new(), SubMethod::ABS).to_string(0),
161 "ABSOLUTE-VALUE",
162 ),
163 ]);
164
165 for (s, expected) in test_data {
166 assert_eq!(s, expected);
167 }
168 }
169
170 #[test]
171 fn sub_type_to_string() {
172 let test_data: HashMap<String, &str> = HashMap::from([
173 (SubMethod::PAREN.to_string(0), "PARENTHESES"),
174 (SubMethod::ABS.to_string(0), "ABSOLUTE-VALUE"),
175 ]);
176
177 for (s, expected) in test_data {
178 assert_eq!(s, expected);
179 }
180 }
181}