1use crate::push::instructions::InstructionSet;
2use crate::push::item::Item;
3use crate::push::stack::PushStack;
4use crate::push::state::PushState;
5use crate::push::vector::{BoolVector, FloatVector, IntVector};
6
7pub struct PushParser {}
8
9#[derive(Debug)]
10pub enum VectorType {
11 Bool,
12 Int,
13 Float,
14}
15
16impl PushParser {
17 pub fn rec_push(stack: &mut PushStack<Item>, item: Item, depth: usize) -> bool {
20 if depth == 0 {
21 stack.push_front(item);
23 return true;
24 }
25 if let Some(mut bottom_item) = stack.bottom_mut() {
26 match &mut bottom_item {
27 Item::List { items } => {
28 return PushParser::rec_push(items, item, depth - 1);
30 }
31 _ => {
32 false
34 }
35 }
36 } else {
37 stack.push(item);
39 true
40 }
41 }
42
43 pub fn copy_to_code_stack(push_state: &mut PushState) {
46 let n = push_state.exec_stack.size();
47 if let Some(exec_code) = push_state.exec_stack.copy_vec(n) {
48 push_state.code_stack.push_vec(exec_code);
49 }
50 }
51
52 pub fn parse_vector(
55 push_state: &mut PushState,
56 depth: usize,
57 vector_type: &VectorType,
58 vector_token: &str,
59 ) {
60 match vector_type {
61 VectorType::Bool => {
62 let mut bv = vec![];
63 for el in vector_token.split(",") {
64 if "1" == el || "true" == el {
65 bv.push(true);
66 } else if "0" == el || "false" == el {
67 bv.push(false);
68 } else {
69 return;
70 }
71 }
72 PushParser::rec_push(
73 &mut push_state.exec_stack,
74 Item::boolvec(BoolVector::new(bv)),
75 depth,
76 );
77 }
78 VectorType::Int => {
79 let mut iv = vec![];
80 for el in vector_token.split(",") {
81 match el.to_string().parse::<i32>() {
82 Ok(ival) => iv.push(ival),
83 Err(_) => return,
84 }
85 }
86 PushParser::rec_push(
87 &mut push_state.exec_stack,
88 Item::intvec(IntVector::new(iv)),
89 depth,
90 );
91 }
92 VectorType::Float => {
93 let mut fv = vec![];
94 for el in vector_token.split(",") {
95 match el.to_string().parse::<f32>() {
96 Ok(fval) => fv.push(fval),
97 Err(_) => return,
98 }
99 }
100 PushParser::rec_push(
101 &mut push_state.exec_stack,
102 Item::floatvec(FloatVector::new(fv)),
103 depth,
104 );
105 }
106 }
107 }
108
109 pub fn parse_program(push_state: &mut PushState, instruction_set: &InstructionSet, code: &str) {
112 let mut depth = 0;
113 for token in code.split_whitespace() {
114 if token.starts_with("INT[") {
115 PushParser::parse_vector(
116 push_state,
117 depth,
118 &VectorType::Int,
119 &token[4..token.len() - 1],
120 );
121 continue;
122 }
123 if token.starts_with("FLOAT[") {
124 PushParser::parse_vector(
125 push_state,
126 depth,
127 &VectorType::Float,
128 &token[6..token.len() - 1],
129 );
130 continue;
131 }
132 if token.starts_with("BOOL[") {
133 PushParser::parse_vector(
134 push_state,
135 depth,
136 &VectorType::Bool,
137 &token[5..token.len() - 1],
138 );
139 continue;
140 }
141 if "(" == token {
142 PushParser::rec_push(
143 &mut push_state.exec_stack,
144 Item::List {
145 items: PushStack::new(),
146 },
147 depth,
148 );
149 depth += 1;
151 continue;
152 }
153 if ")" == token {
154 depth -= 1;
156 continue;
157 }
158
159 if instruction_set.is_instruction(token) {
161 PushParser::rec_push(
162 &mut push_state.exec_stack,
163 Item::instruction(token.to_string()),
164 depth,
165 );
166 continue;
167 }
168 match token.to_string().parse::<i32>() {
170 Ok(ival) => {
171 PushParser::rec_push(&mut push_state.exec_stack, Item::int(ival), depth);
172 continue;
173 }
174 Err(_) => (),
175 }
176 match token.to_string().parse::<f32>() {
177 Ok(fval) => {
178 PushParser::rec_push(&mut push_state.exec_stack, Item::float(fval), depth);
179 continue;
180 }
181 Err(_) => (),
182 }
183
184 match token {
185 "TRUE" => {
186 PushParser::rec_push(&mut push_state.exec_stack, Item::bool(true), depth);
187 continue;
188 }
189 "FALSE" => {
190 PushParser::rec_push(&mut push_state.exec_stack, Item::bool(false), depth);
191 continue;
192 }
193 &_ => {
194 PushParser::rec_push(
195 &mut push_state.exec_stack,
196 Item::name(token.to_string()),
197 depth,
198 );
199 }
200 }
201 }
202 }
203}
204#[cfg(test)]
205mod tests {
206 use super::*;
207
208 #[test]
209 pub fn parse_simple_program() {
210 let input = "( 2 3 INTEGER.* 4.1 5.2 FLOAT.+ TRUE FALSE BOOLEAN.OR )";
211 let mut push_state = PushState::new();
212 let mut instruction_set = InstructionSet::new();
213 instruction_set.load();
214 PushParser::parse_program(&mut push_state, &instruction_set, &input);
215 assert_eq!(push_state.exec_stack.to_string(), "( 2 3 INTEGER.* 4.100 5.200 FLOAT.+ TRUE FALSE BOOLEAN.OR )");
216 }
217
218 #[test]
219 pub fn parse_potentiation_program() {
220 let input = "( ARG FLOAT.DEFINE EXEC.Y ( ARG FLOAT.* 1 INTEGER.- INTEGER.DUP 0 INTEGER.> EXEC.IF ( ) EXEC.POP ) ) ";
221 let mut push_state = PushState::new();
222 let mut instruction_set = InstructionSet::new();
223 instruction_set.load();
224 PushParser::parse_program(&mut push_state, &instruction_set, &input);
225 assert_eq!(
226 push_state.exec_stack.to_string(),
227 "( ARG FLOAT.DEFINE EXEC.Y ( ARG FLOAT.* 1 INTEGER.- INTEGER.DUP 0 INTEGER.> EXEC.IF ( ) EXEC.POP ) )"
228 );
229 }
230
231 #[test]
232 pub fn parse_factorial_program() {
233 let input = "( CODE.QUOTE ( CODE.DUP INTEGER.DUP 1 INTEGER.- CODE.DO INTEGER.* )
234 CODE.QUOTE ( INTEGER.POP 1 )
235 INTEGER.DUP 2 INTEGER.< CODE.IF )";
236 let mut push_state = PushState::new();
237 let mut instruction_set = InstructionSet::new();
238 instruction_set.load();
239 PushParser::parse_program(&mut push_state, &instruction_set, &input);
240 assert_eq!(
241 push_state.exec_stack.to_string(),
242 "( CODE.QUOTE ( CODE.DUP INTEGER.DUP 1 INTEGER.- CODE.DO INTEGER.* ) CODE.QUOTE ( INTEGER.POP 1 ) INTEGER.DUP 2 INTEGER.< CODE.IF )");
243 }
244
245 #[test]
246 pub fn parse_different_vector_types_with_correct_syntax() {
247 let input = "( BOOL[1,1,1,0,0] INT[2,345,-5] FLOAT[3.3,1.2,4.1] )";
248 let mut push_state = PushState::new();
249 let mut instruction_set = InstructionSet::new();
250 instruction_set.load();
251 PushParser::parse_program(&mut push_state, &instruction_set, &input);
252 assert_eq!(
253 push_state.exec_stack.to_string(),
254 "( [TRUE,TRUE,TRUE,FALSE,FALSE] [2,345,-5] [3.300,1.200,4.100] )"
255 );
256 }
257
258 #[test]
259 pub fn parse_different_vector_types_with_wrong_syntax() {
260 let input = "( BOOL[1,1,2,0,0] INT[2,345,-5.0] FLOAT[3.3,NANu,4.1] INT[1,2,3] )";
261 let mut push_state = PushState::new();
262 let mut instruction_set = InstructionSet::new();
263 instruction_set.load();
264 PushParser::parse_program(&mut push_state, &instruction_set, &input);
265 assert_eq!(
266 push_state.exec_stack.to_string(),
267 "( [1,2,3] )"
268 );
269 }
270}