Chris@13
|
1 <?php declare(strict_types=1);
|
Chris@0
|
2
|
Chris@0
|
3 namespace PhpParser\Parser;
|
Chris@0
|
4
|
Chris@0
|
5 use PhpParser\Error;
|
Chris@0
|
6 use PhpParser\ErrorHandler;
|
Chris@0
|
7 use PhpParser\Parser;
|
Chris@0
|
8
|
Chris@13
|
9 class Multiple implements Parser
|
Chris@13
|
10 {
|
Chris@0
|
11 /** @var Parser[] List of parsers to try, in order of preference */
|
Chris@0
|
12 private $parsers;
|
Chris@0
|
13
|
Chris@0
|
14 /**
|
Chris@0
|
15 * Create a parser which will try multiple parsers in an order of preference.
|
Chris@0
|
16 *
|
Chris@0
|
17 * Parsers will be invoked in the order they're provided to the constructor. If one of the
|
Chris@0
|
18 * parsers runs without throwing, it's output is returned. Otherwise the exception that the
|
Chris@0
|
19 * first parser generated is thrown.
|
Chris@0
|
20 *
|
Chris@0
|
21 * @param Parser[] $parsers
|
Chris@0
|
22 */
|
Chris@0
|
23 public function __construct(array $parsers) {
|
Chris@0
|
24 $this->parsers = $parsers;
|
Chris@0
|
25 }
|
Chris@0
|
26
|
Chris@13
|
27 public function parse(string $code, ErrorHandler $errorHandler = null) {
|
Chris@0
|
28 if (null === $errorHandler) {
|
Chris@0
|
29 $errorHandler = new ErrorHandler\Throwing;
|
Chris@0
|
30 }
|
Chris@0
|
31
|
Chris@0
|
32 list($firstStmts, $firstError) = $this->tryParse($this->parsers[0], $errorHandler, $code);
|
Chris@0
|
33 if ($firstError === null) {
|
Chris@0
|
34 return $firstStmts;
|
Chris@0
|
35 }
|
Chris@0
|
36
|
Chris@0
|
37 for ($i = 1, $c = count($this->parsers); $i < $c; ++$i) {
|
Chris@0
|
38 list($stmts, $error) = $this->tryParse($this->parsers[$i], $errorHandler, $code);
|
Chris@0
|
39 if ($error === null) {
|
Chris@0
|
40 return $stmts;
|
Chris@0
|
41 }
|
Chris@0
|
42 }
|
Chris@0
|
43
|
Chris@0
|
44 throw $firstError;
|
Chris@0
|
45 }
|
Chris@0
|
46
|
Chris@0
|
47 private function tryParse(Parser $parser, ErrorHandler $errorHandler, $code) {
|
Chris@0
|
48 $stmts = null;
|
Chris@0
|
49 $error = null;
|
Chris@0
|
50 try {
|
Chris@0
|
51 $stmts = $parser->parse($code, $errorHandler);
|
Chris@0
|
52 } catch (Error $error) {}
|
Chris@0
|
53 return [$stmts, $error];
|
Chris@0
|
54 }
|
Chris@0
|
55 }
|