Qwerty0

Brainfuck Interpreter

Apr 19th, 2013
45
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/perl -w
  2. =begin comment
  3.  
  4. A brainfuck interpreter.
  5.  
  6.     USAGE:
  7. Interactive:     Run script, paste code at prompt, enter EOF (Ctrl+D usually).
  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. and the program will read as much of it as it needs, when it needs.
  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. brackets have matching closing brackets and are properly nested.
  18.  
  19. Comment removal:
  20.   In the preparation phase, it removes all non-bf characters from the code, so
  21. extra formatting and comments have no impact on speed.
  22. NOTE: Valid bf characters are only the canonical eight: +-<>[],.
  23. Semi-official ones like # and ! will be removed.
  24.  
  25. Language implementation details:
  26.   Cell values are 0 to 255 with wrapping.
  27.   It uses 30000 memory cells with wrapping, as in the original implementation.
  28.  
  29. =end 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.   . "Usually this is Ctrl+D.\n";
  39. my @program;
  40. while (<>) {
  41.   s/[^+\-<>.,\[\]]//g;
  42.   my @line = split('', $_);
  43.   push(@program, @line);
  44. }
  45. print STDERR "\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.   if ($program[$counter] eq '+') {
  55.     $mem[$ptr] = ++$mem[$ptr] % 256;
  56.    
  57.   } elsif ($program[$counter] eq '-') {
  58.     $mem[$ptr] = --$mem[$ptr] % 256;
  59.    
  60.   } elsif ($program[$counter] eq '>') {
  61.     $ptr = ++$ptr % $MEMSIZE;
  62.    
  63.   } elsif ($program[$counter] eq '<') {
  64.     $ptr = --$ptr % $MEMSIZE;
  65.    
  66.   } elsif ($program[$counter] eq '.') {
  67.     if ($mem[$ptr]) {
  68.       print chr($mem[$ptr]);
  69.     }
  70.    
  71.   } elsif ($program[$counter] eq ',') {
  72.     unless(@bufferin) {          # fill input buffer
  73.       print "\n";
  74.       chomp(my $in = <STDIN>);
  75.       push(@bufferin, split('', $in));
  76.     }
  77.     $mem[$ptr] = ord(shift @bufferin);
  78.    
  79.   } elsif ($program[$counter] eq '[') {
  80.     unless ($mem[$ptr]) {
  81.       my $nested = 1;
  82.       until ($nested < 1) {
  83.         $counter++;
  84.         if ($program[$counter] eq '[') {
  85.           $nested++;
  86.         } elsif ($program[$counter] eq ']') {
  87.           $nested--;
  88.         }
  89.       }
  90.     }
  91.    
  92.   } elsif ($program[$counter] eq ']') {
  93.     if ($mem[$ptr]) {
  94.       my $nested = 1;
  95.       until ($nested < 1) {
  96.         $counter--;
  97.         if ($program[$counter] eq ']') {
  98.           $nested++;
  99.         } elsif ($program[$counter] eq '[') {
  100.           $nested--;
  101.         }
  102.       }
  103.     }
  104.   }
  105. }
RAW Paste Data