Před časem jsem se dozvěděl o minimalistickém programovacím jazyce Brainfuck. Přestože má jenom osm příkazů, které se navíc zapisují jedním znakem a je tedy extrémně snadný na naučení a používání, tak na něj asi nepřejdu. Napsal jsem si tedy alespoň interpret tohoto jazyka v PHP:
<?php $code = "++++++++[>+++++++++<-]>.<+++++[>++++++<-]>-.+++++++..+++.<++++++++[>>++++<<-]>>.<<++++[>------<-]>.<++++[>++++++<-]>.+++.------.--------.>+."; $buffer = ""; $pos = 0; $while = array(); // array($i, ...) for ($i=0; $i < strlen($code); $i++) { switch ($code[$i]) { case '>': $pos++; break; case '<': $pos--; break; case '+': $buffer[$pos] = chr(ord($buffer[$pos]) + 1); break; case '-': $buffer[$pos] = chr(ord($buffer[$pos]) - 1); break; case '.': echo $buffer[$pos]; break; case ',': $buffer[$pos] = fgetc(STDIN); break; case '[': if (ord($buffer[$pos])) $while[] = $i; else for ($depth=1; $depth; $i++) { if ($code[$i+1] == '[') $depth++; elseif ($code[$i+1] == ']') $depth--; } break; case ']': $i = array_pop($while) - 1; break; default: echo "Unrecognized character.\n"; exit(1); } } ?>
Skript je přímočarý – v řetězci $code
je uložen kód programu v Brainfucku, tímto řetězcem se prochází přes proměnnou $i
, zásobník while cyklu je uložen v proměnné $while
, obsah pásky v $buffer
a pozice na této pásce je uložena v $pos
. Chyby v Brainfuck kódu nejsou ošetřeny, takže např. při chybějící pravé závorce se program může dostat do nekonečné smyčky. Za všimnutí možná stojí, že pro přímý přístup k jednotlivým znakům řetězce se používají složené závorky a že znak se načítá ze streamu STDIN (standardní vstup otevřený v PHP-cli). Zneužívá se faktu, že při přístupu ke znaku na neexistující pozici řetězce se s ním zachází jako s prázdným řetězcem.\0
Ošetření příkazu ]
tupě ukončí cyklus a vrátí běh na [
, který cyklus v závislosti na obsahu pásky případně opět spustí. Optimalizovat by se to dalo tak, že by podmínku testoval už ]
:
<?php switch ($code[$i]) { case ']': if (ord($buffer[$pos])) $i = end($while); else array_pop($while); break; } ?>
Diskuse je zrušena z důvodu spamu.