Skip to main content

bf_derivatives_tools/
parser.rs

1use super::grammar::*;
2use super::token::*;
3use regex;
4use regex::Regex;
5
6pub struct Parser {
7    code: String,
8}
9
10impl Parser {
11    pub fn new(code: &str) -> Self {
12        Self {
13            code: code.to_string(),
14        }
15    }
16
17    pub fn code(&self) -> String {
18        self.code.clone()
19    }
20
21    pub fn translate_to_bf(&mut self, from: &Grammar) {
22        let to = Grammar::bf();
23        self.translate(from, &to);
24    }
25
26    pub fn translate_from_bf(&mut self, to: &Grammar) {
27        let from = Grammar::bf();
28        self.translate(&from, &to);
29    }
30
31    pub fn translate(&mut self, from: &Grammar, to: &Grammar) {
32        let pattern = Parser::make_pattern(from);
33        let translated = Regex::new(&pattern)
34            .unwrap()
35            .find_iter(&self.code)
36            .map(|mat| {
37                let s = mat.as_str();
38                if s == from.rshift {
39                    &to.rshift
40                } else if s == from.lshift {
41                    &to.lshift
42                } else if s == from.inc {
43                    &to.inc
44                } else if s == from.dec {
45                    &to.dec
46                } else if s == from.write {
47                    &to.write
48                } else if s == from.read {
49                    &to.read
50                } else if s == from.loop_begin {
51                    &to.loop_begin
52                } else if s == from.loop_end {
53                    &to.loop_end
54                } else if s == " " || s == "\t" || s == "\n" || s == "\r\n" {
55                    s
56                } else {
57                    ""
58                }
59            })
60            .collect::<String>();
61        self.code = translated;
62    }
63
64    fn make_pattern(grammar: &Grammar) -> String {
65        let rshift = regex::escape(&grammar.rshift);
66        let lshift = regex::escape(&grammar.lshift);
67        let inc = regex::escape(&grammar.inc);
68        let dec = regex::escape(&grammar.dec);
69        let write = regex::escape(&grammar.write);
70        let read = regex::escape(&grammar.read);
71        let loop_begin = regex::escape(&grammar.loop_begin);
72        let loop_end = regex::escape(&grammar.loop_end);
73        format!(
74            "{}|{}|{}|{}|{}|{}|{}|{}|\x20|\t|\n|\r\n",
75            rshift, lshift, inc, dec, write, read, loop_begin, loop_end
76        )
77    }
78
79    pub fn parse(&self) -> Vec<Token> {
80        let tokens: Vec<_> = self
81            .code
82            .chars()
83            .map(|c| match c {
84                '>' => Token::RShift,
85                '<' => Token::LShift,
86                '+' => Token::Inc,
87                '-' => Token::Dec,
88                '.' => Token::Write,
89                ',' => Token::Read,
90                '[' => Token::LoopBegin,
91                ']' => Token::LoopEnd,
92                _ => Token::Ignore,
93            })
94            .collect();
95        tokens
96    }
97}