/** * Tokenizer and preparser. * @return array */ private function parseMacro($input) { $this->tokenizer->tokenize($input); $this->tokenizer->tokens[] = NULL; // sentinel $inTernary = $lastSymbol = $prev = NULL; $tokens = $arrays = array(); $n = -1; while (++$n < count($this->tokenizer->tokens)) { list($token, $name) = $current = $this->tokenizer->tokens[$n]; $depth = count($arrays); if ($name === self::T_COMMENT) { continue; // remove comments } elseif ($name === self::T_WHITESPACE) { $current[2] = $depth; $tokens[] = $current; continue; } elseif ($name === self::T_SYMBOL && in_array($prev[0], array(',', '(', '[', '=', '=>', ':', '?', NULL), TRUE)) { $lastSymbol = count($tokens); // quoting pre-requirements } elseif (is_int($lastSymbol) && in_array($token, array(',', ')', ']', '=', '=>', ':', '|', NULL), TRUE)) { $tokens[$lastSymbol][0] = "'" . $tokens[$lastSymbol][0] . "'"; // quote symbols $lastSymbol = NULL; } else { $lastSymbol = NULL; } if ($token === '?') { // short ternary operators without : $inTernary = $depth; } elseif ($token === ':') { $inTernary = NULL; } elseif ($inTernary === $depth && ($token === ',' || $token === ')' || $token === ']' || $token === NULL)) { // close ternary $tokens[] = array(':', NULL, $depth); $tokens[] = array('null', NULL, $depth); $inTernary = NULL; } if ($token === '[') { // simplified array syntax [...] if ($arrays[] = $prev[0] !== ']' && $prev[1] !== self::T_SYMBOL && $prev[1] !== self::T_VARIABLE) { $tokens[] = array('array', NULL, $depth); $current = array('(', NULL); } } elseif ($token === ']') { if (array_pop($arrays) === TRUE) { $current = array(')', NULL); } } elseif ($token === '(') { // only count $arrays[] = '('; } elseif ($token === ')') { // only count array_pop($arrays); } if ($current) { $current[2] = $depth; $tokens[] = $prev = $current; } } return $tokens; }
private function error($message = "Unexpected '%s'") { list(, $line, $col) = self::$tokenizer->getOffset($this->n); $token = str_replace("\n", '\\n', Nette\String::truncate(self::$tokenizer->tokens[$this->n], 40)); throw new NeonException(str_replace('%s', $token, $message) . "' on line " . ($line - 1) . ", column {$col}."); }
private function error($message = "Unexpected '%s'") { list(, $line, $col) = self::$tokenizer->getOffset($this->n); $token = isset(self::$tokenizer->tokens[$this->n]) ? str_replace("\n", '<new line>', Nette\String::truncate(self::$tokenizer->tokens[$this->n], 40)) : 'end'; throw new NeonException(str_replace('%s', $token, $message) . " on line $line, column $col."); }
/** * Formats parameters to PHP array. * @param string * @param string * @return string */ public static function formatArray($input, $prefix = '') { $tokenizer = new Tokenizer(array( Tokenizer::T_WHITESPACE => '\s+', Tokenizer::T_COMMENT => '/\*.*?\*/', Tokenizer::RE_STRING, 'true|false|null|and|or|xor|clone|new|instanceof', '\$[_a-z0-9\x7F-\xFF]+', // variable self::T_SYMBOL => '[_a-z0-9\x7F-\xFF]+', // string, number '=>|[^"\']', // =>, any char except quotes ), 'i'); $out = ''; $quote = TRUE; foreach ($tokenizer->tokenize($input) as $n => $token) { list($token, $name) = $token; if ($name === Tokenizer::T_COMMENT) { continue; } elseif ($name === self::T_SYMBOL && $quote && !is_numeric($token) && in_array($tokenizer->nextToken($n), array(',', '=>', ')', NULL), TRUE)) { $token = "'$token'"; } if ($name !== Tokenizer::T_WHITESPACE) { $quote = in_array($token, array('[', ',', '=', '(', '=>')); } $out .= $token; } return $out === '' ? '' : $prefix . "array($out)"; }
private function error() { list(, $line, $col) = self::$tokenizer->getOffset($this->n); throw new NeonException("Unexpected '" . str_replace("\n", '\n', substr(self::$tokenizer->tokens[$this->n], 0, 10)) . "' on line " . ($line - 1) . ", column $col."); }