/brainfuck.php
https://github.com/nbartels/php-brainfuck · PHP · 136 lines · 69 code · 17 blank · 50 comment · 16 complexity · 2feb458e9d917dae1140e023d37269bb MD5 · raw file
- <?php
-
- /*
- Brainfuck interpreter Class
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- */
-
- class Brainfuck {
-
- protected $data = array();
- protected $data_index = 0;
- protected $source_index = 0;
- protected $input_index = 0;
- protected $output = '';
- protected $input = null;
- protected $source = null;
-
- function __construct() {
- $this->data[0] = chr(0);
- }
-
- public function setSource($source) {
- $this->source = $source;
- }
-
- public function setInput($input) {
- $this->input = $input;
- }
-
- public function getOutput() {
- return $this->output;
- }
-
- public function execute() {
- $this->brainfuck_interpret($this->source, $this->source_index, $this->data, $this->data_index, $this->input, $this->input_index, $this->output);
- return $this;
- }
-
- /* Debug function displays valuable debug information.
- Rewrite this if desired.
-
- $s, $_s Source string and pointer (current position)
- $d, $_d Data array and pointer
- $i, $_i Input string and pointer
- $o Output string
-
- */
-
- protected function brainfuck_debug(&$s, &$_s, &$d, &$_d, &$i, &$_i, &$o) {
- foreach ($d as $element => $value) {
- echo $element . "\t" . ord($value) . "\t" . (ord($value) >= 32 ? htmlentities($value) : " ") . "\n";
- }
- }
-
- /*
- Brainfuck interpreter in PHP
- Copyright (C) 2002 Daniel Lorch
- */
-
- protected function brainfuck_interpret(&$s, &$_s, &$d, &$_d, &$i, &$_i, &$o) {
- do {
- switch ($s[$_s]) {
- /* Execute brainfuck commands. Values are not stored as numbers, but as their
- representing characters in the ASCII table. This is perfect, as chr(256) is
- automagically converted to chr(0). */
- case '+': $d[$_d] = chr(ord($d[$_d]) + 1);
- break;
- case '-': $d[$_d] = chr(ord($d[$_d]) - 1);
- break;
- case '>': $_d++;
- if (!isset($d[$_d]))
- $d[$_d] = chr(0); break;
- case '<': $_d--;
- break;
-
- /* Output is stored in a variable. Change this to
- echo $d[$_d]; flush();
- if you would like to have a "live" output (when running long calculations, for example.
- Or if you are just terribly impatient). */
- case '.': $o .= $d[$_d];
- break;
-
- /* Due to PHP's non-interactive nature I have the whole input passed over in a string.
- I successively read characters from this string and pass it over to BF every time a
- ',' command is executed. */
- case ',': $d[$_d] = $_i == strlen($i) ? chr(0) : $i[$_i++];
- break;
-
- /* Catch loops */
- case '[':
- /* Skip loop (also nested ones) */
- if ((int) ord($d[$_d]) == 0) {
- $brackets = 1;
- while ($brackets && $_s++ < strlen($s)) {
- if ($s[$_s] == '[')
- $brackets++;
- else if ($s[$_s] == ']')
- $brackets--;
- }
- }
- /* Execute loop */
- else {
- $pos = $_s++ - 1;
- /* The closing ] returns true when the loop has to be executed again. If so, then return
- to the $pos(ition) where the opening [ is. */
- if ($this->brainfuck_interpret($s, $_s, $d, $_d, $i, $_i, $o))
- $_s = $pos;
- }
- break;
- /* Return true when loop has to be executed again. It is redundant to the [ checking, but
- it will save some parsing time (otherwise the interpreter would have to return to [ only
- to skip all characters again) */
- case ']': return ((int) ord($d[$_d]) != 0);
- /* Call debug function */
- case '#': $this->brainfuck_debug($s, $_s, $d, $_d, $i, $_i, $o);
- }
- } while (++$_s < strlen($s));
- }
-
- }
-
- ?>