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 | + |