brainfuck/
brainfuck.rs

1use std::io::{BufRead, BufReader, Bytes, Read};
2
3use parse_it::ParseIt;
4
5#[derive(Debug, Clone)]
6pub enum Instr {
7    Left,
8    Right,
9    Incr,
10    Decr,
11    Read,
12    Write,
13    Loop(Vec<Self>),
14}
15
16parse_it::parse_it! {
17    #[parser]
18    mod parse {
19        use super::Instr;
20
21        type Lexer = parse_it::CharLexer;
22
23        pub Brainfuck -> Vec<Instr> {
24            Primitive* => self,
25        }
26
27        Primitive -> Instr {
28            '<' => Instr::Left,
29            '>' => Instr::Right,
30            '+' => Instr::Incr,
31            '-' => Instr::Decr,
32            ',' => Instr::Read,
33            '.' => Instr::Write,
34            '[' Primitive+ ']' => Instr::Loop(self)
35        }
36    }
37}
38
39fn main() {
40    let parser = parse::Brainfuck::default();
41    let src = "--[>--->->->++>-<<<<<-------]>--.>---------.>--..+++.>----.>+++++++++.<<.+++.------.<-.>>+.";
42
43    match parser.parse(src) {
44        Ok(ast) => {
45            let mut stdin = BufReader::new(std::io::stdin().lock()).bytes();
46            execute(&ast, &mut 0, &mut [0; TAPE_LEN], &mut stdin)
47        }
48        Err(err) => println!("{err:?}"),
49    };
50}
51
52const TAPE_LEN: usize = 10_000;
53
54fn execute(
55    ast: &[Instr],
56    ptr: &mut usize,
57    tape: &mut [u8; TAPE_LEN],
58    stdin: &mut Bytes<impl BufRead>,
59) {
60    for symbol in ast {
61        match symbol {
62            Instr::Left => *ptr = (*ptr + TAPE_LEN - 1).rem_euclid(TAPE_LEN),
63            Instr::Right => *ptr = (*ptr + 1).rem_euclid(TAPE_LEN),
64            Instr::Incr => tape[*ptr] = tape[*ptr].wrapping_add(1),
65            Instr::Decr => tape[*ptr] = tape[*ptr].wrapping_sub(1),
66            Instr::Read => tape[*ptr] = stdin.next().unwrap().unwrap(),
67            Instr::Write => print!("{}", tape[*ptr] as char),
68            Instr::Loop(ast) => {
69                while tape[*ptr] != 0 {
70                    execute(ast, ptr, tape, stdin)
71                }
72            }
73        }
74    }
75}