From fdd2fa736155f9a1f5792dfd477b41d11ce21708 Mon Sep 17 00:00:00 2001 From: Sebastian Lohff Date: Mon, 3 Jan 2022 16:19:37 +0100 Subject: [PATCH] Initial commit --- .gitignore | 3 ++ Cargo.lock | 7 +++ Cargo.toml | 8 ++++ src/main.rs | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 149 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..355560c --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +*.swp +*.swo diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..e2fc507 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "brainfuck" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..a1564a8 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "brainfuck" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..9cfb749 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,131 @@ + +fn check_brainfuck(prog: &str) -> bool { + /* + let valid_bf_chars = "<>+-.,[]"; + for (n, c) in prog.char_indices() { + if ! valid_bf_chars.contains(c) { + println!("Invalid character '{}' on pos {}", c, n); + } + } + */ + let mut brackets = 0; + let mut borked = false; + for (n, c) in prog.char_indices() { + match c { + '[' => brackets += 1, + ']' => { + if brackets > 0 { + brackets -= 1; + } else { + println!("Closing bracket without matching opening bracket in pos {}", n); + borked = true; + } + }, + '<' | '>' | '+' | '-' | '.' | ',' => (), + _ => { + println!("Invalid character '{}' on pos {}", c, n); + borked = true; + }, + } + } + return ! borked; +} + +fn run_brainfuck(prog: &str, debug: bool) { + println!("Running programm {}", prog); + + let mut data = vec![]; + data.push(0); + let mut data_ptr = 0; + let mut pc = 0; + + loop { + let c = prog.chars().nth(pc).unwrap(); + if debug { + println!("At pos {} char {} with data {} at {} (data {:?})", pc, c, data[data_ptr], data_ptr, data); + } + let mut inc_pc = true; + match c { + '+' => data[data_ptr] += 1, + '-' => data[data_ptr] -= 1, + '>' => { + data_ptr += 1; + if data_ptr == data.len() { + data.push(0) + } + }, + '<' => { + if data_ptr > 0 { + data_ptr -= 1; + } else { + data.insert(0, 0); + } + }, + '.' => print!("{}", std::char::from_u32(data[data_ptr]).unwrap()), + ',' => println!(""), + '[' => { + if data[data_ptr] == 0 { + let mut brackets = 0; + loop { + match prog.chars().nth(pc).unwrap() { + '[' => brackets += 1, + ']' => { + brackets -= 1; + if brackets == 0 { + break; + } + }, + _ => (), + } + pc += 1; + } + inc_pc = false; + if debug { + println!("Executed conditional [ jump to pos {}", pc); + } + } + }, + ']' => { + if data[data_ptr] != 0 { + let mut brackets = 1; + loop { + pc -= 1; + match prog.chars().nth(pc).unwrap() { + ']' => brackets += 1, + '[' => { + brackets -= 1; + if brackets == 0 { + break; + } + }, + _ => (), + } + } + if debug { + println!("Executed conditional ] jump to pos {}", pc + 1); + } + } + } + _ => (), + } + + if inc_pc { + pc += 1 + } + if pc == prog.len() { + break; + } + } +} + +fn main() { + println!("Welcome to rust BF!"); + + //let prog = "xxx]]"; + let prog = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."; + if ! check_brainfuck(prog) { + println!("Invalid program, aborting"); + return; + } + run_brainfuck(prog, false); +}