LoginSignup
1
0

More than 5 years have passed since last update.

brainf*ck

Last updated at Posted at 2017-04-01

rustの練習がてらbrainf*ckを実装してみた
簡単すぎて練習にならなかったのは内緒

use std::env;
use std::io;
use std::io::Read;
use std::u16;
use std::char;

fn main() {
  let mut args = env::args();
  if args.len() != 2 {
    println!("usage: <expr>");
  }
  else {
    brainfuck(args.nth(1).unwrap());
  }
}

fn brainfuck(text: String) {
  let bytes = text.as_bytes(); // 扱いやすいように[u8]へ変換
  let mut pos: usize = 0; // プログラムの位置
  let mut pointer: usize = 0; // brainfuckが保持するポインタ
  let mut values: [u32; u16::MAX as usize] = [0; u16::MAX as usize]; // brainfuckが保持する配列 

  while pos < bytes.len() {
    match bytes[pos] {

      // ポインタをインクリメント
      b'>' => {
        pointer += 1;
      },

      // ポインタをデクリメント
      b'<' => {
        if pointer > 0 {
          pointer -= 1;
        }
      },

      // ポインタが指す値をインクリメント
      b'+' => {
        values[pointer] += 1;
      },

      // ポインタが指す値をデクリメントする
      b'-' => {
        values[pointer] -= 1;
      },

      // ポインタが指す値を出力に書き出す
      b'.' => {
        if let Some(c) = char::from_u32(values[pointer]) {
          print!("{}", c);
        }
        else {
          print!("?");
        }
      }

      // 入力から1バイト読み込んで、ポインタが指す先に代入する
      b',' => {
        values[pointer] = io::stdin().bytes().nth(0).unwrap().unwrap() as u32;
      }

      // ポインタが指す値が0なら、対応する ] の直後にジャンプする
      b'[' => {
        if values[pointer] == 0 {
          let mut level = 0; // ネストした[]に対応するために使用
          let mut p = pos;

          loop {
            p += 1;

            if bytes[p] == b'[' {
              level += 1;
            }
            else if bytes[p] == b']' {
              if level == 0 {
                pos = p;
                break;
              }
              else {
                level -= 1;
              }
            }
          }
        }
      },

      // ポインタが指す値が0でないなら、対応する [ の直後にジャンプする
      b']' => {
        if values[pointer] != 0 {
          let mut level = 0; // ネストした[]に対応するために使用
          let mut p = pos;

          loop {
            p -= 1;

            if bytes[p] == b']' {
              level += 1;
            }
            else if bytes[p] == b'[' {
              if level == 0 {
                pos = p;
                break;
              }
              else {
                level -= 1;
              }
            }
          }
        }
      },

      // それ以外はエラー
      b => {
        println!("brainfuck unexpect {}", b);
        break;
      }
    }

    // プログラムを進める
    pos += 1;
  }
}

Hello, world!

ちゃんと動いたよ!よかったね!

cargo run '+++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-.------------.<++++++++.--------.+++.------.--------.>+.'

Hello, world!
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0