60 Commits (20a4fb2e7f70a0695bee4aef4984b24c06db3627)

Author SHA1 Message Date
Jakub Vrana 62d151cb5a Fix typo in comment 11 years ago
David Majda 34fe2c01ae Fix matching of case-instensitive literals
Code that calculated which part of the input to match against a literal
was wrong in case of case-insensitive literals when generating
speed-optimized parsers. As a result, matching of case-insensitive
literals worked only at the end of the input (where too big length
passed to the |substr| method didn't matter).

Fixes GH-153.
11 years ago
David Majda 0df8989f7a Fix buggy position computation
Fixes GH-152.
11 years ago
David Majda 76cc5d55b4 Use the |s| function instead of hardcoded |s0| value
Based on a patch by @fresheneesz:

  https://github.com/dmajda/pegjs/pull/148
11 years ago
David Majda 8759d4899e Fix deduplication in |peg$cleanupExpected|
The deduplication skipped over an expected string right after the one
that was removed because the index variable was incorrectly incremented
in that case.

Based on a patch by @fresheneesz:

  https://github.com/dmajda/pegjs/pull/146
11 years ago
David Majda 02af83f9b4 s/subclass/peg$subclass/
The |subclass| function is not intended to be used by user code.
12 years ago
David Majda 4fe32cee8c Fix indentation 12 years ago
David Majda d3d4ace153 Move options handling from passes to |PEG.compiler.compile|
This eliminates some duplicate code.
12 years ago
David Majda 5942988f66 Remove the |startRule| property from the AST
It's redundant.
12 years ago
David Majda fe1ca481ab 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 :-)
12 years ago