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
extern crate proc_macro;
use std::str::FromStr;
use std::str::from_utf8;
use proc_macro::TokenStream;
const CELL_SIZE: usize = 16;
fn parse(code: &str, cells: &mut [u8; CELL_SIZE], pc: &mut usize, output: &mut Vec<u8>) {
let mut idx = 0;
while idx < code.len() {
let c = code.as_bytes()[idx];
match c {
b'+' => cells[*pc] += 1,
b'-' => cells[*pc] -= 1,
b'>' => *pc += 1,
b'<' => *pc -= 1,
b'[' => {
while cells[*pc] != 0 {
parse(&code[idx+1..], cells, pc, output);
}
idx += code[idx..].find(']').unwrap();
},
b'.' => output.push(cells[*pc]),
b']' => return,
_ => {}
}
idx += 1;
}
}
#[proc_macro]
pub fn brain_fuck(_item: TokenStream) -> TokenStream {
let input = _item.to_string();
let mut cells: [u8; CELL_SIZE] = [0; CELL_SIZE];
let mut pc = 0;
let mut output = Vec::<u8>::new();
parse(&input, &mut cells, &mut pc, &mut output);
TokenStream::from_str(
&format!("\"{}\"", from_utf8(&output).unwrap())
).unwrap()
}