| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- <?php
- /**
- * Soros interpreter
- *
- * @see http://numbertext.org
- * @author Pavel Astakhov <pastakhov@yandex.ru>
- * @license LGPL/BSD dual license
- * @copyright (c) 2009-2010, László Németh
- */
- class Soros {
- private $patterns = [];
- private $values = [];
- private $begins = [];
- private $ends = [];
- private $m;
- private $m2;
- private $c;
- private $c2;
- private $slash;
- private $pipe;
- private $func;
- private $numbertext = false;
- /**
- * Constructor.
- * @param string $source
- */
- public function __construct($source) {
- $this->m = [
- "\\",
- "\"",
- ";",
- "#"];
- $this->m2 = [
- "$",
- "(",
- ")",
- "|"];
- $this->c = [
- json_decode('"\uE000"'),
- json_decode('"\uE001"'),
- json_decode('"\uE002"'),
- json_decode('"\uE003"'),
- ];
- $this->c2 = [
- json_decode('"\uE004"'),
- json_decode('"\uE005"'),
- json_decode('"\uE006"'),
- json_decode('"\uE007"'),
- ];
- $this->slash = [json_decode('"\uE000"')];
- $this->pipe = [json_decode('"\uE003"')];
- $source = self::translate($source, $this->m, $this->c, "\\");
- $source = preg_replace("/(#[^\n]*)?(\n|$)/", ";", $source);
- if (strpos($source, "__numbertext__") !== false) {
- $this->numbertext = true;
- $source = str_replace("__numbertext__", "0+(0|[1-9]\\d*) $1\n", $source);
- }
- foreach (split(";", $source) as $s) {
- if ($s != "" && preg_match("/^\\s*(\"[^\"]*\"|[^\\s]*)\\s*(.*[^\\s])?\\s*$/", $s, $sp) > 0) {
- $s = self::translate(preg_replace("/\"$/", "", preg_replace("/^\"/", "", $sp[1], 1), 1), $this->c, $this->m, "");
- $s = str_replace($this->slash[0], "\\\\", $s);
- $s2 = "";
- if (isset($sp[2]))
- $s2 = preg_replace("/\"$/", "", preg_replace("/^\"/", "", $sp[2], 1), 1);
- $s2 = self::translate($s2, $this->m2, $this->c2, "\\");
- $s2 = preg_replace("/(\\$\\d|\\))\\|\\$/", "$1||\\$", $s2);
- $s2 = self::translate($s2, $this->c, $this->m, "");
- $s2 = self::translate($s2, $this->m2, $this->c, "");
- $s2 = self::translate($s2, $this->c2, $this->m2, "");
- $s2 = preg_replace("/[$]/", "\\$", $s2); // $ -> \$
- $s2 = preg_replace("/" . $this->c[0] . "(\\d)/", $this->c[0] . $this->c[1] . "\\$$1" . $this->c[2], $s2); // $n -> $(\n)
- $s2 = preg_replace("/\\\\(\\d)/", "\\$$1", $s2); // \[n] -> $[n]
- $s2 = preg_replace("/\\n/", "\n", $s2); // \n -> [new line]
- $this->patterns[] = "^" . preg_replace("/\\$$/", "", preg_replace("/^\\^/", "", $s, 1), 1) . "$";
- $this->begins[] = (mb_substr($s, 0, 1) == "^");
- $this->ends[] = (mb_substr($s, -1) == "$");
- $this->values[] = $s2;
- }
- }
- $this->func = self::translate("(?:\\|?(?:\\$\\()+)?" . "(\\|?\\$\\(([^\\(\\)]*)\\)\\|?)" . "(?:\\)+\\|?)?", $this->m2, $this->c, "\\");
- }
- /**
- *
- * @param string $input
- * @return string
- */
- public function run($input) {
- if (!$this->numbertext)
- return $this->run3($input, true, true);
- return preg_replace("/ +/", " ", trim($this->run3($input, true, true)));
- }
- /**
- *
- * @param string $input
- * @param string $begin
- * @param string $end
- * @return string
- */
- private function run3($input, $begin, $end) {
- $count = count($this->patterns);
- for ($i = 0; $i < $count; $i++) {
- if ((!$begin && $this->begins[$i]) || (!$end && $this->ends[$i]))
- continue;
- if (!preg_match("/" . $this->patterns[$i] . "/", $input, $m))
- continue;
- $s = preg_replace("/" . $this->patterns[$i] . "/", $this->values[$i], $m[0]);
- preg_match_all("/" . $this->func . "/u", $s, $n, PREG_OFFSET_CAPTURE);
- while (count($n[0]) > 0) {
- // n.start() n.group() n.start(1) n.group(1) n.start(2) n.group(2)
- //MWDebug::log( $n[0][0][1] . "=>" . $n[0][0][0] . ", " . $n[1][0][1] . "=>" . $n[1][0][0] . ", " . $n[2][0][1] . "=>" . $n[2][0][0] );
- $b = false;
- $e = false;
- if (mb_substr($n[1][0][0], 0, 1) == $this->pipe[0] || mb_substr($n[0][0][0], 0, 1) == $this->pipe[0]) {
- $b = true;
- } elseif ($n[0][0][1] == 0) {
- $b = $begin;
- }
- if (mb_substr($n[1][0][0], -1) == $this->pipe[0] || mb_substr($n[0][0][0], -1) == $this->pipe[0]) {
- $e = true;
- } elseif ($n[0][0][1] + strlen($n[0][0][0]) == strlen($s))
- $e = $end;
- $s = substr($s, 0, $n[1][0][1]) . $this->run3($n[2][0][0], $b, $e) . substr($s, $n[1][0][1] + strlen($n[1][0][0]));
- preg_match_all("/" . $this->func . "/u", $s, $n, PREG_OFFSET_CAPTURE);
- }
- return $s;
- }
- return "";
- }
- /**
- *
- * @param string $s
- * @param string $chars
- * @param string $chars2
- * @param string $delim
- * @return string
- */
- private static function translate($s, $chars, $chars2, $delim) {
- $count = count($chars);
- for ($i = 0; $i < $count; $i++) {
- $s = str_replace($delim . $chars[$i], $chars2[$i], $s);
- }
- return $s;
- }
- }
|