Notice
Recent Posts
Recent Comments
NeuroWhAI의 잡블로그
[Rust] Brainfuck(브레인퍽) 구현 본문
use std::io::{self, Read};
mod bf {
use std::io::{self, Read};
#[derive(Default)]
pub struct Machine {
code: Vec<char>,
ram: Vec<u8>,
head: usize,
ptr: usize,
}
impl Machine {
pub fn new() -> Self {
Machine::default()
}
}
impl Machine {
pub fn initialize(&mut self, ram_size: usize) {
self.ram.resize(ram_size, 0);
}
pub fn mount(&mut self, code: &str) {
self.code = code.chars().collect();
}
pub fn step(&mut self) -> Result<bool, String> {
if self.head >= self.code.len() {
return Ok(true);
}
match self.code[self.head] {
'>' => {
// Increase ptr.
if self.ptr + 1 >= self.ram.len() {
return Err("the pointer is out of bound".into());
}
self.ptr += 1;
self.head += 1;
},
'<' => {
// Decrease ptr.
if self.ptr < 1 {
return Err("the pointer is out of bound".into());
}
self.ptr -= 1;
self.head += 1;
},
'+' => {
// Increase value that ptr points.
self.ram[self.ptr] = self.ram[self.ptr].wrapping_add(1);
self.head += 1;
},
'-' => {
// Decrease value that ptr points.
self.ram[self.ptr] = self.ram[self.ptr].wrapping_sub(1);
self.head += 1;
},
'.' => {
// Print value that ptr points.
print!("{}", char::from(self.ram[self.ptr]));
self.head += 1;
},
',' => {
// Read a byte from stream.
let mut buff = [0_u8];
let io_result = io::stdin().read_exact(&mut buff);
if let Err(err) = io_result {
return Err(err.to_string());
}
self.ram[self.ptr] = buff[0];
self.head += 1;
},
'[' => {
// Jump to matching ']' if value at ptr is zero
if self.ram[self.ptr] == 0 {
let mut depth = 0;
while self.head < self.code.len() {
let token = self.code[self.head];
if token == '[' {
depth += 1;
}
else if token == ']' {
depth -= 1;
if depth == 0 {
break;
}
}
self.head += 1;
}
if depth != 0 {
return Err("parentheses not found".into());
}
}
else {
self.head += 1;
}
},
']' => {
// Jump to matching '[' if value at ptr is not zero
if self.ram[self.ptr] != 0 {
let mut depth = 0;
while self.head > 0 {
let token = self.code[self.head];
if token == ']' {
depth += 1;
}
else if token == '[' {
depth -= 1;
if depth == 0 {
break;
}
}
self.head -= 1;
}
if depth != 0 {
return Err("parentheses not found".into());
}
}
else {
self.head += 1;
}
},
_ => { }
}
// is end?
Ok(self.head >= self.code.len())
}
}
}
fn main() -> io::Result<()> {
use crate::bf::Machine;
let mut code = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."
.to_string();
//io::stdin().read_to_string(&mut code)?;
let mut machine = Machine::new();
machine.initialize(256);
machine.mount(&code);
loop {
let result = machine.step();
match result {
Ok(true) => break,
Ok(false) => continue,
Err(msg) => {
eprintln!("error: {}", msg);
break;
},
}
}
Ok(())
}
실행 및 결과 확인 : https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b983021490480d828ff330be0a382691
Brainfuck(브레인퍽)은 유명한(?) 난해한 프로그래밍 언어 중 하나입니다.
비교적 구현이 쉽습니다.
뜬금없이 이걸 구현한 이유는 저도 모릅니다.
ㅌㅌ
'개발 및 공부' 카테고리의 다른 글
[Web] Node.js와 Socket.io로 멀티플레이 게임 개발 테스트 (2) | 2019.02.07 |
---|---|
[Web] Firebase로 메모 웹앱 개발 실습 (0) | 2019.01.27 |
수알못의 '딥 드림(Deep Dream)' 원리 파헤치기 (0) | 2019.01.07 |
크리스마스! 웹 어셈블리로 만든 눈 내리는 페이지 (0) | 2018.12.25 |
티스토리에 글 조회수를 표시하기 위한 개발자의 여정 기록 (0) | 2018.11.11 |
Comments