Move filter logic from the compiler to the parser.

This commit is contained in:
Justin Hileman
2014-08-18 18:28:50 -07:00
parent d225afe032
commit 58a7726515
3 changed files with 120 additions and 83 deletions
+52 -68
View File
@@ -60,7 +60,7 @@ class Mustache_Compiler
*
* @internal Users should set global pragmas in Mustache_Engine, not here :)
*
* @param array $pragmas
* @param string[] $pragmas
*/
public function setPragmas(array $pragmas)
{
@@ -95,6 +95,7 @@ class Mustache_Compiler
$code .= $this->section(
$node[Mustache_Tokenizer::NODES],
$node[Mustache_Tokenizer::NAME],
isset($node[Mustache_Tokenizer::FILTERS]) ? $node[Mustache_Tokenizer::FILTERS] : array(),
$node[Mustache_Tokenizer::INDEX],
$node[Mustache_Tokenizer::END],
$node[Mustache_Tokenizer::OTAG],
@@ -107,6 +108,7 @@ class Mustache_Compiler
$code .= $this->invertedSection(
$node[Mustache_Tokenizer::NODES],
$node[Mustache_Tokenizer::NAME],
isset($node[Mustache_Tokenizer::FILTERS]) ? $node[Mustache_Tokenizer::FILTERS] : array(),
$level
);
break;
@@ -154,14 +156,24 @@ class Mustache_Compiler
case Mustache_Tokenizer::T_UNESCAPED:
case Mustache_Tokenizer::T_UNESCAPED_2:
$code .= $this->variable($node[Mustache_Tokenizer::NAME], false, $level);
$code .= $this->variable(
$node[Mustache_Tokenizer::NAME],
isset($node[Mustache_Tokenizer::FILTERS]) ? $node[Mustache_Tokenizer::FILTERS] : array(),
false,
$level
);
break;
case Mustache_Tokenizer::T_COMMENT:
break;
case Mustache_Tokenizer::T_ESCAPED:
$code .= $this->variable($node[Mustache_Tokenizer::NAME], true, $level);
$code .= $this->variable(
$node[Mustache_Tokenizer::NAME],
isset($node[Mustache_Tokenizer::FILTERS]) ? $node[Mustache_Tokenizer::FILTERS] : array(),
true,
$level
);
break;
case Mustache_Tokenizer::T_TEXT:
@@ -279,8 +291,8 @@ class Mustache_Compiler
*/
private function blockArg($nodes, $id, $start, $end, $otag, $ctag, $level)
{
$key = $this->section($nodes, $id, $start, $end, $otag, $ctag, $level, true);
$id = var_export($id, true);
$key = $this->section($nodes, $id, array(), $start, $end, $otag, $ctag, $level, true);
$id = var_export($id, true);
return sprintf($this->prepare(self::BLOCK_ARG, $level), $id, $key, $id, $this->flushIndent());
}
@@ -320,25 +332,20 @@ class Mustache_Compiler
/**
* Generate Mustache Template section PHP source.
*
* @param array $nodes Array of child tokens
* @param string $id Section name
* @param int $start Section start offset
* @param int $end Section end offset
* @param string $otag Current Mustache opening tag
* @param string $ctag Current Mustache closing tag
* @param int $level
* @param bool $arg (default: false)
* @param array $nodes Array of child tokens
* @param string $id Section name
* @param string[] $filters Array of filters
* @param int $start Section start offset
* @param int $end Section end offset
* @param string $otag Current Mustache opening tag
* @param string $ctag Current Mustache closing tag
* @param int $level
* @param bool $arg (default: false)
*
* @return string Generated section PHP source code
*/
private function section($nodes, $id, $start, $end, $otag, $ctag, $level, $arg = false)
private function section($nodes, $id, $filters, $start, $end, $otag, $ctag, $level, $arg = false)
{
$filters = '';
if (isset($this->pragmas[Mustache_Engine::PRAGMA_FILTERS])) {
list($id, $filters) = $this->getFilters($id, $level);
}
$source = var_export(substr($this->source, $start, $end - $start), true);
$callable = $this->getCallable();
@@ -357,8 +364,9 @@ class Mustache_Compiler
if ($arg === true) {
return $key;
} else {
$method = $this->getFindMethod($id);
$id = var_export($id, true);
$method = $this->getFindMethod($id);
$id = var_export($id, true);
$filters = $this->getFilters($filters, $level);
return sprintf($this->prepare(self::SECTION_CALL, $level), $id, $method, $id, $filters, $key);
}
@@ -374,22 +382,18 @@ class Mustache_Compiler
/**
* Generate Mustache Template inverted section PHP source.
*
* @param array $nodes Array of child tokens
* @param string $id Section name
* @param int $level
* @param array $nodes Array of child tokens
* @param string $id Section name
* @param string[] $filters Array of filters
* @param int $level
*
* @return string Generated inverted section PHP source code
*/
private function invertedSection($nodes, $id, $level)
private function invertedSection($nodes, $id, $filters, $level)
{
$filters = '';
if (isset($this->pragmas[Mustache_Engine::PRAGMA_FILTERS])) {
list($id, $filters) = $this->getFilters($id, $level);
}
$method = $this->getFindMethod($id);
$id = var_export($id, true);
$method = $this->getFindMethod($id);
$id = var_export($id, true);
$filters = $this->getFilters($filters, $level);
return sprintf($this->prepare(self::INVERTED_SECTION, $level), $id, $method, $id, $filters, $this->walk($nodes, $level));
}
@@ -477,43 +481,23 @@ class Mustache_Compiler
/**
* Generate Mustache Template variable interpolation PHP source.
*
* @param string $id Variable name
* @param boolean $escape Escape the variable value for output?
* @param int $level
* @param string $id Variable name
* @param string[] $filters Array of filters
* @param boolean $escape Escape the variable value for output?
* @param int $level
*
* @return string Generated variable interpolation PHP source
*/
private function variable($id, $escape, $level)
private function variable($id, $filters, $escape, $level)
{
$filters = '';
if (isset($this->pragmas[Mustache_Engine::PRAGMA_FILTERS])) {
list($id, $filters) = $this->getFilters($id, $level);
}
$method = $this->getFindMethod($id);
$id = ($method !== 'last') ? var_export($id, true) : '';
$value = $escape ? $this->getEscape() : '$value';
$method = $this->getFindMethod($id);
$id = ($method !== 'last') ? var_export($id, true) : '';
$filters = $this->getFilters($filters, $level);
$value = $escape ? $this->getEscape() : '$value';
return sprintf($this->prepare(self::VARIABLE, $level), $method, $id, $filters, $this->flushIndent(), $value);
}
/**
* Generate Mustache Template variable filtering PHP source.
*
* @param string $id Variable name
* @param int $level
*
* @return string Generated variable filtering PHP source
*/
private function getFilters($id, $level)
{
$filters = array_map('trim', explode('|', $id));
$id = array_shift($filters);
return array($id, $this->getFilter($filters, $level));
}
const FILTER = '
$filter = $context->%s(%s);
if (!(%s)) {
@@ -523,14 +507,14 @@ class Mustache_Compiler
';
/**
* Generate PHP source for a single filter.
* Generate Mustache Template variable filtering PHP source.
*
* @param array $filters
* @param int $level
* @param string[] $filters Array of filters
* @param int $level
*
* @return string Generated filter PHP source
*/
private function getFilter(array $filters, $level)
private function getFilters(array $filters, $level)
{
if (empty($filters)) {
return '';
@@ -542,7 +526,7 @@ class Mustache_Compiler
$callable = $this->getCallable('$filter');
$msg = var_export($name, true);
return sprintf($this->prepare(self::FILTER, $level), $method, $filter, $callable, $msg, $this->getFilter($filters, $level));
return sprintf($this->prepare(self::FILTER, $level), $method, $filter, $callable, $msg, $this->getFilters($filters, $level));
}
const LINE = '$buffer .= "\n";';
+57 -5
View File
@@ -21,6 +21,9 @@ class Mustache_Parser
private $pragmas;
private $defaultPragmas = array();
private $pragmaFilters;
private $pragmaBlocks;
/**
* Process an array of Mustache tokens and convert them into a parse tree.
*
@@ -34,6 +37,9 @@ class Mustache_Parser
$this->lineTokens = 0;
$this->pragmas = $this->defaultPragmas;
$this->pragmaFilters = isset($this->pragmas[Mustache_Engine::PRAGMA_FILTERS]);
$this->pragmaBlocks = isset($this->pragmas[Mustache_Engine::PRAGMA_BLOCKS]);
return $this->buildTree($tokens);
}
@@ -43,13 +49,13 @@ class Mustache_Parser
*
* @internal Users should set global pragmas in Mustache_Engine, not here :)
*
* @param array $pragmas
* @param string[] $pragmas
*/
public function setPragmas(array $pragmas)
{
$this->pragmas = array();
foreach ($pragmas as $pragma) {
$this->pragmas[$pragma] = true;
$this->enablePragma($pragma);
}
$this->defaultPragmas = $this->pragmas;
}
@@ -78,6 +84,14 @@ class Mustache_Parser
$this->lineTokens = 0;
}
if ($this->pragmaFilters && isset($token[Mustache_Tokenizer::NAME])) {
list($name, $filters) = $this->getNameAndFilters($token[Mustache_Tokenizer::NAME]);
if (!empty($filters)) {
$token[Mustache_Tokenizer::NAME] = $name;
$token[Mustache_Tokenizer::FILTERS] = $filters;
}
}
switch ($token[Mustache_Tokenizer::TYPE]) {
case Mustache_Tokenizer::T_DELIM_CHANGE:
$this->checkIfTokenIsAllowedInParent($parent, $token);
@@ -133,7 +147,7 @@ class Mustache_Parser
break;
case Mustache_Tokenizer::T_BLOCK_VAR:
if (isset($this->pragmas[Mustache_Engine::PRAGMA_BLOCKS])) {
if ($this->pragmaBlocks) {
// BLOCKS pragma is enabled, let's do this!
if ($parent[Mustache_Tokenizer::TYPE] === Mustache_Tokenizer::T_PARENT) {
$token[Mustache_Tokenizer::TYPE] = Mustache_Tokenizer::T_BLOCK_ARG;
@@ -150,7 +164,7 @@ class Mustache_Parser
break;
case Mustache_Tokenizer::T_PRAGMA:
$this->pragmas[$token[Mustache_Tokenizer::NAME]] = true;
$this->enablePragma($token[Mustache_Tokenizer::NAME]);
// no break
case Mustache_Tokenizer::T_COMMENT:
@@ -184,7 +198,7 @@ class Mustache_Parser
* @param array $nodes Parsed nodes.
* @param array $tokens Tokens to be parsed.
*
* @return array Resulting indent token, if any.
* @return array|null Resulting indent token, if any.
*/
private function clearStandaloneLines(array &$nodes, array &$tokens)
{
@@ -265,4 +279,42 @@ class Mustache_Parser
throw new Mustache_Exception_SyntaxException('Illegal content in < parent tag', $token);
}
}
/**
* Split a tag name into name and filters.
*
* @param string $name
*
* @return array {
* @type string Tag name
* @type string[] Array of filters
* }
*/
private function getNameAndFilters($name)
{
$filters = array_map('trim', explode('|', $name));
$name = array_shift($filters);
return array($name, $filters);
}
/**
* Enable a pragma.
*
* @param string $name
*/
private function enablePragma($name)
{
$this->pragmas[$name] = true;
switch ($name) {
case Mustache_Engine::PRAGMA_BLOCKS:
$this->pragmaBlocks = true;
break;
case Mustache_Engine::PRAGMA_FILTERS:
$this->pragmaFilters = true;
break;
}
}
}
+11 -10
View File
@@ -61,16 +61,17 @@ class Mustache_Tokenizer
);
// Token properties
const TYPE = 'type';
const NAME = 'name';
const OTAG = 'otag';
const CTAG = 'ctag';
const LINE = 'line';
const INDEX = 'index';
const END = 'end';
const INDENT = 'indent';
const NODES = 'nodes';
const VALUE = 'value';
const TYPE = 'type';
const NAME = 'name';
const OTAG = 'otag';
const CTAG = 'ctag';
const LINE = 'line';
const INDEX = 'index';
const END = 'end';
const INDENT = 'indent';
const NODES = 'nodes';
const VALUE = 'value';
const FILTERS = 'filters';
private $state;
private $tagType;