/Template/docs/examples/brainfuck/brainfuck.php

https://github.com/F5/zetacomponents · PHP · 131 lines · 85 code · 14 blank · 32 comment · 7 complexity · 82998c56a435148787c34ceac5371e24 MD5 · raw file

  1. <?php
  2. /**
  3. * PHP Brainf*ck compiler
  4. * (c) Kristian Hole 2006
  5. *
  6. * License:
  7. * --
  8. * This code is licensed under the Beerware License.
  9. * As long as you keep this notice, do whatever you want with the code.
  10. * If you like it, buy the author a beer.
  11. * Kristian Hole 2006
  12. * --
  13. *
  14. * RB: The code is adapted, so that it works as CustomBlock.
  15. *
  16. * Licensed to the Apache Software Foundation (ASF) under one
  17. * or more contributor license agreements. See the NOTICE file
  18. * distributed with this work for additional information
  19. * regarding copyright ownership. The ASF licenses this file
  20. * to you under the Apache License, Version 2.0 (the
  21. * "License"); you may not use this file except in compliance
  22. * with the License. You may obtain a copy of the License at
  23. *
  24. * http://www.apache.org/licenses/LICENSE-2.0
  25. *
  26. * Unless required by applicable law or agreed to in writing,
  27. * software distributed under the License is distributed on an
  28. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  29. * KIND, either express or implied. See the License for the
  30. * specific language governing permissions and limitations
  31. * under the License.
  32. *
  33. **/
  34. class BrainFuck implements ezcTemplateCustomBlock, ezcTemplateCustomFunction
  35. {
  36. public static function getCustomBlockDefinition( $name )
  37. {
  38. switch ( $name )
  39. {
  40. case "brainfuck":
  41. $def = new ezcTemplateCustomBlockDefinition();
  42. $def->class = __CLASS__;
  43. $def->method = "emulate";
  44. $def->hasCloseTag = true;
  45. $def->requiredParameters = array();
  46. $def->optionalParameters = array("buffer_size");
  47. return $def;
  48. case "bf":
  49. $def = new ezcTemplateCustomBlockDefinition();
  50. $def->class = __CLASS__;
  51. $def->method = "emulate_inline";
  52. $def->hasCloseTag = false;
  53. $def->startExpressionName = "code";
  54. $def->requiredParameters = array("code");
  55. $def->optionalParameters = array("buffer_size");
  56. return $def;
  57. }
  58. }
  59. public static function getCustomFunctionDefinition( $name )
  60. {
  61. switch ( $name )
  62. {
  63. case "brainfuck":
  64. $def = new ezcTemplateCustomFunctionDefinition();
  65. $def->class = __CLASS__;
  66. $def->method = "bfFunction";
  67. $def->parameters = array( "code", "[buffer_size]" );
  68. return $def;
  69. }
  70. }
  71. public static function bfFunction( $code, $bufferSize = 1000 )
  72. {
  73. return eval( self::compile( $code, "", $bufferSize ) );
  74. }
  75. public static function emulate( $parameters, $code )
  76. {
  77. if ( !isset( $parameters["buffer_size"] ) ) $parameters["buffer_size"] = 1000;
  78. return eval( self::compile( $code, "", $parameters["buffer_size"] ) );
  79. }
  80. public static function emulate_inline( $parameters)
  81. {
  82. if ( !isset( $parameters["buffer_size"] ) ) $parameters["buffer_size"] = 1000;
  83. return eval( self::compile( $parameters["code"], "", $parameters["buffer_size"] ) );
  84. }
  85. public static function compile( $code, $input = '', $bufsize = 1000 )
  86. {
  87. $phpcode = <<<ENDL
  88. \$data = array();
  89. \$pointer = 0;
  90. \$bufsize = $bufsize;
  91. for ( \$i = 0; \$i < \$bufsize; \$i++)
  92. \$data[\$i]=0;
  93. \$input='$input';
  94. \$inputcounter=0;
  95. \$result = '';
  96. ENDL;
  97. $length = strlen( $code );
  98. for ( $ip = 0; $ip < $length; $ip++ )
  99. {
  100. switch ( $code[ $ip ] )
  101. {
  102. case '<': $phpcode .= '$pointer++; $pointer = ( $pointer % $bufsize ); ' ."\n"; break;
  103. case '>': $phpcode .= '$pointer = ( $pointer > 1 ? $pointer-1 : $pointer+$bufsize-1 );' ."\n"; break;
  104. case '+': $phpcode .= '$data[$pointer]++; $data[$pointer] = $data[$pointer] % 255; ' ."\n"; break;
  105. case '-': $phpcode .= '$data[$pointer] = ( $data[$pointer] > 0 ? $data[$pointer]-1 : $data[$pointer]+255 );' ."\n"; break;
  106. case '.': $phpcode .= '$result .= chr( $data[$pointer] );' ."\n"; break;
  107. case ',': $phpcode .= '$data[$pointer]= ( $inputcounter < strlen( $input) ? ord( $input[$inputcounter] ) : 0 ); $inputcounter++;' ."\n"; break;
  108. case '[': $phpcode .= 'while ($data[$pointer]) {' ."\n"; break;
  109. case ']': $phpcode .= '}' ."\n"; break;
  110. default: // echo "unknown instruction $code[$ip]\n";
  111. }
  112. }
  113. $phpcode .= 'return $result;';
  114. return $phpcode;
  115. }
  116. }
  117. ?>