A PHP implement for Brainfuck Compiler
<?php
/**
Brainfuck Compiler on PHP
Copyright 2015 Everstray Jun Sinri Edogawa
**/
$bc=new BrainfuckCompiler();
$bc->compile(
'++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.'
);
/**
字符 含义
> 指针加一
< 指针减一
+ 指针指向的字节的值加一
- 指针指向的字节的值减一
. 输出指针指向的单元内容(ASCII码)
, 输入内容到指针指向的单元(ASCII码)
[ 如果指针指向的单元值为零,向后跳转到对应的]指令的次一指令处
] 如果指针指向的单元值不为零,向前跳转到对应的[指令的次一指令处
*/
class BrainfuckCompiler
{
public static $PTR_RIGHT ='>';
public static $PTR_LEFT ='<';
public static $VAL_PLUS ='+';
public static $VAL_MINUS = '-';
public static $PTR_OUTPUT = '.';
public static $PTR_INPUT = ',';
public static $WHILE_BEGIN = '[';
public static $WHILE_END = ']';
public static $DEBUG_MODE=false;
private $ptr=0;
private $memory=array(-1=>0,0=>0,1=>0);
private $codes=array();
private $code_index=0;
public function compile($program_code){
$this->codes=str_split($program_code);
$this->code_index=0;
while($this->code_index<count($this->codes)){
$this->process_code();
}
}
private function process_code(){
if(BrainfuckCompiler::$DEBUG_MODE){
echo "[DEBUG] process_code at ".$this->code_index;
}
$code=$this->codes[$this->code_index];
if(BrainfuckCompiler::$DEBUG_MODE){
echo " as ".$code.PHP_EOL;
}
if($code===BrainfuckCompiler::$PTR_RIGHT){
$this->act_ptr_right();
$this->code_index+=1;
}
elseif($code===BrainfuckCompiler::$PTR_LEFT){
$this->act_ptr_left();
$this->code_index+=1;
}
elseif($code===BrainfuckCompiler::$VAL_PLUS){
$this->act_val_plus();
$this->code_index+=1;
}
elseif($code===BrainfuckCompiler::$VAL_MINUS){
$this->act_val_minus();
$this->code_index+=1;
}
elseif($code===BrainfuckCompiler::$PTR_OUTPUT){
$this->act_ptr_output();
$this->code_index+=1;
}
elseif($code===BrainfuckCompiler::$PTR_INPUT){
$this->act_ptr_input($this->codes[$this->code_index+1]);
$this->code_index+=2;
}
elseif($code===BrainfuckCompiler::$WHILE_BEGIN){
$this->act_while_begin();
}
elseif($code===BrainfuckCompiler::$WHILE_END){
$this->act_while_end();
}
}
private function act_ptr_right(){
$this->ptr+=1;
if(!isset($this->memory[$this->ptr])){
$this->memory[$this->ptr]=0;
}
}
private function act_ptr_left(){
$this->ptr-=1;
if(!isset($this->memory[$this->ptr])){
$this->memory[$this->ptr]=0;
}
}
private function act_val_plus(){
$this->memory[$this->ptr]=($this->memory[$this->ptr]+1)%256;
}
private function act_val_minus(){
$this->memory[$this->ptr]=($this->memory[$this->ptr]-1)%256;
}
private function act_ptr_output(){
echo chr($this->memory[$this->ptr]);
}
private function act_ptr_input($value){
$this->memory[$this->ptr]=($value%256);
}
private function act_while_begin(){
if($this->memory[$this->ptr]===0){
//find the pair WHILE_END
$pair=1;
$i=0;
for($i=$this->code_index+1;$i<count($this->codes);$i++){
if($this->codes[$i]===BrainfuckCompiler::$WHILE_BEGIN){
$pair+=1;
}elseif($this->codes[$i]===BrainfuckCompiler::$WHILE_END){
$pair-=1;
}
if($pair==0){
//here it is
break;
}
}
$this->code_index=$i;
}else{
$this->code_index+=1;
}
}
private function act_while_end(){
if($this->memory[$this->ptr]!==0){
//find the pair WHILE_BEGIN
$pair=1;
$i=0;
for($i=$this->code_index-1;$i>=0;$i--){
if($this->codes[$i]===BrainfuckCompiler::$WHILE_END){
$pair+=1;
}elseif($this->codes[$i]===BrainfuckCompiler::$WHILE_BEGIN){
$pair-=1;
}
if($pair==0){
//here it is
break;
}
}
$this->code_index=$i+1;
}else{
$this->code_index+=1;
}
}
}
?>