You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

83 lines
2.2 KiB

Code generator rewrite This is a complete rewrite of the PEG.js code generator. Its goals are: 1. Allow optimizing the generated parser code for code size as well as for parsing speed. 2. Prepare ground for future optimizations and big features (like incremental parsing). 2. Replace the old template-based code-generation system with something more lightweight and flexible. 4. General code cleanup (structure, style, variable names, ...). New Architecture ---------------- The new code generator consists of two steps: * Bytecode generator -- produces bytecode for an abstract virtual machine * JavaScript generator -- produces JavaScript code based on the bytecode The abstract virtual machine is stack-based. Originally I wanted to make it register-based, but it turned out that all the code related to it would be more complex and the bytecode itself would be longer (because of explicit register specifications in instructions). The only downsides of the stack-based approach seem to be few small inefficiencies (see e.g. the |NIP| instruction), which seem to be insignificant. The new generator allows optimizing for parsing speed or code size (you can choose using the |optimize| option of the |PEG.buildParser| method or the --optimize/-o option on the command-line). When optimizing for size, the JavaScript generator emits the bytecode together with its constant table and a generic bytecode interpreter. Because the interpreter is small and the bytecode and constant table grow only slowly with size of the grammar, the resulting parser is also small. When optimizing for speed, the JavaScript generator just compiles the bytecode into JavaScript. The generated code is relatively efficient, so the resulting parser is fast. Internal Identifiers -------------------- As a small bonus, all internal identifiers visible to user code in the initializer, actions and predicates are prefixed by |peg$|. This lowers the chance that identifiers in user code will conflict with the ones from PEG.js. It also makes using any internals in user code ugly, which is a good thing. This solves GH-92. Performance ----------- The new code generator improved parsing speed and parser code size significantly. The generated parsers are now: * 39% faster when optimizing for speed * 69% smaller when optimizing for size (without minification) * 31% smaller when optimizing for size (with minification) (Parsing speed was measured using the |benchmark/run| script. Code size was measured by generating parsers for examples in the |examples| directory and adding up the file sizes. Minification was done by |uglify --ascii| in version 1.3.4.) Final Note ---------- This is just a beginning! The new code generator lays a foundation upon which many optimizations and improvements can (and will) be made. Stay tuned :-)
9 years ago
  1. {
  2. "name": "pegjs",
  3. "version": "0.10.0",
  4. "description": "Parser generator for JavaScript",
  5. "keywords": [
  6. "parser generator",
  7. "PEG"
  8. ],
  9. "homepage": "https://pegjs.org/",
  10. "bugs": "https://github.com/pegjs/pegjs/issues",
  11. "license": "MIT",
  12. "contributors": [
  13. "David Majda <david@majda.cz> (https://majda.cz/)",
  14. "Futago-za Ryuu <futagoza.ryuu@gmail.com>"
  15. ],
  16. "files": [
  17. "CHANGELOG.md",
  18. "LICENSE",
  19. "README.md",
  20. "bin/peg.js",
  21. "bin/options.js",
  22. "bin/usage.txt",
  23. "examples/arithmetics.pegjs",
  24. "examples/css.pegjs",
  25. "examples/javascript.pegjs",
  26. "examples/json.pegjs",
  27. "lib/compiler/asts.js",
  28. "lib/compiler/index.js",
  29. "lib/compiler/js.js",
  30. "lib/compiler/opcodes.js",
  31. "lib/compiler/passes/generate-bytecode.js",
  32. "lib/compiler/passes/generate-js.js",
  33. "lib/compiler/passes/remove-proxy-rules.js",
  34. "lib/compiler/passes/report-duplicate-labels.js",
  35. "lib/compiler/passes/report-duplicate-rules.js",
  36. "lib/compiler/passes/report-infinite-recursion.js",
  37. "lib/compiler/passes/report-infinite-repetition.js",
  38. "lib/compiler/passes/report-undefined-rules.js",
  39. "lib/compiler/visitor.js",
  40. "lib/grammar-error.js",
  41. "lib/parser.js",
  42. "lib/peg.js",
  43. "package.json"
  44. ],
  45. "main": "lib/peg",
  46. "bin": "bin/peg.js",
  47. "repository": "pegjs/pegjs",
  48. "scripts": {
  49. "lint": "gulp lint",
  50. "spec": "gulp test",
  51. "test": "gulp",
  52. "test:server": "node test/server/run",
  53. "benchmark": "gulp benchmark",
  54. "browser:build": "gulp browser:build",
  55. "browser:clean": "gulp browser:build",
  56. "parser": "gulp parser"
  57. },
  58. "devDependencies": {
  59. "babel-preset-es2015": "6.14.0",
  60. "babelify": "7.3.0",
  61. "browserify": "13.1.0",
  62. "chai": "3.5.0",
  63. "del": "2.2.2",
  64. "eslint-config-dmajda": "1.0.0",
  65. "express": "4.14.0",
  66. "glob": "7.0.6",
  67. "gulp": "3.9.1",
  68. "gulp-eslint": "3.0.1",
  69. "gulp-header": "1.8.8",
  70. "gulp-mocha": "3.0.1",
  71. "gulp-rename": "1.2.2",
  72. "gulp-transform": "1.0.8",
  73. "gulp-uglify": "2.0.0",
  74. "morgan": "1.7.0",
  75. "run-sequence": "1.2.2",
  76. "sinon": "1.17.6",
  77. "vinyl-buffer": "1.0.0",
  78. "vinyl-source-stream": "1.1.0"
  79. },
  80. "engines": {
  81. "node": ">=4"
  82. }
  83. }