PluginProbe
GetResponse Forms by Optin Cat / 1.4.2
GetResponse Forms by Optin Cat v1.4.2
1.3.4 1.3.5 1.3.6 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.1 1.6.2 1.6.3 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 2.0.0 All 36 releases
getresponse / includes / classes / Mustache / Parser.php

Parser.php in GetResponse Forms by Optin Cat 1.4.2, at includes/classes/Mustache/Parser.php

207 lines 6.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 * This file is part of Mustache.php.
5 *
6 * (c) 2010-2014 Justin Hileman
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12 /**
13 * Mustache Parser class.
14 *
15 * This class is responsible for turning a set of Mustache tokens into a parse tree.
16 */
17 class Mustache_Parser
18 {
19 private $lineNum;
20 private $lineTokens;
21
22 /**
23 * Process an array of Mustache tokens and convert them into a parse tree.
24 *
25 * @param array $tokens Set of Mustache tokens
26 *
27 * @return array Mustache token parse tree
28 */
29 public function parse(array $tokens = array())
30 {
31 $this->lineNum = -1;
32 $this->lineTokens = 0;
33
34 return $this->buildTree($tokens);
35 }
36
37 /**
38 * Helper method for recursively building a parse tree.
39 *
40 * @throws Mustache_Exception_SyntaxException when nesting errors or mismatched section tags are encountered.
41 *
42 * @param array &$tokens Set of Mustache tokens
43 * @param array $parent Parent token (default: null)
44 *
45 * @return array Mustache Token parse tree
46 */
47 private function buildTree(array &$tokens, array $parent = null)
48 {
49 $nodes = array();
50
51 while (!empty($tokens)) {
52 $token = array_shift($tokens);
53
54 if ($token[Mustache_Tokenizer::LINE] === $this->lineNum) {
55 $this->lineTokens++;
56 } else {
57 $this->lineNum = $token[Mustache_Tokenizer::LINE];
58 $this->lineTokens = 0;
59 }
60
61 switch ($token[Mustache_Tokenizer::TYPE]) {
62 case Mustache_Tokenizer::T_DELIM_CHANGE:
63 $this->clearStandaloneLines($nodes, $tokens);
64 break;
65
66 case Mustache_Tokenizer::T_SECTION:
67 case Mustache_Tokenizer::T_INVERTED:
68 $this->clearStandaloneLines($nodes, $tokens);
69 $nodes[] = $this->buildTree($tokens, $token);
70 break;
71
72 case Mustache_Tokenizer::T_END_SECTION:
73 if (!isset($parent)) {
74 $msg = sprintf(
75 'Unexpected closing tag: /%s on line %d',
76 $token[Mustache_Tokenizer::NAME],
77 $token[Mustache_Tokenizer::LINE]
78 );
79 throw new Mustache_Exception_SyntaxException($msg, $token);
80 }
81
82 if ($token[Mustache_Tokenizer::NAME] !== $parent[Mustache_Tokenizer::NAME]) {
83 $msg = sprintf(
84 'Nesting error: %s (on line %d) vs. %s (on line %d)',
85 $parent[Mustache_Tokenizer::NAME],
86 $parent[Mustache_Tokenizer::LINE],
87 $token[Mustache_Tokenizer::NAME],
88 $token[Mustache_Tokenizer::LINE]
89 );
90 throw new Mustache_Exception_SyntaxException($msg, $token);
91 }
92
93 $this->clearStandaloneLines($nodes, $tokens);
94 $parent[Mustache_Tokenizer::END] = $token[Mustache_Tokenizer::INDEX];
95 $parent[Mustache_Tokenizer::NODES] = $nodes;
96
97 return $parent;
98
99 case Mustache_Tokenizer::T_PARTIAL:
100 case Mustache_Tokenizer::T_PARTIAL_2:
101 // store the whitespace prefix for laters!
102 if ($indent = $this->clearStandaloneLines($nodes, $tokens)) {
103 $token[Mustache_Tokenizer::INDENT] = $indent[Mustache_Tokenizer::VALUE];
104 }
105 $nodes[] = $token;
106 break;
107
108 case Mustache_Tokenizer::T_PRAGMA:
109 case Mustache_Tokenizer::T_COMMENT:
110 $this->clearStandaloneLines($nodes, $tokens);
111 $nodes[] = $token;
112 break;
113
114 default:
115 $nodes[] = $token;
116 break;
117 }
118 }
119
120 if (isset($parent)) {
121 $msg = sprintf(
122 'Missing closing tag: %s opened on line %d',
123 $parent[Mustache_Tokenizer::NAME],
124 $parent[Mustache_Tokenizer::LINE]
125 );
126 throw new Mustache_Exception_SyntaxException($msg, $parent);
127 }
128
129 return $nodes;
130 }
131
132 /**
133 * Clear standalone line tokens.
134 *
135 * Returns a whitespace token for indenting partials, if applicable.
136 *
137 * @param array $nodes Parsed nodes.
138 * @param array $tokens Tokens to be parsed.
139 *
140 * @return array Resulting indent token, if any.
141 */
142 private function clearStandaloneLines(array &$nodes, array &$tokens)
143 {
144 if ($this->lineTokens > 1) {
145 // this is the third or later node on this line, so it can't be standalone
146 return;
147 }
148
149 $prev = null;
150 if ($this->lineTokens === 1) {
151 // this is the second node on this line, so it can't be standalone
152 // unless the previous node is whitespace.
153 if ($prev = end($nodes)) {
154 if (!$this->tokenIsWhitespace($prev)) {
155 return;
156 }
157 }
158 }
159
160 if ($next = reset($tokens)) {
161 // If we're on a new line, bail.
162 if ($next[Mustache_Tokenizer::LINE] !== $this->lineNum) {
163 return;
164 }
165
166 // If the next token isn't whitespace, bail.
167 if (!$this->tokenIsWhitespace($next)) {
168 return;
169 }
170
171 if (count($tokens) !== 1) {
172 // Unless it's the last token in the template, the next token
173 // must end in newline for this to be standalone.
174 if (substr($next[Mustache_Tokenizer::VALUE], -1) !== "\n") {
175 return;
176 }
177 }
178
179 // Discard the whitespace suffix
180 array_shift($tokens);
181 }
182
183 if ($prev) {
184 // Return the whitespace prefix, if any
185 return array_pop($nodes);
186 }
187 }
188
189 /**
190 * Check whether token is a whitespace token.
191 *
192 * True if token type is T_TEXT and value is all whitespace characters.
193 *
194 * @param array $token
195 *
196 * @return boolean True if token is a whitespace token
197 */
198 private function tokenIsWhitespace(array $token)
199 {
200 if ($token[Mustache_Tokenizer::TYPE] == Mustache_Tokenizer::T_TEXT) {
201 return preg_match('/^\s*$/', $token[Mustache_Tokenizer::VALUE]);
202 }
203
204 return false;
205 }
206 }
207