Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Brainfuck Interpreter

by o(o_o)o (Scribe)
on Mar 13, 2002 at 05:45 UTC ( #151319=CUFP: print w/replies, xml ) Need Help??

well... i think this is cool even if you don't :p ... I've become interested in the esoteric languages Brainfuck and Befunge after getting enthusiastic about Obfuscated code, and have decided to make this Perl-Module which interprets Brainfuck code so that i can put brainfuck bit's into my programs for no reason but bordom ;)

i'm very happy with it.. i've tested it quite a bit and am very confident on it's accuracy, but if someone finds something wrong with it i shall aim to fix the problem :) It was quite easy to implement really, but i'm a newbie/rubbish programmer :p The only hard bit was the iteration step which i rightfully took as recursion..

usage:
use Brainfuck; bf_execute(">++++[<++++>-]<+++[->++++<]+ ++[>---<-]++[>+.<-]>[>+>+<<- ]>----.>-.>++++[<+++>-]<--.< .[-]+++++++[->+<]>.-."); or bf_load_sourcefile("asourcefile.b"); bf_execute();
here's the code:
package Brainfuck; use strict; use vars qw($VERSION @ISA @EXPORT); @ISA = qw(Exporter); @EXPORT = qw( &bf_load_sourcefile &bf_execute ); $VERSION = 0.01; #setup the stack & global code scalar my @stack; my $stack_ptr = 0; my $thecode; #load a brainfuck sourcefile into the #interpreter sub bf_load_sourcefile { $thecode = ""; open(BF, "@_[0]") || return 0; while(<BF>) { $thecode .= $_; } close(BF); } #execute the given code either given into #this sub, or given by $thecode if no #params are passed to it. sub bf_execute { my $code; if(@_) { $code = shift; } else { $code = $thecode; } $code =~ s/\n|\s//g; my @chars = split(//, $code); my $index = 0; while($index<@chars) { $_ = @chars[$index]; if($_ eq "+") { @stack[$stack_ptr]++; } elsif($_ eq "-") { --@stack[$stack_ptr]; } elsif($_ eq "<") { $stack_ptr-- unless $stack_ptr == 0; } elsif($_ eq ">") { $stack_ptr++; } elsif($_ eq ".") { print chr(@stack[$stack_ptr]); } elsif($_ eq ",") { @stack[$stack_ptr] = ord(<>); } elsif($_ eq "[") { my $end = match_bracket($index, @chars); my $temp_ptr = $stack_ptr; while(@stack[$temp_ptr] > 0) { my $fragment; my $frag_index=$index+1; while($frag_index < $end ) { $fragment .= @chars[$frag_index]; $frag_index++; } #recursively call execute on the code #within the []s bf_execute($fragment); } #make the stack_ptr what it was before the iteration step $stack_ptr = $temp_ptr; $index = $end; } $index++; } } ############################ #private sub used by execute #to match up the open square #brackets with the close one sub match_bracket { my $index = shift; $index++; my @chars = @_; my $num_bracket = 1; while(1) { if(@chars[$index] eq "[") { $num_bracket++; } if(@chars[$index] eq "]" && $num_bracket == 1) { last; } elsif(@chars[$index] eq "]" && $num_bracket != 1) { $num_bracket--; } $index++; } return $index; } 1;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
i would slit my wrists for you

Replies are listed 'Best First'.
Re: Brainfuck Interpreter
by Juerd (Abbot) on Mar 13, 2002 at 08:11 UTC

    Have a look at my Brainf*ck interpreter :).
    Please note that not all Brainf*ck programs will work with our implementation, because the original brainfuck:

    • Has 30000 values
    • Has a single byte per value
    Perl makes it easy to make both those things unlimited, but that means that if $array[$pointer] is 255, + will set it to 256, instead of 0. It also means that if $pointer is 29999, the next one will be 30000, not 0.

    And of course, @_[0] is better written as $_[0] but -w probably already told you. (Further, it isn't smart to interpolate if the end result will be the exact same string, and it might be nice to use the new 3-argument open() for safety)

    Next point of comment: <> will wait for $/, while , is supposed to get just a single character.

    U28geW91IGNhbiBhbGwgcm90MTMgY
    W5kIHBhY2soKS4gQnV0IGRvIHlvdS
    ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
    geW91IHNlZSBpdD8gIC0tIEp1ZXJk
    

      @_[0] is better written as $_[0]

      That depends on your definition of "better". If you're writing code to parse a language which is deliberately confusing, it's arguably better to parse it in as confusing a way as possible.

      I found this parser really easy to understand - why not write an obfuscated parser for obfuscated code? ;-)

      Update: Perhaps I need to make it clear that I'm not being entirely serious. It's certainly a bad idea to use the side effects of an array slice in real code. On the other hand, if you want to do something confusing, do it in the most confused way possible!

        That depends on your definition of "better".

        2;0 juerd@ouranos:~$ perl -we'@_[0]' Scalar value @_[0] better written as $_[0] at -e line 1.
        That's my definition. @_[0] is an array slice, which happens to have a single value, and just happens to work because of that. For example:
        my @foo = qw(a b c d e f g h i j); my @bar = @foo[1, 5, 6, 4]; # @bar is now qw(b f g e) my $bar = $foo[0];
        When you want a scalar, USE a scalar :)

        If you're writing code to parse a language which is deliberately confusing, it's arguably better to parse it in as confusing a way as possible.

        Perhaps, but I don't agree. And even if you were right, there's no need to use PERL for that. (note: "PERL" ne "Perl").

        U28geW91IGNhbiBhbGwgcm90MTMgY
        W5kIHBhY2soKS4gQnV0IGRvIHlvdS
        ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
        geW91IHNlZSBpdD8gIC0tIEp1ZXJk
        

      I'm gonna take that stuff into consideration when implement .02 which will hopefully have load of cool features which i was thinking about when i wrote the code, but didn't implement in v.01...

      i'll add in all the restraints on the language too like the size of the buffer, and the single byte per value...

      my intention for "," as input was to have <> trap whatever the user input but it will only push the first character of the string inputted onto the stack... but i'll make it trap only 1 character in the future..

      Thanks very much for your help o(o_o)o

      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      i would slit my wrists for you

        another thing ;)... i know most people think that it should maybe be written obfu'd, but that wasn't really my way of thinking... i set out to write an interpreter which will be easy to understand so that modifications could easily be made to 1)make the code better, 2)add extra features and make extra commands(ie.another language), 3)allow easy integration of more functions of the interpreter such as debugging and stepover. but i see where u lot are all coming from ;)

        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        i would slit my wrists for you
Re: Brainfuck Interpreter
by patgas (Friar) on Mar 13, 2002 at 16:49 UTC

    Perhaps you could write this to be compatible with Inline? Seems like a logical step to me...

    "As information travels faster in the modern age, as our days are crawling by so slowly." -- DCFC

      Apparently not on CPAN yet, there is an Inline BrainF*** module available here1.

      broquaint

      1 link courtesy of miyagawa in this node.

Re: Brainfuck Interpreter
by kluzz (Initiate) on Apr 18, 2002 at 10:21 UTC
    Great! Now write a perl-to-brainf*** translator... :)
Re: Brainfuck Interpreter
by Bobcat (Scribe) on Apr 04, 2002 at 03:10 UTC
    I'd love to take credit for a shorter interpreter, but I can't.

    Check here instead.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: CUFP [id://151319]
Approved by root
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (4)
As of 2018-01-18 02:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    How did you see in the new year?










    Results (206 votes). Check out past polls.

    Notices?