Multiple.php 1.6 KB

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