Skip to main content

brainfuck_plus_core/
parser.rs

1use std::process::exit;
2
3use crate::prelude::*;
4
5fn trim_tokens(i: &mut usize, tokens: &Vec<Token>, token_type: TokenType) -> Operation {
6    let mut count = 0;
7
8    let len: usize = tokens.len();
9
10    let mut values: Vec<String> = Vec::new();
11
12    let row = tokens[*i].row;
13    let col = tokens[*i].col;
14    let filename: String = tokens[*i].filename.clone();
15
16    while tokens[*i].token_type == token_type {
17        count += 1;
18        *i += 1;
19        values.push(tokens[*i].value.clone());
20        if *i >= len {
21            break;
22        }
23    }
24
25    Operation {
26        token_type,
27        count,
28        values,
29        tape: None,
30        row,
31        col,
32        filename,
33    }
34}
35
36#[must_use]
37pub fn parse_file(tokens: Vec<Token>, tapes: &[Tape]) -> Vec<Operation> {
38    let mut operations: Vec<Operation> = Vec::new();
39
40    let mut i: usize = 0;
41    let len: usize = tokens.len();
42
43    while i < len {
44        let token = tokens[i].clone();
45
46        match token.token_type {
47            TokenType::Add => operations.push(trim_tokens(&mut i, &tokens, token.token_type)),
48
49            TokenType::Sub => operations.push(trim_tokens(&mut i, &tokens, token.token_type)),
50
51            TokenType::PointerLeft => {
52                operations.push(trim_tokens(&mut i, &tokens, token.token_type))
53            }
54            TokenType::BitwiseLeft => {
55                operations.push(trim_tokens(&mut i, &tokens, token.token_type))
56            }
57            TokenType::BitwiseRight => {
58                operations.push(trim_tokens(&mut i, &tokens, token.token_type))
59            }
60
61            TokenType::PointerRight => {
62                operations.push(trim_tokens(&mut i, &tokens, token.token_type))
63            }
64
65            TokenType::Push => operations.push(trim_tokens(&mut i, &tokens, token.token_type)),
66
67            TokenType::Pop => operations.push(trim_tokens(&mut i, &tokens, token.token_type)),
68
69            TokenType::CurrentTape => {
70                i += 1;
71                let tape_name = tokens[i].clone();
72                if tape_name.token_type != TokenType::TapeName {
73                    println!(
74                        "{}:{}:{} CurrentTape: Expected tape name after operation got {}",
75                        token.filename,
76                        token.row,
77                        token.col + 1,
78                        tape_name.value
79                    );
80                    exit(1);
81                }
82
83                let tape = {
84                    let mut tape: Option<Tape> = None;
85                    for tapem in tapes {
86                        if tapem.name == tape_name.value {
87                            tape = Some(tapem.clone());
88                            break;
89                        }
90                    }
91
92                    tape
93                };
94
95                if tape.is_none() {
96                    println!(
97                        "{}:{}:{} Tape {} not defined",
98                        token.filename,
99                        token.col,
100                        token.row + 1,
101                        tape_name.value
102                    );
103                    exit(1);
104                }
105
106                operations.push(Operation {
107                    token_type: token.token_type,
108                    count: 1,
109                    values: vec![token.value],
110                    tape,
111                    row: token.row,
112                    col: token.col,
113                    filename: token.filename,
114                });
115                i += 1;
116            }
117
118            _ => {
119                operations.push(Operation {
120                    token_type: token.token_type,
121                    count: 1,
122                    values: vec![token.value],
123                    tape: None,
124                    row: token.row,
125                    col: token.col,
126                    filename: token.filename,
127                });
128                i += 1;
129            }
130        }
131    }
132
133    operations
134}