/** * @param string */ static function parse_string($src) { // src must begin with an opening php tag to tokenize properly if (substr($src, 0, 2) !== '<?') { $src = "<?php\n" . $src; } // use native tokenizer $tokens = token_get_all($src); // remove opening tag while also checking for tokenizer bug $opentag = array_shift($tokens); if ($opentag[0] !== T_OPEN_TAG) { trigger_error("Tokenizer error: T_OPEN_TAG expected, got " . print_r($opentag, 1), E_USER_ERROR); } // construct and parse $Parser = new IncParser(); return $Parser->parse($tokens); }
/** * @internal * @param array token for directive, e.g. [T_STRING,'import'] * @param array all tokens with pointer at start of statement * @param bool * @return string source to substitute for statement */ private function handle_inc_statement(array $tok, array &$tokens, $path) { $func = $tok[1]; // gather entire statement up to next `;' // warning: if you do something like "import() or die();" parsing will fail. $src = $tok[1]; $inctokens = array($tok); $pathargs = array(); while ($inctok = next($tokens)) { $inctokens[] = $inctok; $src .= is_scalar($inctok) ? $inctok : $inctok[1]; if ($inctok === ';') { break; } } // hand off to any special cases switch ($func) { case 'import_return_value': return $this->import_return_value($src); } // The remaining directives require compilation of simple string arguments. // Attempt parse - will throw on error ... $Compiler = new IncParser(); try { $Stat = $Compiler->parse($inctokens); // ensure current __FILE__ reference is correct as it may be referenced in include statement $consts = $this->conf_consts; $consts['__FILE__'] = $path; $pathargs = $Stat->get_args($consts, $this->conf_vars); } catch (Exception $Ex) { trigger_error("Failed to parse `{$func}' directive in `{$path}', line {$tok[2]}: " . $Ex->getMessage(), E_USER_WARNING); // return empty statement with commented error in case of error return sprintf('/* Failed to parse %s directive */;', $func); } // process all arguments according to directive type $src = ''; foreach ($pathargs as $arg) { $arg = cleanpath($arg); switch ($func) { case 'import': $s = $this->compile_import($arg); break; case 'include': case 'require': case 'include_once': case 'require_once': $s = $this->compile_php($arg, $func); break; case 'virtual': $s = $this->compile_virtual($arg); break; } // handle error if no source returned if (is_null($s)) { $this->open_php($src); $src .= "{$func} (" . var_export($arg, 1) . "); // <- failed \n"; } else { $src .= $s; } } // handle php state, when we return to where this directive was found, we are expected to still be in php $this->open_php($src); return $src; }