-
Notifications
You must be signed in to change notification settings - Fork 418
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 :-)
- Loading branch information
Showing
21 changed files
with
4,973 additions
and
4,047 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/* Bytecode instruction opcodes. */ | ||
module.exports = { | ||
/* Stack Manipulation */ | ||
PUSH: 0, // PUSH c | ||
PUSH_CURR_POS: 1, // PUSH_CURR_POS | ||
POP: 2, // POP | ||
POP_CURR_POS: 3, // POP_CURR_POS | ||
POP_N: 4, // POP_N n | ||
NIP: 5, // NIP | ||
NIP_CURR_POS: 6, // NIP_CURR_POS | ||
APPEND: 7, // APPEND | ||
WRAP: 8, // WRAP n | ||
TEXT: 9, // TEXT | ||
|
||
/* Conditions and Loops */ | ||
|
||
IF: 10, // IF t, f | ||
IF_ERROR: 11, // IF_ERROR t, f | ||
IF_NOT_ERROR: 12, // IF_NOT_ERROR t, f | ||
WHILE_NOT_ERROR: 13, // WHILE_NOT_ERROR b | ||
|
||
/* Matching */ | ||
|
||
MATCH_ANY: 14, // MATCH_ANY a, f, ... | ||
MATCH_STRING: 15, // MATCH_STRING s, a, f, ... | ||
MATCH_STRING_IC: 16, // MATCH_STRING_IC s, a, f, ... | ||
MATCH_REGEXP: 17, // MATCH_REGEXP r, a, f, ... | ||
ACCEPT_N: 18, // ACCEPT_N n | ||
ACCEPT_STRING: 19, // ACCEPT_STRING s | ||
FAIL: 20, // FAIL e | ||
|
||
/* Calls */ | ||
|
||
REPORT_SAVED_POS: 21, // REPORT_SAVED_POS p | ||
REPORT_CURR_POS: 22, // REPORT_CURR_POS | ||
CALL: 23, // CALL f, n, pc, p1, p2, ..., pN | ||
|
||
/* Rules */ | ||
|
||
RULE: 24, // RULE r | ||
|
||
/* Failure Reporting */ | ||
|
||
SILENT_FAILS_ON: 25, // SILENT_FAILS_ON | ||
SILENT_FAILS_OFF: 26 // SILENT_FAILS_FF | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
fe1ca48
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great Job !!!
and have you decided the time to make new npm release ?
fe1ca48
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@windyrobin I'll prepare a new release (0.8.0) when all features I'd like to be in get implemented. See the Trello board for details.
fe1ca48
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, seems you kept it under the hood for a long time, great job!