Chris@13: parserFactory = new ParserFactory(); Chris@13: $this->parsers = []; Chris@13: Chris@13: parent::__construct($name); Chris@13: } Chris@13: Chris@13: /** Chris@13: * ContextAware interface. Chris@13: * Chris@13: * @param Context $context Chris@13: */ Chris@13: public function setContext(Context $context) Chris@13: { Chris@13: $this->context = $context; Chris@13: } Chris@13: Chris@13: /** Chris@13: * PresenterAware interface. Chris@13: * Chris@13: * @param Presenter $presenter Chris@13: */ Chris@13: public function setPresenter(Presenter $presenter) Chris@13: { Chris@13: $this->presenter = clone $presenter; Chris@13: $this->presenter->addCasters([ Chris@13: 'PhpParser\Node' => function (Node $node, array $a) { Chris@13: $a = [ Chris@13: Caster::PREFIX_VIRTUAL . 'type' => $node->getType(), Chris@13: Caster::PREFIX_VIRTUAL . 'attributes' => $node->getAttributes(), Chris@13: ]; Chris@13: Chris@13: foreach ($node->getSubNodeNames() as $name) { Chris@13: $a[Caster::PREFIX_VIRTUAL . $name] = $node->$name; Chris@13: } Chris@13: Chris@13: return $a; Chris@13: }, Chris@13: ]); Chris@13: } Chris@13: Chris@13: /** Chris@13: * {@inheritdoc} Chris@13: */ Chris@13: protected function configure() Chris@13: { Chris@13: $definition = [ Chris@13: new CodeArgument('code', CodeArgument::REQUIRED, 'PHP code to parse.'), Chris@13: new InputOption('depth', '', InputOption::VALUE_REQUIRED, 'Depth to parse.', 10), Chris@13: ]; Chris@13: Chris@13: if ($this->parserFactory->hasKindsSupport()) { Chris@13: $msg = 'One of PhpParser\\ParserFactory constants: ' Chris@17: . \implode(', ', ParserFactory::getPossibleKinds()) Chris@13: . " (default is based on current interpreter's version)."; Chris@13: $defaultKind = $this->parserFactory->getDefaultKind(); Chris@13: Chris@13: $definition[] = new InputOption('kind', '', InputOption::VALUE_REQUIRED, $msg, $defaultKind); Chris@13: } Chris@13: Chris@13: $this Chris@13: ->setName('parse') Chris@13: ->setDefinition($definition) Chris@13: ->setDescription('Parse PHP code and show the abstract syntax tree.') Chris@13: ->setHelp( Chris@13: <<<'HELP' Chris@13: Parse PHP code and show the abstract syntax tree. Chris@13: Chris@13: This command is used in the development of PsySH. Given a string of PHP code, Chris@13: it pretty-prints the PHP Parser parse tree. Chris@13: Chris@13: See https://github.com/nikic/PHP-Parser Chris@13: Chris@13: It prolly won't be super useful for most of you, but it's here if you want to play. Chris@13: HELP Chris@13: ); Chris@13: } Chris@13: Chris@13: /** Chris@13: * {@inheritdoc} Chris@13: */ Chris@13: protected function execute(InputInterface $input, OutputInterface $output) Chris@13: { Chris@13: $code = $input->getArgument('code'); Chris@17: if (\strpos('parserFactory->hasKindsSupport() ? $input->getOption('kind') : null; Chris@13: $depth = $input->getOption('depth'); Chris@13: $nodes = $this->parse($this->getParser($parserKind), $code); Chris@13: $output->page($this->presenter->present($nodes, $depth)); Chris@13: Chris@13: $this->context->setReturnValue($nodes); Chris@13: } Chris@13: Chris@13: /** Chris@13: * Lex and parse a string of code into statements. Chris@13: * Chris@13: * @param Parser $parser Chris@13: * @param string $code Chris@13: * Chris@13: * @return array Statements Chris@13: */ Chris@13: private function parse(Parser $parser, $code) Chris@13: { Chris@13: try { Chris@13: return $parser->parse($code); Chris@13: } catch (\PhpParser\Error $e) { Chris@17: if (\strpos($e->getMessage(), 'unexpected EOF') === false) { Chris@13: throw $e; Chris@13: } Chris@13: Chris@13: // If we got an unexpected EOF, let's try it again with a semicolon. Chris@13: return $parser->parse($code . ';'); Chris@13: } Chris@13: } Chris@13: Chris@13: /** Chris@13: * Get (or create) the Parser instance. Chris@13: * Chris@13: * @param string|null $kind One of Psy\ParserFactory constants (only for PHP parser 2.0 and above) Chris@13: * Chris@13: * @return Parser Chris@13: */ Chris@13: private function getParser($kind = null) Chris@13: { Chris@17: if (!\array_key_exists($kind, $this->parsers)) { Chris@13: $this->parsers[$kind] = $this->parserFactory->createParser($kind); Chris@13: } Chris@13: Chris@13: return $this->parsers[$kind]; Chris@13: } Chris@13: }