|
0
|
1 |
<?php |
|
|
2 |
|
|
|
3 |
/* |
|
|
4 |
* This file is part of Twig. |
|
|
5 |
* |
|
|
6 |
* (c) 2010 Fabien Potencier |
|
|
7 |
* |
|
|
8 |
* For the full copyright and license information, please view the LICENSE |
|
|
9 |
* file that was distributed with this source code. |
|
|
10 |
*/ |
|
|
11 |
abstract class Twig_Extensions_SimpleTokenParser extends Twig_TokenParser |
|
|
12 |
{ |
|
|
13 |
/** |
|
|
14 |
* Parses a token and returns a node. |
|
|
15 |
* |
|
|
16 |
* @param Twig_Token $token A Twig_Token instance |
|
|
17 |
* |
|
|
18 |
* @return Twig_NodeInterface A Twig_NodeInterface instance |
|
|
19 |
*/ |
|
|
20 |
public function parse(Twig_Token $token) |
|
|
21 |
{ |
|
|
22 |
$grammar = $this->getGrammar(); |
|
|
23 |
if (!is_object($grammar)) { |
|
|
24 |
$grammar = self::parseGrammar($grammar); |
|
|
25 |
} |
|
|
26 |
|
|
|
27 |
$grammar->setParser($this->parser); |
|
|
28 |
$values = $grammar->parse($token); |
|
|
29 |
|
|
|
30 |
return $this->getNode($values, $token->getLine()); |
|
|
31 |
} |
|
|
32 |
|
|
|
33 |
/** |
|
|
34 |
* Gets the grammar as an object or as a string. |
|
|
35 |
* |
|
|
36 |
* @return string|Twig_Extensions_Grammar A Twig_Extensions_Grammar instance or a string |
|
|
37 |
*/ |
|
|
38 |
abstract protected function getGrammar(); |
|
|
39 |
|
|
|
40 |
/** |
|
|
41 |
* Gets the nodes based on the parsed values. |
|
|
42 |
* |
|
|
43 |
* @param array $values An array of values |
|
|
44 |
* @param integer $line The parser line |
|
|
45 |
*/ |
|
|
46 |
abstract protected function getNode(array $values, $line); |
|
|
47 |
|
|
|
48 |
protected function getAttribute($node, $attribute, $arguments = array(), $type = Twig_Node_Expression_GetAttr::TYPE_ANY, $line = -1) |
|
|
49 |
{ |
|
|
50 |
return new Twig_Node_Expression_GetAttr( |
|
|
51 |
$node instanceof Twig_NodeInterface ? $node : new Twig_Node_Expression_Name($node, $line), |
|
|
52 |
$attribute instanceof Twig_NodeInterface ? $attribute : new Twig_Node_Expression_Constant($attribute, $line), |
|
|
53 |
$arguments instanceof Twig_NodeInterface ? $arguments : new Twig_Node($arguments), |
|
|
54 |
$type, |
|
|
55 |
$line |
|
|
56 |
); |
|
|
57 |
} |
|
|
58 |
|
|
|
59 |
protected function call($node, $attribute, $arguments = array(), $line = -1) |
|
|
60 |
{ |
|
|
61 |
return $this->getAttribute($node, $attribute, $arguments, Twig_Node_Expression_GetAttr::TYPE_METHOD, $line); |
|
|
62 |
} |
|
|
63 |
|
|
|
64 |
protected function markAsSafe(Twig_NodeInterface $node, $line = -1) |
|
|
65 |
{ |
|
|
66 |
return new Twig_Node_Expression_Filter( |
|
|
67 |
$node, |
|
|
68 |
new Twig_Node_Expression_Constant('raw', $line), |
|
|
69 |
new Twig_Node(), |
|
|
70 |
$line |
|
|
71 |
); |
|
|
72 |
} |
|
|
73 |
|
|
|
74 |
protected function output(Twig_NodeInterface $node, $line = -1) |
|
|
75 |
{ |
|
|
76 |
return new Twig_Node_Print($node, $line); |
|
|
77 |
} |
|
|
78 |
|
|
|
79 |
protected function getNodeValues(array $values) |
|
|
80 |
{ |
|
|
81 |
$nodes = array(); |
|
|
82 |
foreach ($values as $value) { |
|
|
83 |
if ($value instanceof Twig_NodeInterface) { |
|
|
84 |
$nodes[] = $value; |
|
|
85 |
} |
|
|
86 |
} |
|
|
87 |
|
|
|
88 |
return $nodes; |
|
|
89 |
} |
|
|
90 |
|
|
|
91 |
static public function parseGrammar($str, $main = true) |
|
|
92 |
{ |
|
|
93 |
static $cursor; |
|
|
94 |
|
|
|
95 |
if (true === $main) { |
|
|
96 |
$cursor = 0; |
|
|
97 |
$grammar = new Twig_Extensions_Grammar_Tag(); |
|
|
98 |
} else { |
|
|
99 |
$grammar = new Twig_Extensions_Grammar_Optional(); |
|
|
100 |
} |
|
|
101 |
|
|
|
102 |
while ($cursor < strlen($str)) { |
|
|
103 |
if (preg_match('/\s+/A', $str, $match, null, $cursor)) { |
|
|
104 |
$cursor += strlen($match[0]); |
|
|
105 |
} elseif (preg_match('/<(\w+)(?:\:(\w+))?>/A', $str, $match, null, $cursor)) { |
|
|
106 |
$class = sprintf('Twig_Extensions_Grammar_%s', ucfirst(isset($match[2]) ? $match[2] : 'Expression')); |
|
|
107 |
if (!class_exists($class)) { |
|
|
108 |
throw new Twig_Error_Runtime(sprintf('Unable to understand "%s" in grammar (%s class does not exist)', $match[0], $class)); |
|
|
109 |
} |
|
|
110 |
$grammar->addGrammar(new $class($match[1])); |
|
|
111 |
$cursor += strlen($match[0]); |
|
|
112 |
} elseif (preg_match('/\w+/A', $str, $match, null, $cursor)) { |
|
|
113 |
$grammar->addGrammar(new Twig_Extensions_Grammar_Constant($match[0])); |
|
|
114 |
$cursor += strlen($match[0]); |
|
|
115 |
} elseif (preg_match('/,/A', $str, $match, null, $cursor)) { |
|
|
116 |
$grammar->addGrammar(new Twig_Extensions_Grammar_Constant($match[0], Twig_Token::PUNCTUATION_TYPE)); |
|
|
117 |
$cursor += strlen($match[0]); |
|
|
118 |
} elseif (preg_match('/\[/A', $str, $match, null, $cursor)) { |
|
|
119 |
$cursor += strlen($match[0]); |
|
|
120 |
$grammar->addGrammar(self::parseGrammar($str, false)); |
|
|
121 |
} elseif (true !== $main && preg_match('/\]/A', $str, $match, null, $cursor)) { |
|
|
122 |
$cursor += strlen($match[0]); |
|
|
123 |
|
|
|
124 |
return $grammar; |
|
|
125 |
} else { |
|
|
126 |
throw new Twig_Error_Runtime(sprintf('Unable to parse grammar "%s" near "...%s..."', $str, substr($str, $cursor, 10))); |
|
|
127 |
} |
|
|
128 |
} |
|
|
129 |
|
|
|
130 |
return $grammar; |
|
|
131 |
} |
|
|
132 |
} |