PluginProbe ʕ •ᴥ•ʔ
WP All Import – Drag & Drop Import for CSV, XML, Excel & Google Sheets / 3.0
WP All Import – Drag & Drop Import for CSV, XML, Excel & Google Sheets v3.0
4.1.1 3.9.5 3.9.6 4.0.0 4.0.1 4.1.0 trunk 2.12 2.13 2.14 3.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6 3.4.7 3.4.8 3.4.9 3.5.0 3.5.1 3.5.2 3.5.3 3.5.4 3.5.5 3.5.6 3.5.7 3.5.8 3.5.9 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.6.8 3.6.9 3.7.0 3.7.1 3.7.2 3.7.3 3.7.3-beta-1.0 3.7.4 3.7.4-beta-1.0 3.7.5 3.7.6 3.7.7 3.7.8 3.7.9 3.8.0 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4
wp-all-import / libraries / XmlImportTemplateParser.php
wp-all-import / libraries Last commit date
ast 13 years ago cache 13 years ago XmlImportConfig.php 13 years ago XmlImportCsvParse.php 13 years ago XmlImportException.php 13 years ago XmlImportParser.php 13 years ago XmlImportReaderInterface.php 13 years ago XmlImportStringReader.php 13 years ago XmlImportTemplate.php 13 years ago XmlImportTemplateCodeGenerator.php 13 years ago XmlImportTemplateParser.php 13 years ago XmlImportTemplateScanner.php 13 years ago XmlImportToken.php 13 years ago pclzip.lib.php 13 years ago
XmlImportTemplateParser.php
399 lines
1 <?php
2 /**
3 * @author Olexandr Zanichkovsky <olexandr.zanichkovsky@zophiatech.com>
4 * @package General
5 */
6
7 require_once dirname(__FILE__) . '/ast/XmlImportAstSequence.php';
8 require_once dirname(__FILE__) . '/ast/XmlImportAstPrint.php';
9 require_once dirname(__FILE__) . '/ast/XmlImportAstText.php';
10 require_once dirname(__FILE__) . '/ast/XmlImportAstWith.php';
11 require_once dirname(__FILE__) . '/ast/XmlImportAstForeach.php';
12 require_once dirname(__FILE__) . '/ast/XmlImportAstIf.php';
13 require_once dirname(__FILE__) . '/ast/XmlImportAstMath.php';
14 require_once dirname(__FILE__) . '/ast/XmlImportAstSpintax.php';
15
16 require_once dirname(__FILE__) . '/ast/XmlImportAstXPath.php';
17 require_once dirname(__FILE__) . '/ast/XmlImportAstString.php';
18 require_once dirname(__FILE__) . '/ast/XmlImportAstInteger.php';
19 require_once dirname(__FILE__) . '/ast/XmlImportAstFloat.php';
20
21 /**
22 * Parses a list of nodes into AST (Abstract Syntax Tree)
23 */
24 class XmlImportTemplateParser
25 {
26 /**
27 * List of tokens
28 *
29 * @var array
30 */
31 private $tokens;
32
33 /**
34 * Current index
35 *
36 * @var int
37 */
38 private $index = -1;
39
40 /**
41 * Stack that stores possible block endings
42 *
43 * @var array
44 */
45 private $clauseStack = array();
46
47 /**
48 * Stack of sequences
49 *
50 * @var array
51 */
52 private $sequenceStack = array();
53
54 /**
55 * Whether else subclause is allowed
56 *
57 * @var bool
58 */
59 private $elseAllowed = false;
60
61 /**
62 * Creates new instance
63 *
64 * @param array $tokens
65 */
66 public function __construct(array $tokens)
67 {
68 $this->tokens = $tokens;
69 }
70
71 /**
72 * Parses the list of tokens into AST tree
73 *
74 * @return XmlImportAstSequence
75 */
76 public function parse()
77 {
78 $result = $this->parseSequence();
79
80 if (count($this->clauseStack) > 0)
81 throw new XmlImportException("Unexpected end of template.");
82
83 return $result;
84 }
85
86 /**
87 * Parses sequence
88 *
89 * @return XmlImportAstSequence
90 */
91 private function parseSequence()
92 {
93 if (($this->index + 1) == count($this->tokens))
94 throw new XmlImportException("Reached end of template but statement sequence expected");
95 $sequence = new XmlImportAstSequence();
96 array_push($this->sequenceStack, $sequence);
97 if (count($this->clauseStack) == 0)
98 {
99 while (($this->index + 1) < count($this->tokens))
100 {
101 $sequence->addStatement($this->parseStatement());
102 }
103 }
104 else
105 {
106 while (($this->index + 1) < count($this->tokens))
107 {
108 if ($this->tokens[$this->index + 1]->getKind() == $this->clauseStack[count($this->clauseStack) - 1])
109 {
110 $this->index++;
111 array_pop($this->clauseStack);
112 break;
113 }
114 $statement = $this->parseStatement();
115 if (is_null($statement))
116 return $sequence;
117 $sequence->addStatement($statement);
118 }
119 }
120 array_pop($this->sequenceStack);
121
122 return $sequence;
123 }
124
125 /**
126 * Parses statement
127 *
128 * @return XmlImportAstText
129 */
130 private function parseStatement()
131 {
132 if ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_TEXT)
133 {
134 return new XmlImportAstText($this->tokens[++$this->index]->getValue());
135 }
136 elseif ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_PRINT)
137 {
138 $this->index++;
139 return new XmlImportAstPrint($this->parseExpression());
140 }
141 elseif ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_WITH)
142 {
143 return $this->parseWith();
144 }
145 elseif ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_FOREACH)
146 {
147 return $this->parseForeach();
148 }
149 elseif($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_MATH)
150 {
151 return new XmlImportAstPrint($this->parseExpression());
152 }
153 elseif($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_SPINTAX)
154 {
155 return new XmlImportAstPrint($this->parseExpression());
156 }
157 elseif ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_IF)
158 {
159 return $this->parseIf();
160 }
161 elseif($this->clauseStack[count($this->clauseStack) - 1] == XmlImportToken::KIND_ENDIF &&
162 in_array($this->tokens[$this->index + 1]->getKind(), array(XmlImportToken::KIND_ELSE, XmlImportToken::KIND_ELSEIF)))
163 {
164 if ($this->elseAllowed)
165 {
166 if ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_ELSE)
167 $this->elseAllowed = false;
168 }
169 else
170 {
171 throw new XmlImportException("ELSEIF or ELSE is not allowed again after ELSE");
172 }
173 return null;
174 }
175 else
176 throw new XmlImportException ("Unexpected token {$this->tokens[$this->index + 1]->getKind()}, statement was expected.");
177 }
178
179 /**
180 * Parses expression
181 *
182 * @return XmlImportAstXPath
183 */
184 private function parseExpression()
185 {
186 if ($this->index + 1 == count($this->tokens))
187 throw new XmlImportException("Reached end of template but expression was expected");
188
189 if($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_MATH)
190 {
191 return $this->parseMath();
192 }
193 elseif($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_SPINTAX)
194 {
195 return $this->parseSpintax();
196 }
197 elseif ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_XPATH)
198 {
199 $xpath = new XmlImportAstXPath($this->tokens[++$this->index]->getValue());
200 $this->sequenceStack[count($this->sequenceStack) - 1]->addVariable($xpath);
201 return $xpath;
202 }
203 elseif ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_STRING || $this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_OPERATION)
204 {
205 return new XmlImportAstString($this->tokens[++$this->index]->getValue());
206 }
207 elseif ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_INT)
208 {
209 return new XmlImportAstInteger($this->tokens[++$this->index]->getValue());
210 }
211 elseif ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_FLOAT)
212 {
213 return new XmlImportAstFloat($this->tokens[++$this->index]->getValue());
214 }
215 else
216 throw new XmlImportException("Unexpected token " . $this->tokens[$this->index + 1]->getKind());
217 }
218
219 /**
220 * Parses function
221 *
222 * @return XmlImportAstFunction
223 */
224 private function parseMath()
225 {
226 $math = new XmlImportAstMath($this->tokens[++$this->index]->getValue());
227 if ($this->tokens[$this->index + 1]->getKind() != XmlImportToken::KIND_OPEN)
228 throw new XmlImportException ("Open brace expected instead of " . $this->tokens[$this->index + 1]->getKind());
229 $this->index++;
230 if ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_CLOSE)
231 {
232 $this->index++;
233 return $math;
234 }
235 else
236 {
237 while ($this->index < count($this->tokens) - 2)
238 {
239 $math->addArgument($this->parseExpression());
240 if ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_CLOSE)
241 {
242 $this->index++;
243 return $math;
244 break;
245 }
246 elseif ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_COMMA)
247 $this->index++;
248 else
249 throw new XmlImportException("Comma or closing brace expected instead of " . $this->tokens[$this->index + 1]->getKind());
250 }
251 throw new XmlImportException("Unexpected end of MATH argument list");
252 }
253 }
254
255 /**
256 * Parses function
257 *
258 * @return XmlImportSpintaxFunction
259 */
260 private function parseSpintax()
261 {
262 $spintax = new XmlImportAstSpintax($this->tokens[++$this->index]->getValue());
263 if ($this->tokens[$this->index + 1]->getKind() != XmlImportToken::KIND_OPEN)
264 throw new XmlImportException ("Open brace expected instead of " . $this->tokens[$this->index + 1]->getKind());
265 $this->index++;
266 if ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_CLOSE)
267 {
268 $this->index++;
269 return $spintax;
270 }
271 else
272 {
273 while ($this->index < count($this->tokens) - 2)
274 {
275 $spintax->addArgument($this->parseExpression());
276 if ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_CLOSE)
277 {
278 $this->index++;
279 return $spintax;
280 break;
281 }
282 elseif ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_COMMA)
283 $this->index++;
284 else
285 throw new XmlImportException("Comma or closing brace expected instead of " . $this->tokens[$this->index + 1]->getKind());
286 }
287 throw new XmlImportException("Unexpected end of {$function->getName()} function argument list");
288 }
289 }
290
291 /**
292 * Parses clause that uses XPath and returns XPath
293 *
294 * @return XmlImportAstXPath
295 */
296 private function parseXPathDependant()
297 {
298 $this->index++;
299
300 if ($this->index + 1 == count($this->tokens))
301 throw new XmlImportException("Reached end of template but expression was expected");
302
303 if ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_OPEN)
304 $this->index++;
305 else
306 throw new XmlImportException("Open brace expected instead of " . $this->tokens[$this->index + 1]->getKind());
307 if ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_XPATH)
308 {
309 $xpath = new XmlImportAstXPath($this->tokens[++$this->index]->getValue());
310 $this->sequenceStack[count($this->sequenceStack) - 1]->addVariable($xpath);
311 }
312 else
313 throw new XmlImportException("XPath expression expected instead of " . $this->tokens[$this->index + 1]->getKind());
314 if ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_CLOSE)
315 $this->index++;
316 else
317 throw new XmlImportException("Close brace expected instead of " . $this->tokens[$this->index + 1]->getKind());
318 return $xpath;
319 }
320
321 /**
322 * Parses WITH clause
323 *
324 * @return XmlImportAstWith
325 */
326 private function parseWith()
327 {
328 $xpath = $this->parseXPathDependant();
329 //store sequence exit
330 array_push($this->clauseStack, XmlImportToken::KIND_ENDWITH);
331 return new XmlImportAstWith($xpath, $this->parseSequence());
332 }
333
334 /**
335 * Parses FOREACH clause
336 *
337 * @return XmlImportAstForeach
338 */
339 private function parseForeach()
340 {
341 $xpath = $this->parseXPathDependant();
342
343 array_push($this->clauseStack, XmlImportToken::KIND_ENDFOREACH);
344 return new XmlImportAstForeach($xpath, $this->parseSequence());
345 }
346
347 /**
348 * Parses IF clause
349 *
350 * @return XmlImportAstIf
351 */
352 private function parseIf()
353 {
354 $this->index++;
355 $this->elseAllowed = true;
356 array_push($this->clauseStack, XmlImportToken::KIND_ENDIF);
357
358 if ($this->index + 1 == count($this->tokens))
359 throw new XmlImportException("Reached end of template but expression was expected");
360
361 if ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_OPEN)
362 $this->index++;
363 else
364 throw new XmlImportException("Open brace expected instead of " . $this->tokens[$this->index + 1]->getKind());
365 $if = new XmlImportAstIf($this->parseExpression());
366 if ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_CLOSE)
367 $this->index++;
368 else
369 throw new XmlImportException("Close brace expected instead of " . $this->tokens[$this->index + 1]->getKind());
370 $if->addIfBody($this->parseSequence());
371 if ($this->index + 1 != count($this->tokens))
372 {
373 while ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_ELSEIF)
374 {
375 $this->index++;
376 if ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_OPEN)
377 $this->index++;
378 else
379 throw new XmlImportException("Open brace expected instead of " . $this->tokens[$this->index + 1]->getKind());
380 $condition = $this->parseExpression();
381 if ($this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_CLOSE)
382 $this->index++;
383 else
384 throw new XmlImportException("Close brace expected instead of " . $this->tokens[$this->index + 1]->getKind());
385 $elseif = new XmlImportAstElseif($condition, $this->parseSequence());
386 $if->addElseif($elseif);
387 if ($this->index + 1 == count($this->tokens))
388 break;
389 }
390 if ($this->index + 1 < count($this->tokens) && $this->tokens[$this->index + 1]->getKind() == XmlImportToken::KIND_ELSE)
391 {
392 $this->index++;
393 $if->addElseBody($this->parseSequence());
394 }
395 }
396
397 return $if;
398 }
399 }