Qwerty0

Brainfuck Interpreter

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