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