SHOW:
|
|
- or go back to the newest paste.
| 1 | #!/usr/bin/perl -w | |
| 2 | - | #brainfuck.pl |
| 2 | + | |
| 3 | ||
| 4 | A brainfuck interpreter. | |
| 5 | ||
| 6 | USAGE: | |
| 7 | - | USAGE: |
| 7 | + | |
| 8 | Non-Interactive: Run script with brainfuck program file as command line option. | |
| 9 | ||
| 10 | Input buffer: | |
| 11 | Uses an input buffer so that you can enter an entire line of text at a time | |
| 12 | - | Uses an input buffer so that you can enter an entire line of text at a time |
| 12 | + | |
| 13 | NOTE: Since you use "enter" to submit a line, there's no way to enter newlines. | |
| 14 | ||
| 15 | Use valid code: | |
| 16 | This doesn't check the brainfuck code for validity. It assumes all open | |
| 17 | - | This doesn't check the brainfuck code for validity. It assumes all open |
| 17 | + | |
| 18 | ||
| 19 | Comment removal: | |
| 20 | In the preparation phase, it removes all non-bf characters from the code, so | |
| 21 | - | In the preparation phase, it removes all non-bf characters from the code, |
| 21 | + | extra formatting and comments have no impact on speed. |
| 22 | - | so extra formatting and comments have no impact on speed. |
| 22 | + | NOTE: Valid bf characters are only the canonical eight: +-<>[],. |
| 23 | - | NOTE: Valid bf characters are only the canonical eight: +-<>[],. |
| 23 | + | |
| 24 | ||
| 25 | Language implementation details: | |
| 26 | Cell values are 0 to 255 with wrapping. | |
| 27 | - | Cell values are 0 to 255 with wrapping. |
| 27 | + | It uses 30000 memory cells with wrapping, as in the original implementation. |
| 28 | - | It uses 30000 memory cells with wrapping, as in the original implementation. |
| 28 | + | |
| 29 | =end comment | |
| 30 | - | =cut comment |
| 30 | + | =cut |
| 31 | use strict; | |
| 32 | ||
| 33 | # Number of memory cells | |
| 34 | my $MEMSIZE = 30_000; | |
| 35 | ||
| 36 | # Read in program, remove comments, turn into array of characters | |
| 37 | print STDERR "Enter brainfuck code, then an EOF character to signal the end.\n" | |
| 38 | - | print "Enter brainfuck code, then an EOF character to signal the end.\n" . |
| 38 | + | . "Usually this is Ctrl+D.\n"; |
| 39 | - | "Usually this is Ctrl+D.\n"; |
| 39 | + | |
| 40 | while (<>) {
| |
| 41 | s/[^+\-<>.,\[\]]//g; | |
| 42 | - | s/[^+\-<>.,\[\]]//g; |
| 42 | + | my @line = split('', $_);
|
| 43 | - | my @line = split('', $_);
|
| 43 | + | push(@program, @line); |
| 44 | - | push(@program, @line); |
| 44 | + | |
| 45 | print STDERR "\n=====Program Output=====\n"; | |
| 46 | - | print "\n=====Program Output=====\n"; |
| 46 | + | |
| 47 | # MAIN PARSING AND EXECUTION LOOP | |
| 48 | ||
| 49 | my $ptr = 0; | |
| 50 | my @mem = (); | |
| 51 | my @bufferin = (); | |
| 52 | for (my $counter = 0; $counter < @program; $counter++) {
| |
| 53 | ||
| 54 | - | |
| 54 | + | if ($program[$counter] eq '+') {
|
| 55 | - | if ($program[$counter] eq '+') {
|
| 55 | + | $mem[$ptr] = ++$mem[$ptr] % 256; |
| 56 | - | $mem[$ptr] = ++$mem[$ptr] % 256; |
| 56 | + | |
| 57 | - | |
| 57 | + | } elsif ($program[$counter] eq '-') {
|
| 58 | - | } elsif ($program[$counter] eq '-') {
|
| 58 | + | $mem[$ptr] = --$mem[$ptr] % 256; |
| 59 | - | $mem[$ptr] = --$mem[$ptr] % 256; |
| 59 | + | |
| 60 | - | |
| 60 | + | } elsif ($program[$counter] eq '>') {
|
| 61 | - | } elsif ($program[$counter] eq '>') {
|
| 61 | + | $ptr = ++$ptr % $MEMSIZE; |
| 62 | - | $ptr = ++$ptr % $MEMSIZE; |
| 62 | + | |
| 63 | - | |
| 63 | + | } elsif ($program[$counter] eq '<') {
|
| 64 | - | } elsif ($program[$counter] eq '<') {
|
| 64 | + | $ptr = --$ptr % $MEMSIZE; |
| 65 | - | $ptr = --$ptr % $MEMSIZE; |
| 65 | + | |
| 66 | - | |
| 66 | + | } elsif ($program[$counter] eq '.') {
|
| 67 | - | } elsif ($program[$counter] eq '.') {
|
| 67 | + | if ($mem[$ptr]) {
|
| 68 | - | if ($mem[$ptr]) {
|
| 68 | + | print chr($mem[$ptr]); |
| 69 | - | print chr($mem[$ptr]); |
| 69 | + | } |
| 70 | - | } |
| 70 | + | |
| 71 | - | |
| 71 | + | } elsif ($program[$counter] eq ',') {
|
| 72 | - | } elsif ($program[$counter] eq ',') {
|
| 72 | + | unless(@bufferin) { # fill input buffer
|
| 73 | - | unless(@bufferin) { # fill input buffer
|
| 73 | + | print "\n"; |
| 74 | - | print "\n"; |
| 74 | + | chomp(my $in = <STDIN>); |
| 75 | - | chomp(my $in = <STDIN>); |
| 75 | + | push(@bufferin, split('', $in));
|
| 76 | - | push(@bufferin, split('', $in));
|
| 76 | + | } |
| 77 | - | } |
| 77 | + | $mem[$ptr] = ord(shift @bufferin); |
| 78 | - | $mem[$ptr] = ord(shift @bufferin); |
| 78 | + | |
| 79 | - | |
| 79 | + | } elsif ($program[$counter] eq '[') {
|
| 80 | - | } elsif ($program[$counter] eq '[') {
|
| 80 | + | unless ($mem[$ptr]) {
|
| 81 | - | unless ($mem[$ptr]) {
|
| 81 | + | my $nested = 1; |
| 82 | - | my $nested = 1; |
| 82 | + | until ($nested < 1) {
|
| 83 | - | until ($nested < 1) {
|
| 83 | + | $counter++; |
| 84 | - | $counter++; |
| 84 | + | if ($program[$counter] eq '[') {
|
| 85 | - | if ($program[$counter] eq '[') {
|
| 85 | + | $nested++; |
| 86 | - | $nested++; |
| 86 | + | } elsif ($program[$counter] eq ']') {
|
| 87 | - | } elsif ($program[$counter] eq ']') {
|
| 87 | + | $nested--; |
| 88 | - | $nested--; |
| 88 | + | } |
| 89 | - | } |
| 89 | + | } |
| 90 | - | } |
| 90 | + | } |
| 91 | - | } |
| 91 | + | |
| 92 | - | |
| 92 | + | } elsif ($program[$counter] eq ']') {
|
| 93 | - | } elsif ($program[$counter] eq ']') {
|
| 93 | + | if ($mem[$ptr]) {
|
| 94 | - | if ($mem[$ptr]) {
|
| 94 | + | my $nested = 1; |
| 95 | - | my $nested = 1; |
| 95 | + | until ($nested < 1) {
|
| 96 | - | until ($nested < 1) {
|
| 96 | + | $counter--; |
| 97 | - | $counter--; |
| 97 | + | if ($program[$counter] eq ']') {
|
| 98 | - | if ($program[$counter] eq ']') {
|
| 98 | + | $nested++; |
| 99 | - | $nested++; |
| 99 | + | } elsif ($program[$counter] eq '[') {
|
| 100 | - | } elsif ($program[$counter] eq '[') {
|
| 100 | + | $nested--; |
| 101 | - | $nested--; |
| 101 | + | } |
| 102 | - | } |
| 102 | + | } |
| 103 | - | } |
| 103 | + | } |
| 104 | - | } |
| 104 | + | } |
| 105 | - | |
| 105 | + |