Execute Brain****/Python: Difference between revisions

From Rosetta Code
Content added Content deleted
(Neater code, (almost) infinite tape, 'exit' opcode (']' outside of any loop).)
Line 1: Line 1:
{{implementation|Brainf***}}{{collection|RCBF}}
{{implementation|Brainf***}}{{collection|RCBF}}


Quick implementation of a [[Brainfuck]] interpreter in [[Python]].
Implementation of a [[Brainfuck]] interpreter in [[Python]].


<lang python>#!/usr/bin/python
<lang python>#!/usr/bin/python
import sys
import collections


def brainfuck (filename=None):
from __future__ import with_statement
fd = filename or (open(sys.argv[1]) if sys.argv[1:] else sys.stdin)

source = fd.read()
import sys
loop_ptrs = {}
loop_stack = []
for ptr, opcode in enumerate(source):
if opcode == '[': loop_stack.append(ptr)
if opcode == ']':
if not loop_stack:
source = source[:ptr]
break
sptr = loop_stack.pop()
loop_ptrs[ptr], loop_ptrs[sptr] = sptr, ptr
if loop_stack:
raise SyntaxError ("unclosed loops at {}".format(loop_stack))
tape = collections.defaultdict(int)
cell = 0
ptr = 0
while ptr < len(source):
opcode = source[ptr]
if opcode == '>': cell += 1
elif opcode == '<': cell -= 1
elif opcode == '+': tape[cell] += 1
elif opcode == '-': tape[cell] -= 1
elif opcode == ',': tape[cell] = ord(sys.stdin.read(1))
elif opcode == '.': sys.stdout.write(chr(tape[cell]))
elif (opcode == '[' and tape[cell]) or \
(opcode == ']' and not tape[cell]): ptr = loop_ptrs[ptr]
ptr += 1


if __name__ == "__main__": brainfuck()</lang>
class BrainFuck():
def __init__(self):
self.instructions = ''
def main(self):
if len(sys.argv[1:]) > 0:
source_file = sys.argv[1]
with open(source_file) as source_handle:
self.instructions = source_handle.read()
else:
print >> sys.stderr, 'No source file.'
sys.exit(2)
self.match_braces()
def match_braces(self):
loops = {}
loop_stack = []
for ptr, instruction in enumerate(self.instructions):
if instruction == '[':loop_stack.append(ptr)
elif instruction == ']':loops[ptr],loops[loops[ptr]] = loop_stack.pop(),ptr
self.start_interpreting(loops)
def start_interpreting(self, loops):
tape = [0] * 30000
cell = 0
pointer = 0
while pointer < len(self.instructions):
instruction = self.instructions[pointer]
if instruction == '>':
cell += 1
elif instruction == '<':
cell -= 1
elif instruction == '+':
tape[cell] += 1
elif instruction == '-':
tape[cell] -= 1
elif instruction == ',':
tape[cell] = ord(sys.stdin.read(1))
elif instruction == '.':
sys.stdout.write(chr(tape[cell]))
elif instruction == '[' and tape[cell] == 0:
pointer = loops[pointer]
elif instruction == ']' and tape[cell] != 0:
pointer = loops[pointer]
pointer += 1
if __name__ == "__main__":
interpreter = BrainFuck()
interpreter.main()</lang>

Revision as of 22:17, 12 February 2011

Execute Brain****/Python is an implementation of Brainf***. Other implementations of Brainf***.
Execute Brain****/Python is part of RCBF. You may find other members of RCBF at Category:RCBF.

Implementation of a Brainfuck interpreter in Python.

<lang python>#!/usr/bin/python import sys import collections

def brainfuck (filename=None):

   fd = filename or (open(sys.argv[1]) if sys.argv[1:] else sys.stdin)
   source = fd.read()
   loop_ptrs = {}
   loop_stack = []
   for ptr, opcode in enumerate(source):
       if opcode == '[': loop_stack.append(ptr)
       if opcode == ']':
           if not loop_stack:
               source = source[:ptr]
               break
           sptr = loop_stack.pop()
           loop_ptrs[ptr], loop_ptrs[sptr] = sptr, ptr
   if loop_stack:
       raise SyntaxError ("unclosed loops at {}".format(loop_stack))
   tape = collections.defaultdict(int)
   cell = 0
   ptr = 0
   while ptr < len(source):
       opcode = source[ptr]
       if   opcode == '>': cell += 1
       elif opcode == '<': cell -= 1
       elif opcode == '+': tape[cell] += 1
       elif opcode == '-': tape[cell] -= 1
       elif opcode == ',': tape[cell] = ord(sys.stdin.read(1))
       elif opcode == '.': sys.stdout.write(chr(tape[cell]))
       elif (opcode == '[' and tape[cell]) or \
            (opcode == ']' and not tape[cell]): ptr = loop_ptrs[ptr]
       ptr += 1

if __name__ == "__main__": brainfuck()</lang>