rebuildParsers.php 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. <?php declare(strict_types=1);
  2. require __DIR__ . '/phpyLang.php';
  3. $parserToDefines = [
  4. 'Php7' => ['PHP7' => true],
  5. 'Php8' => ['PHP8' => true],
  6. ];
  7. $grammarFile = __DIR__ . '/php.y';
  8. $skeletonFile = __DIR__ . '/parser.template';
  9. $tmpGrammarFile = __DIR__ . '/tmp_parser.phpy';
  10. $tmpResultFile = __DIR__ . '/tmp_parser.php';
  11. $resultDir = __DIR__ . '/../lib/PhpParser/Parser';
  12. $kmyacc = getenv('KMYACC');
  13. if (!$kmyacc) {
  14. // Use phpyacc from dev dependencies by default.
  15. $kmyacc = __DIR__ . '/../vendor/bin/phpyacc';
  16. }
  17. $options = array_flip($argv);
  18. $optionDebug = isset($options['--debug']);
  19. $optionKeepTmpGrammar = isset($options['--keep-tmp-grammar']);
  20. ///////////////////
  21. /// Main script ///
  22. ///////////////////
  23. foreach ($parserToDefines as $name => $defines) {
  24. echo "Building temporary $name grammar file.\n";
  25. $grammarCode = file_get_contents($grammarFile);
  26. $grammarCode = replaceIfBlocks($grammarCode, $defines);
  27. $grammarCode = preprocessGrammar($grammarCode);
  28. file_put_contents($tmpGrammarFile, $grammarCode);
  29. $additionalArgs = $optionDebug ? '-t -v' : '';
  30. echo "Building $name parser.\n";
  31. $output = execCmd("$kmyacc $additionalArgs -m $skeletonFile -p $name $tmpGrammarFile");
  32. $resultCode = file_get_contents($tmpResultFile);
  33. $resultCode = removeTrailingWhitespace($resultCode);
  34. ensureDirExists($resultDir);
  35. file_put_contents("$resultDir/$name.php", $resultCode);
  36. unlink($tmpResultFile);
  37. if (!$optionKeepTmpGrammar) {
  38. unlink($tmpGrammarFile);
  39. }
  40. }
  41. ////////////////////////////////
  42. /// Utility helper functions ///
  43. ////////////////////////////////
  44. function ensureDirExists($dir) {
  45. if (!is_dir($dir)) {
  46. mkdir($dir, 0777, true);
  47. }
  48. }
  49. function execCmd($cmd) {
  50. $output = trim(shell_exec("$cmd 2>&1") ?? '');
  51. if ($output !== "") {
  52. echo "> " . $cmd . "\n";
  53. echo $output;
  54. }
  55. return $output;
  56. }
  57. function replaceIfBlocks(string $code, array $defines): string {
  58. return preg_replace_callback('/\n#if\s+(\w+)\n(.*?)\n#endif/s', function ($matches) use ($defines) {
  59. $value = $defines[$matches[1]] ?? false;
  60. return $value ? $matches[2] : '';
  61. }, $code);
  62. }