about summary refs log tree commit diff stats
path: root/rust/bf/src/main.rs
diff options
context:
space:
mode:
authorelioat <{ID}+{username}@users.noreply.github.com>2024-09-20 17:15:11 -0400
committerelioat <{ID}+{username}@users.noreply.github.com>2024-09-20 17:15:11 -0400
commite010163faaca10c20d5301af99f1505bb361d5a9 (patch)
tree3a4aa4355743728bfe1aaf0eb31c18aeefd83b3b /rust/bf/src/main.rs
parent665ad1f48ddb4513272bfecb372651a4ea96d869 (diff)
downloadtour-e010163faaca10c20d5301af99f1505bb361d5a9.tar.gz
*
Diffstat (limited to 'rust/bf/src/main.rs')
-rw-r--r--rust/bf/src/main.rs91
1 files changed, 91 insertions, 0 deletions
diff --git a/rust/bf/src/main.rs b/rust/bf/src/main.rs
new file mode 100644
index 0000000..9257ae2
--- /dev/null
+++ b/rust/bf/src/main.rs
@@ -0,0 +1,91 @@
+use std::io::{self, Read};
+use std::env;
+use std::process;
+
+fn interpret_brainfuck(code: &str) {
+    let mut memory = vec![0u8; 30000]; // 30,000 cells of memory initialized to 0
+    let mut pointer: usize = 0; // data pointer starts at the first cell
+    let mut pc: usize = 0; // program counter for the Brainfuck code
+    let code_chars: Vec<char> = code.chars().collect(); // convert the Brainfuck code to a vector of characters
+
+    // Stack to keep track of [ and ] for loops
+    let mut loop_stack: Vec<usize> = Vec::new();
+
+    while pc < code_chars.len() {
+        match code_chars[pc] {
+            '>' => {
+                pointer += 1;
+                if pointer >= memory.len() {
+                    panic!("Pointer out of bounds");
+                }
+            }
+            '<' => {
+                if pointer == 0 {
+                    panic!("Pointer out of bounds");
+                }
+                pointer -= 1;
+            }
+            '+' => {
+                memory[pointer] = memory[pointer].wrapping_add(1); // increment with wrap around
+            }
+            '-' => {
+                memory[pointer] = memory[pointer].wrapping_sub(1); // decrement with wrap around
+            }
+            '.' => {
+                print!("{}", memory[pointer] as char);
+            }
+            ',' => {
+                let mut input = [0u8];
+                io::stdin().read_exact(&mut input).expect("Failed to read input");
+                memory[pointer] = input[0];
+            }
+            '[' => {
+                if memory[pointer] == 0 {
+                    // Jump to the matching ']' if the current cell is 0
+                    let mut open_brackets = 1;
+                    while open_brackets > 0 {
+                        pc += 1;
+                        if pc >= code_chars.len() {
+                            panic!("Unmatched [");
+                        }
+                        if code_chars[pc] == '[' {
+                            open_brackets += 1;
+                        } else if code_chars[pc] == ']' {
+                            open_brackets -= 1;
+                        }
+                    }
+                } else {
+                    // Push the current position to the stack if not jumping
+                    loop_stack.push(pc);
+                }
+            }
+            ']' => {
+                if memory[pointer] != 0 {
+                    // Jump back to the matching '[' if the current cell is nonzero
+                    if let Some(loop_start) = loop_stack.last() {
+                        pc = *loop_start;
+                    } else {
+                        panic!("Unmatched ]");
+                    }
+                } else {
+                    // Pop the stack if done with the loop
+                    loop_stack.pop();
+                }
+            }
+            _ => {} // Ignore any non-Brainfuck commands
+        }
+        pc += 1; // Move to the next instruction
+    }
+}
+
+fn main() {
+    let args: Vec<String> = env::args().collect();
+    if args.len() != 2 || !args[1].ends_with(".bf") {
+        eprintln!("Usage: {} <filename.bf>", args[0]);
+        process::exit(1);
+    }
+
+    let filename = &args[1];
+    let code = std::fs::read_to_string(filename).expect("Failed to read the file");
+    interpret_brainfuck(&code);
+}