« 日記 |Main| 日記 »

« | Brainf*ck | HaskellでBrainf*ck »

PythonによるBrainf*ckインタプリタ 1.01

PythonによるBrainf*ckインタプリタ @ NISHIO HIROKAZU # Archived COREBlogの改良版です。 便利な機能としては「入出力を数字にするモード(7を入力したいときに文字コード7のものを入れるとか、7の文字コードから0の文字コードを引くコードにしておく等の面倒なことが不要)」「ステップ実行」「メモリの内容表示」「#以降行末まではコメントになる」「コメント以外でもコードに使われる種類以外の文字は無視される」などです。

## 掛け算
,>,< # 2つ値を読み込む
[-  # [0]の回数だけブロック内を繰り返し
    >
    [->+>+<<]  # [1]の内容を[2], [3]に加算、[1]は0になる
    >>[-<<+>>] # [3]の内容を[1]に加算(移動)、[3]は0になる
    <<<
]
# -*- coding: cp932 -*-
#
# Brainf*ck Interpreter
#
import sys
IO_ORD = True

class BFInterpreter:
    pointer = 0
    caret = 0
    code = ""
    def __init__(self):
        self.command = {
            ">": self.incPtr,
            "<": self.decPtr,
            "+": self.incValue,
            "-": self.decValue,
            ".": self.putValue,
            ",": self.getValue,
            "[": self.jumpIfZero,
            "]": self.backJump
        }
        self.memSpace = {}

    def incPtr(self):
        self.pointer += 1
        self.caret += 1

    def decPtr(self):
        self.pointer -= 1
        self.caret += 1

    def incValue(self):
        ptr = self.pointer
        v = self.memSpace.get(ptr, 0)
        self.memSpace[ptr] = (v + 1) % 256
        self.caret += 1

    def decValue(self):
        ptr = self.pointer
        v = self.memSpace.get(ptr, 0)
        self.memSpace[ptr] = (v + 255) % 256
        self.caret += 1

    def putValue(self):
        value = self.memSpace.get(self.pointer, 0)
        if IO_ORD:
            print value,
        else:
            sys.stdout.write(chr(value))
        self.caret += 1

    def getValue(self):
        data = raw_input("bf>")
        if IO_ORD:
            self.memSpace[self.pointer] = int(data) % 256
        else:
            self.memSpace[self.pointer] = ord(data[0]) % 256
        self.caret += 1

    def jumpIfZero(self):
        if self.memSpace.get(self.pointer, 0) == 0:
            c = self.caret + 1
            depth = 1
            while c < len(self.code):
                cod = self.code[c]
                if cod == "]":
                    depth -= 1
                elif cod == "[":
                    depth += 1
                if depth == 0:
                    break
                c += 1
            else:
                raise RuntimeError
            self.caret = c + 1
        else:
            self.caret += 1

    def backJump(self):
        if self.memSpace.get(self.pointer, 0) != 0:
            c = self.caret - 1
            depth = 1
            while c != 0:
                cod = self.code[c]
                if cod == "]":
                    depth += 1
                elif cod == "[":
                    depth -= 1
                if depth == 0:
                    break
                c -= 1
            self.caret = c + 1
        else:
            self.caret += 1

    def stepCode(self):
        c = self.code[self.caret]
        self.command[c]()

    def runCode(self):
        while self.caret < len(self.code):
            self.stepCode()

    # util
    def showMem(self):
        ks = self.memSpace.keys()
        ks.sort()
        for k in ks:
            print k, self.memSpace[k]
            
    def simplify(self, source):
        code = ""
        for line in source.split("\n"):
            for c in line:
                if c == "#":
                    break
                elif c in "><+-,.[]":
                    code += c

        self.code = code

    def removeOpposite(self, source):
        code = ""
        code = self.simplify(source)
        while True:
            prev = code
            for p in ">< <> +- -+".split():
                code = code.replace(p, "")
            if prev == code:
                break

        self.code = code



bf = BFInterpreter()

bf.simplify("""
++++++++++
[                   # The initial loop to set up useful values in the array
   >+++++++>++++++++++>+++>+<<<<-
]
>++.                #print 'H'
>+.                 #print 'e'
+++++++.            #      'l'
.                   #      'l'
+++.                #      'o'
>++.                #      space
<<+++++++++++++++.  #      'W'
>.                  #      'o'
+++.                #      'r'
------.             #      'l'
--------.           #      'd'
>+.                 #      '!'
>.                  #      newline
""")

bf.runCode()

トラックバック(Trackback)

Trackback URL: http://www.nishiohirokazu.org/mt/mt-tb.cgi/148

ご意見・ご感想をお送りください(フィードバック)

(フィードバックはメールで送信され、基本的に表示されませんが、内容によっては公開させていただくこともございます。ご了承ください。Your comment doesn't appear the page immediately. If the comment has value to other people, it will be put on the page or subsequent entries. Thank you.)

上の情報は、いずれも未記入でかまいません。 All of above questions are optional.