Brainf*ck in Python
箱根駅伝を見ながら、Python で brainf*ck インタプリタを実装してみました。
すでに偉大なる Pythonista 達の手により行われていること*1ではあるのですが、あえて車輪の再実装です。
インタプリタのコード (bf.py)
# -*- coding:utf-8 -*- import sys from array import array from optparse import OptionParser def bf_eval(expr, debug): loop_begin_ptr = [] loop_end_ptr = [] # 最初に "[", "]" の位置を走査 for i, token in enumerate(expr): if token == '[': loop_begin_ptr.append(i) elif token == ']': loop_end_ptr.append(i) # 構文解析 # 仕様 - http://ja.wikipedia.org/wiki/Brainfuck memory = array('b', [0]*256) ptr = 0; i = 0 while i < len(expr): token = expr[i] if token == '>': ptr += 1 elif token == '<': ptr -= 1 elif token == '+': memory[ptr] += 1 elif token == '-': memory[ptr] -= 1 elif token == '.': sys.stdout.write(chr(memory[ptr])) elif token == ',': memory[ptr] = sys.stdin.read(1) elif token == '[': if memory[ptr] == 0: i = loop_end_ptr[loop_begin_ptr.index(i)] + 1 elif token == ']': if memory[ptr] != 0: i = loop_begin_ptr[loop_end_ptr.index(i)] else: raise SyntaxError, i if debug: print " ptr=%s" % ptr, memory[:16] # dump i += 1 if __name__ == '__main__': usage = 'bf.py [source-file]' version = '%prog 0.0.1' parser = OptionParser(usage=usage, version=version) parser.add_option( '-d', '--debug', action='store_true', help=u'1ステップごとにバイト配列をダンプします。とりあえず先頭16バイトのみ。', ) options, args = parser.parse_args() if len(args) == 0: print u'ファイルが指定されていません。' sys.exit() buf = open(args[0]).read() if options.debug: bf_eval(buf, True) else: bf_eval(buf, False)
実行するソースコード (bf_hny.txt)
+++++++++[>++++++++>+++++++++++>+++++<<<-]>.>--.+++++++++++++++..+++++++++.>-------------.<-----------.<+++++++++++++++++++++++++++++.>+++++++++.>.<++.<.----.+++++++++++++++++.>>+.
実行結果
C:\Documents and Settings\takanori\junks>python bf.py bf_hny.txt Happy new year!
でた!