blob: 42ce61f3d5ffec5958997039f09b8c5137a5ca34 [file]
<?php
/**
* PHP Brainf*ck compiler
* (c) Kristian Hole 2006
*
* License:
* --
* This code is licensed under the Beerware License.
* As long as you keep this notice, do whatever you want with the code.
* If you like it, buy the author a beer.
* Kristian Hole 2006
* --
*
* RB: The code is adapted, so that it works as CustomBlock.
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
**/
class BrainFuck implements ezcTemplateCustomBlock, ezcTemplateCustomFunction
{
public static function getCustomBlockDefinition( $name )
{
switch ( $name )
{
case "brainfuck":
$def = new ezcTemplateCustomBlockDefinition();
$def->class = __CLASS__;
$def->method = "emulate";
$def->hasCloseTag = true;
$def->requiredParameters = array();
$def->optionalParameters = array("buffer_size");
return $def;
case "bf":
$def = new ezcTemplateCustomBlockDefinition();
$def->class = __CLASS__;
$def->method = "emulate_inline";
$def->hasCloseTag = false;
$def->startExpressionName = "code";
$def->requiredParameters = array("code");
$def->optionalParameters = array("buffer_size");
return $def;
}
}
public static function getCustomFunctionDefinition( $name )
{
switch ( $name )
{
case "brainfuck":
$def = new ezcTemplateCustomFunctionDefinition();
$def->class = __CLASS__;
$def->method = "bfFunction";
$def->parameters = array( "code", "[buffer_size]" );
return $def;
}
}
public static function bfFunction( $code, $bufferSize = 1000 )
{
return eval( self::compile( $code, "", $bufferSize ) );
}
public static function emulate( $parameters, $code )
{
if ( !isset( $parameters["buffer_size"] ) ) $parameters["buffer_size"] = 1000;
return eval( self::compile( $code, "", $parameters["buffer_size"] ) );
}
public static function emulate_inline( $parameters)
{
if ( !isset( $parameters["buffer_size"] ) ) $parameters["buffer_size"] = 1000;
return eval( self::compile( $parameters["code"], "", $parameters["buffer_size"] ) );
}
public static function compile( $code, $input = '', $bufsize = 1000 )
{
$phpcode = <<<ENDL
\$data = array();
\$pointer = 0;
\$bufsize = $bufsize;
for ( \$i = 0; \$i < \$bufsize; \$i++)
\$data[\$i]=0;
\$input='$input';
\$inputcounter=0;
\$result = '';
ENDL;
$length = strlen( $code );
for ( $ip = 0; $ip < $length; $ip++ )
{
switch ( $code[ $ip ] )
{
case '<': $phpcode .= '$pointer++; $pointer = ( $pointer % $bufsize ); ' ."\n"; break;
case '>': $phpcode .= '$pointer = ( $pointer > 1 ? $pointer-1 : $pointer+$bufsize-1 );' ."\n"; break;
case '+': $phpcode .= '$data[$pointer]++; $data[$pointer] = $data[$pointer] % 255; ' ."\n"; break;
case '-': $phpcode .= '$data[$pointer] = ( $data[$pointer] > 0 ? $data[$pointer]-1 : $data[$pointer]+255 );' ."\n"; break;
case '.': $phpcode .= '$result .= chr( $data[$pointer] );' ."\n"; break;
case ',': $phpcode .= '$data[$pointer]= ( $inputcounter < strlen( $input) ? ord( $input[$inputcounter] ) : 0 ); $inputcounter++;' ."\n"; break;
case '[': $phpcode .= 'while ($data[$pointer]) {' ."\n"; break;
case ']': $phpcode .= '}' ."\n"; break;
default: // echo "unknown instruction $code[$ip]\n";
}
}
$phpcode .= 'return $result;';
return $phpcode;
}
}
?>