Brainfuck Language Specification
This is a quote from Wikipedia.
The interpreter consists of the following elements: a Brainfuck program, an instruction pointer (pointing to a character in the program), an array of at least 30000 bytes (each element initialized to zero), a data pointer (pointing to one of the elements in the array, initialized to point to the leftmost element), and two byte streams for input and output. A Brainfuck program consists of 8 executable instructions (other characters are ignored and skipped):
Increment the pointer. Equivalent to C’s “ptr++;”.
- < Decrement the pointer. Equivalent to C’s “ptr–;”.
- Increment the value at the pointer. Equivalent to C’s “(*ptr)++;”.
- Decrement the value at the pointer. Equivalent to C’s “(*ptr)–;”.
- . Output the value at the pointer. Equivalent to C’s “putchar(*ptr);”.
- , Read one byte from input and assign it to the pointer. Equivalent to C’s “*ptr=getchar();”.
- [ If the value at the pointer is 0, jump to the instruction after the corresponding ]. Equivalent to C’s “while(*ptr){”.
- ] If the value at the pointer is not 0, jump to the corresponding [ (right after it[1]). Equivalent to C’s “}"[2].
Implementation
I used Ruby. The “[” and “]” parts are still difficult.
#!/usr/bin/env ruby
class BrainFuck
def set(program)
@pc = 0 # Program pointer
@pro = program # Program
@mar = 0 # Memory address register
@mem = Array.new(30000,0) # Memory (30000 Bytes)
end
def step()
# Fetch opcode
op = @pro[@pc]
@pc+=1
# Execute
case op
when ">"
@mar+=1
when "<"
@mar-=1
when "+"
@mem[@mar]+=1
when "-"
@mem[@mar]-=1
when "."
print @mem[@mar].chr
when "["
if @mem[@mar] == 0
depth = 0
(@pc..@pro.length).each do |i|
# Found matching bracket
if depth == 0 && @pro[i] == "]"
@pc = i+1
break
# Check depth
elsif @pro[i] == "["
depth+=1
elsif @pro[i] == "]"
depth-=1
end
end
end
when "]"
if @mem[@mar]!=0
depth = 0
(0..@pc-2).reverse_each do |i|
# Found matching bracket
if depth == 0 && @pro[i] == "["
@pc = i+1
break
# Check depth
elsif @pro[i] == "]"
depth+=1
elsif @pro[i] == "["
depth-=1
end
end
end
end
end
def exec()
while @pc!=@pro.length
step
end
print "\n"
end
end
brainfuck = BrainFuck.new
while line = gets
brainfuck.set(line)
brainfuck.exec
end
Test
This is Brainfuck programming in action. Please add execution permissions before playing. Also, since it reads line by line, it’s bad if there are newline codes in the brainfuck code.
$ ./brainfuck.rb
+++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-.------------.<++++++++.--------.+++.------.--------.>+.
Hello, world!
++++++++++[>++++++++++>+++++++++++>++++++++++++>++++++++++>++++++++++>+++++++++++<<<<<<-]>--.>+.<.>>---.>++++.>+++++.>++++.<<<<.
bobuhiro