neutralts/bif/
parse_bif_for.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#![doc = include_str!("../../doc/bif-for.md")]

use crate::{bif::constants::*, bif::Bif, bif::BifError};

impl<'a> Bif<'a> {
    /*
       {:for; varname 1 10 >>
           var is:{:;varname:}
       :}
    */
    pub(crate) fn parse_bif_for(&mut self) -> Result<(), BifError> {
        if self.mod_filter || self.mod_negate {
            return Err(self.bif_error(BIF_ERROR_MODIFIER_NOT_ALLOWED));
        }

        self.extract_params_code(true);

        if !self.flags.is_empty() {
            return Err(self.bif_error(BIF_ERROR_FLAGS_NOT_ALLOWED));
        }

        self.params = self.params.replace("..", " ");
        let mut parts = self.params.split_whitespace();

        let var_name = match parts.next() {
            Some(value) => value.to_string(),
            None => {
                return Err(self.bif_error(BIF_ERROR_ARGUMENTS_NOT_FOUND));
            }
        };

        let from = match parts.next() {
            Some(value) => match value.parse::<i32>() {
                Ok(num) => num,
                Err(_) => {
                    return Err(self.bif_error(BIF_ERROR_ARGUMENT_NOT_NUMBER));
                }
            },
            None => {
                return Err(self.bif_error(BIF_ERROR_ARGS_FROM_TO_NOT_FOUND));
            }
        };

        let to = match parts.next() {
            Some(value) => match value.parse::<i32>() {
                Ok(num) => num,
                Err(_) => {
                    return Err(self.bif_error(BIF_ERROR_ARGUMENT_NOT_NUMBER));
                }
            },
            None => {
                return Err(self.bif_error(BIF_ERROR_ARGS_TO_NOT_FOUND));
            }
        };

        let range = if from > to {
            (to..=from).rev().collect::<Vec<i32>>()
        } else {
            (from..=to).collect::<Vec<i32>>()
        };

        let restore_var = self.get_data(&var_name);
        for i in range {
            self.set_data(&var_name, &i.to_string());
            self.out += &new_child_parse!(self, &self.code, self.mod_scope);
        }
        self.set_data(&var_name, &restore_var);

        Ok(())
    }
}

#[cfg(test)]
#[path = "parse_bif_for_tests.rs"]
mod tests;