PluginProbe
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor / 2.7.1
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor v2.7.1
4.0.2 4.0.1 4.0.0 3.16.6 3.16.5 3.16.4 3.16.3 3.16.2 3.16.1 3.16.0 3.15.9 3.9.9 3.9.5 3.9.6 3.9.7 3.9.8 1.1.7 1.1.8 1.1.9 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 All 340 releases
profile-builder / assets / lib / Mustache / Parser.php

Parser.php in User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor 2.7.1, at assets/lib/Mustache/Parser.php

195 lines 6.4 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) 2012 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('Unexpected closing tag: /%s', $token[Mustache_Tokenizer::NAME]);
75 throw new Mustache_Exception_SyntaxException($msg, $token);
76 }
77
78 if ($token[Mustache_Tokenizer::NAME] !== $parent[Mustache_Tokenizer::NAME]) {
79 $msg = sprintf('Nesting error: %s vs. %s', $parent[Mustache_Tokenizer::NAME], $token[Mustache_Tokenizer::NAME]);
80 throw new Mustache_Exception_SyntaxException($msg, $token);
81 }
82
83 $this->clearStandaloneLines($nodes, $tokens);
84 $parent[Mustache_Tokenizer::END] = $token[Mustache_Tokenizer::INDEX];
85 $parent[Mustache_Tokenizer::NODES] = $nodes;
86
87 return $parent;
88 break;
89
90 case Mustache_Tokenizer::T_PARTIAL:
91 case Mustache_Tokenizer::T_PARTIAL_2:
92 // store the whitespace prefix for laters!
93 if ($indent = $this->clearStandaloneLines($nodes, $tokens)) {
94 $token[Mustache_Tokenizer::INDENT] = $indent[Mustache_Tokenizer::VALUE];
95 }
96 $nodes[] = $token;
97 break;
98
99 case Mustache_Tokenizer::T_PRAGMA:
100 case Mustache_Tokenizer::T_COMMENT:
101 $this->clearStandaloneLines($nodes, $tokens);
102 $nodes[] = $token;
103 break;
104
105 default:
106 $nodes[] = $token;
107 break;
108 }
109 }
110
111 if (isset($parent)) {
112 $msg = sprintf('Missing closing tag: %s', $parent[Mustache_Tokenizer::NAME]);
113 throw new Mustache_Exception_SyntaxException($msg, $parent);
114 }
115
116 return $nodes;
117 }
118
119 /**
120 * Clear standalone line tokens.
121 *
122 * Returns a whitespace token for indenting partials, if applicable.
123 *
124 * @param array $nodes Parsed nodes.
125 * @param array $tokens Tokens to be parsed.
126 *
127 * @return array Resulting indent token, if any.
128 */
129 private function clearStandaloneLines(array &$nodes, array &$tokens)
130 {
131 if ($this->lineTokens > 1) {
132 // this is the third or later node on this line, so it can't be standalone
133 return;
134 }
135
136 $prev = null;
137 if ($this->lineTokens === 1) {
138 // this is the second node on this line, so it can't be standalone
139 // unless the previous node is whitespace.
140 if ($prev = end($nodes)) {
141 if (!$this->tokenIsWhitespace($prev)) {
142 return;
143 }
144 }
145 }
146
147 $next = null;
148 if ($next = reset($tokens)) {
149 // If we're on a new line, bail.
150 if ($next[Mustache_Tokenizer::LINE] !== $this->lineNum) {
151 return;
152 }
153
154 // If the next token isn't whitespace, bail.
155 if (!$this->tokenIsWhitespace($next)) {
156 return;
157 }
158
159 if (count($tokens) !== 1) {
160 // Unless it's the last token in the template, the next token
161 // must end in newline for this to be standalone.
162 if (substr($next[Mustache_Tokenizer::VALUE], -1) !== "\n") {
163 return;
164 }
165 }
166
167 // Discard the whitespace suffix
168 array_shift($tokens);
169 }
170
171 if ($prev) {
172 // Return the whitespace prefix, if any
173 return array_pop($nodes);
174 }
175 }
176
177 /**
178 * Check whether token is a whitespace token.
179 *
180 * True if token type is T_TEXT and value is all whitespace characters.
181 *
182 * @param array $token
183 *
184 * @return boolean True if token is a whitespace token
185 */
186 private function tokenIsWhitespace(array $token)
187 {
188 if ($token[Mustache_Tokenizer::TYPE] == Mustache_Tokenizer::T_TEXT) {
189 return preg_match('/^\s*$/', $token[Mustache_Tokenizer::VALUE]);
190 }
191
192 return false;
193 }
194 }
195