pastebin

Paste Search Dynamic
Recent pastes
php parse
  1. #!/usr/bin/env php
  2. <?php
  3.  
  4. foreach ([__DIR__ . '/../../../autoload.php', __DIR__ . '/../vendor/autoload.php'] as $file) {
  5.     if (file_exists($file)) {
  6.         require $file;
  7.         break;
  8.     }
  9. }
  10.  
  11. ini_set('xdebug.max_nesting_level', 3000);
  12.  
  13. // Disable XDebug var_dump() output truncation
  14. ini_set('xdebug.var_display_max_children', -1);
  15. ini_set('xdebug.var_display_max_data', -1);
  16. ini_set('xdebug.var_display_max_depth', -1);
  17.  
  18. list($operations, $files, $attributes) = parseArgs($argv);
  19.  
  20. /* Dump nodes by default */
  21. if (empty($operations)) {
  22.     $operations[] = 'dump';
  23. }
  24.  
  25. if (empty($files)) {
  26.     showHelp("Must specify at least one file.");
  27. }
  28.  
  29. $lexer = new PhpParserLexerEmulative(['usedAttributes' => [
  30.     'startLine', 'endLine', 'startFilePos', 'endFilePos', 'comments'
  31. ]]);
  32. $parser = (new PhpParserParserFactory)->create(
  33.     PhpParserParserFactory::PREFER_PHP7,
  34.     $lexer
  35. );
  36. $dumper = new PhpParserNodeDumper([
  37.     'dumpComments' => true,
  38.     'dumpPositions' => $attributes['with-positions'],
  39. ]);
  40. $prettyPrinter = new PhpParserPrettyPrinterStandard;
  41.  
  42. $traverser = new PhpParserNodeTraverser();
  43. $traverser->addVisitor(new PhpParserNodeVisitorNameResolver);
  44.  
  45. foreach ($files as $file) {
  46.     if (strpos($file, '<?php') === 0) {
  47.         $code = $file;
  48.         fwrite(STDERR, "====> Code $coden");
  49.     } else {
  50.         if (!file_exists($file)) {
  51.             fwrite(STDERR, "File $file does not exist.n");
  52.             exit(1);
  53.         }
  54.  
  55.         $code = file_get_contents($file);
  56.         fwrite(STDERR, "====> File $file:n");
  57.     }
  58.  
  59.     if ($attributes['with-recovery']) {
  60.         $errorHandler = new PhpParserErrorHandlerCollecting;
  61.         $stmts = $parser->parse($code, $errorHandler);
  62.         foreach ($errorHandler->getErrors() as $error) {
  63.             $message = formatErrorMessage($error, $code, $attributes['with-column-info']);
  64.             fwrite(STDERR, $message . "n");
  65.         }
  66.         if (null === $stmts) {
  67.             continue;
  68.         }
  69.     } else {
  70.         try {
  71.             $stmts = $parser->parse($code);
  72.         } catch (PhpParserError $error) {
  73.             $message = formatErrorMessage($error, $code, $attributes['with-column-info']);
  74.             fwrite(STDERR, $message . "n");
  75.             exit(1);
  76.         }
  77.     }
  78.  
  79.     foreach ($operations as $operation) {
  80.         if ('dump' === $operation) {
  81.             fwrite(STDERR, "==> Node dump:n");
  82.             echo $dumper->dump($stmts, $code), "n";
  83.         } elseif ('pretty-print' === $operation) {
  84.             fwrite(STDERR, "==> Pretty print:n");
  85.             echo $prettyPrinter->prettyPrintFile($stmts), "n";
  86.         } elseif ('json-dump' === $operation) {
  87.             fwrite(STDERR, "==> JSON dump:n");
  88.             echo json_encode($stmts, JSON_PRETTY_PRINT), "n";
  89.         } elseif ('var-dump' === $operation) {
  90.             fwrite(STDERR, "==> var_dump():n");
  91.             var_dump($stmts);
  92.         } elseif ('resolve-names' === $operation) {
  93.             fwrite(STDERR, "==> Resolved names.n");
  94.             $stmts = $traverser->traverse($stmts);
  95.         }
  96.     }
  97. }
  98.  
  99. function formatErrorMessage(PhpParserError $e, $code, $withColumnInfo) {
  100.     if ($withColumnInfo && $e->hasColumnInfo()) {
  101.         return $e->getMessageWithColumnInfo($code);
  102.     } else {
  103.         return $e->getMessage();
  104.     }
  105. }
  106.  
  107. function showHelp($error = '') {
  108.     if ($error) {
  109.         fwrite(STDERR, $error . "nn");
  110.     }
  111.     fwrite($error ? STDERR : STDOUT, <<<OUTPUT
  112. Usage: php-parse [operations] file1.php [file2.php ...]
  113.    or: php-parse [operations] "<?php code"
  114. Turn PHP source code into an abstract syntax tree.
  115.  
  116. Operations is a list of the following options (--dump by default):
  117.  
  118.     -d, --dump              Dump nodes using NodeDumper
  119.     -p, --pretty-print      Pretty print file using PrettyPrinterStandard
  120.     -j, --json-dump         print json_encode() result
  121.         --var-dump          var_dump() nodes (for exact structure)
  122.     -N, --resolve-names     Resolve names using NodeVisitorNameResolver
  123.     -c, --with-column-info  Show column-numbers for errors (if available)
  124.     -P, --with-positions    Show positions in node dumps
  125.     -r, --with-recovery     Use parsing with error recovery
  126.     -h, --help              Display this page
  127.  
  128. Example:
  129.     php-parse -d -p -N -d file.php
  130.  
  131.     Dumps nodes, pretty prints them, then resolves names and dumps them again.
  132.  
  133.  
  134. OUTPUT
  135.     );
  136.     exit($error ? 1 : 0);
  137. }
  138.  
  139. function parseArgs($args) {
  140.     $operations = [];
  141.     $files = [];
  142.     $attributes = [
  143.         'with-column-info' => false,
  144.         'with-positions' => false,
  145.         'with-recovery' => false,
  146.     ];
  147.  
  148.     array_shift($args);
  149.     $parseOptions = true;
  150.     foreach ($args as $arg) {
  151.         if (!$parseOptions) {
  152.             $files[] = $arg;
  153.             continue;
  154.         }
  155.  
  156.         switch ($arg) {
  157.             case '--dump':
  158.             case '-d':
  159.                 $operations[] = 'dump';
  160.                 break;
  161.             case '--pretty-print':
  162.             case '-p':
  163.                 $operations[] = 'pretty-print';
  164.                 break;
  165.             case '--json-dump':
  166.             case '-j':
  167.                 $operations[] = 'json-dump';
  168.                 break;
  169.             case '--var-dump':
  170.                 $operations[] = 'var-dump';
  171.                 break;
  172.             case '--resolve-names':
  173.             case '-N';
  174.                 $operations[] = 'resolve-names';
  175.                 break;
  176.             case '--with-column-info':
  177.             case '-c';
  178.                 $attributes['with-column-info'] = true;
  179.                 break;
  180.             case '--with-positions':
  181.             case '-P':
  182.                 $attributes['with-positions'] = true;
  183.                 break;
  184.             case '--with-recovery':
  185.             case '-r':
  186.                 $attributes['with-recovery'] = true;
  187.                 break;
  188.             case '--help':
  189.             case '-h';
  190.                 showHelp();
  191.                 break;
  192.             case '--':
  193.                 $parseOptions = false;
  194.                 break;
  195.             default:
  196.                 if ($arg[0] === '-') {
  197.                     showHelp("Invalid operation $arg.");
  198.                 } else {
  199.                     $files[] = $arg;
  200.                 }
  201.         }
  202.     }
  203.  
  204.     return [$operations, $files, $attributes];
  205. }
Parsed in 0.312 seconds