397 Commits (b0a5db1ab964745add140632d72b8bd451612cf2)

Author SHA1 Message Date
David Majda 1870308afb Code style: Fix ESLint "object-shorthand" errors
Part of #407.
8 years ago
David Majda 5dd8e797f7 Code style: Do not lint lib/parser.js
The idea behind linting lib/parser.js was that it would improve quality
of code generated by PEG.js in general. However, there is a couple of
problems with it:

  1. Code in lib/parser.js is ES5 while the rest of the code is ES2015.
     This would mean a separate ESLint configuration and a separate set
     of code style rules just for lib/parser.js once code style checks
     are added.

  2. Code in lib/parser.js is generated. This means that even today it
     violates checks like "no-unused-var", which have to be disabled.
     This would get worse once code style checks are added, again
     requiring a separate ESLint configuration just for lib/parser.js.

  3. Linting lib/parser.js checks only small portion of possible code
     generator output. For example, code generated when optimizing for
     size or when tracing is not checked at all. Thus, linting
     lib/parser.js gives a false sense of security.

Because of these problems I decided not to lint lib/parser.js at all and
rely on ad-hoc linting of parser files produced by PEG.js with ignoring
false-positives. I consider this more of a pragmatic cost vs. benefits
decision than a principial one.

Part of #407.
8 years ago
David Majda f82d9872ba Replace stray "var" by "let"
Likely missed in bdf91b5941.
8 years ago
David Majda 7495e6e03f Add missing semicolons 8 years ago
David Majda b81afb1471 Do not quote the "class" key
Quoting reserved words in property names is not needed since dropping
support of IE < 9.
8 years ago
David Majda ec3f7f5bb0 Remove extra indentation 8 years ago
David Majda 7ca229a432 Improve indentation of variable declarations
Before this commit, continuation lines of multi-line values in variable
declaration initializers were aligned with the variable name:

  let foo = {
        a: 5,
        b: 6
      };

This was highly irregular, maintenance intensive, and made declarations
look different from assignments.

This commit changes the indentation to be more regular and similar to
assignments:

  let foo = {
    a: 5,
    b: 6
  };
8 years ago
David Majda e29d62558d Do not prepend the "eslint-env" directive to lib/parser.js
The lib/parser.js file is a CommonJS module like all the other files in
lib/, so setting the environment explicitly is not needed. Besides, the
environment set by "eslint-env" was wrong (since transitioning from the
AMD format).
8 years ago
David Majda 9648ca53d7 Use the "eslint-disable" directive instead of "eslint"
The "eslint-disable" directive is more specific.
8 years ago
David Majda 60821bb80b Sort "require" calls by variable names and group them
This makes things consistent and reduces thinking about "require"
ordering.
8 years ago
David Majda ff7193776e Avoid aligning "="
The only exception left are instances where aligning "=" helps to
express symmetry between lines.

See #443.
8 years ago
David Majda 400a3cfa3c Avoid aligning object keys
The only exception left are objects representing a mapping with simple
keys and values -- essentially tables written as object literals.

See #443.
8 years ago
David Majda 12112310f2 Use only double quotes for strings
See #443
8 years ago
David Majda 6294bb5b13 Use only "//" comments
See #443.
8 years ago
David Majda 1da6abc458 Use one var/let/const per variable (fixup)
Fix few instances in generated code which I missed in the previous
commit.

See #443.
8 years ago
David Majda 516023546d Use one var/let/const per variable (for initialized variables)
Use one var/let/const per variable, but only for initialized variables.
Uninitialized variables are still grouped into one var/let/const
declaration as I don't see any value in separating them. This approach
reflects the fact that initialized and uninitialized var/let/const
declarations are really two different things.

See #443.
8 years ago
David Majda 7f01db2fb8 Get rid of for-in loops
The for-in statement in JavaScript iterates also over inherited
properties. This is typically not desired and requires adding a
check using Object.prototype.hasOwnProperty inside the loop.

This commit replaces all for-in statements and related checks inside
them with iteration over Object.keys(...). The iteration is performed
using either Array.prototype.forEach of a plain for loop.
8 years ago
David Majda b2a9dabcff Remove now unused lib/utils/objects.js
See #442.
8 years ago
David Majda 5fbb557f80 Don't use "objects" in lib/peg.js
The "objects" module will be removed.

See #442.
8 years ago
David Majda 66ca7e2168 Don't use "objects" in lib/compiler/visitor.js
The "objects" module will be removed.

See #442.
8 years ago
David Majda 76e70c3923 Don't use "objects" in lib/compiler/passes/report-duplicate-labels.js
The "objects" module will be removed.

See #442.
8 years ago
David Majda d2569b9bf3 Don't use "objects" in lib/compiler/passes/generate-js.js
The "objects" module will be removed.

See #442.
8 years ago
David Majda 8a75d19468 Don't use "objects" in lib/compiler/passes/generate-bytecode.js
The "objects" module will be removed.

See #442.
8 years ago
David Majda 97d92c9d8b Don't use "objects" in lib/compiler/index.js
The "objects" module will be removed.

See #442.
8 years ago
David Majda c344460855 Remove now unused lib/utils/arrays.js
See #442.
8 years ago
David Majda f81ae1845b Don't use "arrays" in lib/compiler/passes/report-infinite-recursion.js
The "arrays" module will be removed.

See #442.
8 years ago
David Majda 71ef4c9b91 Don't use "arrays" in lib/compiler/passes/remove-proxy-rules.js
The "arrays" module will be removed.

See #442.
8 years ago
David Majda 8f8484b1a1 Don't use "arrays" in lib/compiler/passes/generate-js.js
The "arrays" module will be removed.

See #442.
8 years ago
David Majda 33f23ee4be Don't use "arrays" in lib/compiler/passes/generate-bytecode.js
The "arrays" module will be removed.

See #442.
8 years ago
David Majda 4dec5e52ba Don't use "arrays" in lib/compiler/asts.js
The "arrays" module will be removed.

See #442.
8 years ago
David Majda 5822596ab8 Replace classes.subclass with native classes
See #442.
8 years ago
David Majda 6fa8ad63f9 Replace some functions with arrow functions
Because arrow functions work rather differently than normal functions (a
bad design mistake if you ask me), I decided to be conservative with the
conversion.

I converted:

  * event handlers
  * callbacks
  * arguments to Array.prototype.map & co.
  * small standalone lambda functions

I didn't convert:

  * functions assigned to object literal properties (the new shorthand
    syntax would be better here)
  * functions passed to "describe", "it", etc. in specs (because Jasmine
    relies on dynamic "this")

See #442.
8 years ago
David Majda d00e9526c3 Minimize variable scope
Where possible, move "let" statements into inner blocks, loop headers,
etc.

See #442.
8 years ago
David Majda bdf91b5941 Replace "var" with "let" & "const"
This is purely a mechanical change, not taking advantage of block scope
of "let" and "const". Minimizing variable scope will come in the next
commit.

In general, "var" is converted into "let" and "const" is used only for
immutable variables of permanent character (generally spelled in
ALL_CAPS). Using it for any immutable variable regardless on its
permanence would feel confusing.

Any code which is not transpiled and needs to run in ES6 environment
(examples, code in grammars embedded in specs, ...) is kept unchanged.
This is also true for code generated by PEG.js.

See #442.
8 years ago
David Majda c3e7072fa2 Remove unused arrays.pluck function 8 years ago
David Majda 062c6ae706 Escape backspace in regexp classes as "\b", not "\x08"
The "\x08" escaping is necessary only outside of classes (where "\b"
means "word boundary").
8 years ago
David Majda bd62ddf846 Use "[]" & "[^]" for empty character classes, not "(?!)" & "[\\S\\s]"
See #441.
8 years ago
David Majda 9c04c94c85 Escape vertical tab as "\v", not "\x0B"
See #441.
8 years ago
David Majda f36a667376 Remove "undefined" redefinition protection
See #441.
8 years ago
David Majda fad4ab74d1 Replace suitable for loops with Array methods (in /lib)
See #441.
8 years ago
David Majda 3e8bcbea73 Replace suitable for loops with Array methods (in /src)
See #441.
8 years ago
David Majda 1c3fbf6cb0 Replace "... instanceof Array" with "Array.isArray(...)"
See #441.
8 years ago
David Majda d346d2a66d Replace objects.keys with Object.keys
See #441.
8 years ago
David Majda 0059cc3bdd Replace arrays.some with Array.prototype.some
See #441.
8 years ago
David Majda d162fe1cfc Replace arrays.every with Array.prototype.every
See #441.
8 years ago
David Majda 5f65de92bc Replace arrays.map with Array.prototype.map
See #441.
8 years ago
David Majda b044a021c4 Replace arrays.each with Array.prototype.forEach
See #441.
8 years ago
David Majda 671166bbe8 Update version to 0.10.0 8 years ago
David Majda 8003edafc9 Rename the "node" module format to "commonjs"
Parsers generated in this format use module.exports, so they are not
strictly CommonJS, but this is a common extension and the original name
would be confusing once Node.js implements ES2015 modules.
8 years ago
David Majda 8962dcfd16 Rename the "global" module format to "globals"
I think the new name is more widely used when describing the pattern.
8 years ago
David Majda b77d33ca05 generate-js.js: Quote the "class" key in DESCRIBE_EXPECTATION_FNS
"class" is a reserved word. Having it as a key unquoted broke IE 8 (both
in standards and quirks mode) and IE 9 (in quirks mode).
8 years ago
David Majda 67d85f2de8 Align names of compiler passes that detect infinite loops
Rename compiler passes as follows:

  reportLeftRecursion -> reportInfiniteRecursion
  reportInfiniteLoops -> reportInfiniteRepetition

This reflects the fact that both passes detect different ways of causing
the same problem (possible infinite loop when parsing).
8 years ago
David Majda 9717dc3417 Talk about "undefined rules" instead of "missing rules" internally
The new terminology is more precise and in line with commonly used
programming languages.

The change involves mainly renaming related compiler pass and files
associated with it.
8 years ago
David Majda e9cb23608d Split peg$buildException into two separate functions
This change reflects the fact that PEG.js-generated parsers really
produce two kinds of syntax errors:

  Structured errors

    Caused by match failures, trailing input, or calls of the "expected"
    function in parser code. Their messages have fixed format ("Expected
    ... but ... found.").

  Simple errors

    Caused by calls of the "error" function in parser code. Their
    messages don't have any fixed format.

Each kind of error now has a separate helper function which builds its
instances.
8 years ago
David Majda e03d92488a Set the "found" property of syntax errors produced by "error" to null
The property doesn't correspond to anything in the error's message.
8 years ago
David Majda 6ca546a44e Regenerate lib/parser.js 8 years ago
David Majda db9920e3ca peg.generate: Implement { format: "global" } 8 years ago
David Majda 61c11ee1b4 peg.generate: Implement { format: "amd" } 8 years ago
David Majda f633f697c9 peg.generate: Implement { format: "node" } 8 years ago
David Majda 9454c11c59 generate-js.js: Fix "=" alignment 8 years ago
David Majda e546af5543 Regenerate lib/parser.js 8 years ago
David Majda e8be76ee3a Don't expose the "parser" variable in parser code
The "parser" variable allowed access to the parser object. Among other
things, this made it possible to invoke the parser recursively using
"parser.parse".

One problem with the "parser" variable is that it bakes in the idea that
the parser is an *object*, not a *module*. While this is true now, it
won't necessarily be in the future, when parsers may be exported as ES6
modules. Also, people tend to use parsers as modules even today, e.g.
like this:

  var parse = require("parser").parse;
  var result = parse(...);

Such usage broke the "parser" variable (as it was implemented).

For this reasons I decided to remove the "parser" variable. If someone
needs to do tricks like recursive invocation of the parser, he/she must
pass the parser or the "parse" function itself using options.

Related to #433.
8 years ago
David Majda 6aa956452e Don't use "this" inside peg.generate
This change makes it possible to use "generate" as a module function,
e.g. like this:

  var generate = require("pegjs").generate;
  var parser = generate(...);

Fixes #433.
8 years ago
David Majda 65550965c6 Remove extraneous "with" from an error message 8 years ago
David Majda b3a90de020 Syntax error messages: Use Oxford comma
In general PEG.js uses American English, where Oxford comma is
prevalent.

Part of #371.
8 years ago
David Majda ec8ede5bbe Grammar error messages 3/3: Improve the left recursion message
New wording is more explanatory.

Part of #371.
8 years ago
David Majda f5e43f842c Grammar error messages 2/3: Improve the infinite loop message
New wording is more explanatory.

Part of #371.
8 years ago
David Majda 85fb8aaa0e Grammar error messages 1/3: Improve the missing rule message
New wording is more similar to wording used in various programming
languages and it is in line with the duplicate rule message.

Part of #371.
8 years ago
David Majda eb67cbedb4 Report duplicate labels as errors
Resolves #270.
8 years ago
David Majda 2a889535bd Add location to the "Rule ... is already defined" error message
See this discussion:

  eb5875bc6a (commitcomment-17970220)
8 years ago
David Majda eb5875bc6a Report duplicate rule definitions as errors
Based on a pull request by Futago-za Ryuu (@futagoza):

  https://github.com/pegjs/pegjs/pull/329

Resolves #318.
8 years ago
David Majda 149c829897 lib/compiler/index.js: Order default option values alphabetically 8 years ago
David Majda 930877c3ba Move lib/compiler.js to lib/compiler/index.js
This makes "compiler" a regular Node.js module.
8 years ago
David Majda 5a4d04fa90 Construct expectations using functions
Until now, expectations were constructed using object literals. This
commit changes the construction to use factory functions.

This change makes generated parsers slightly smaller because property
names don't have to be repeated many times and factory function calls
are more amenable to minifying.

Some numbers based on the aggregate size of parsers generated from
examples/*.pegjs:

  Optimization   Minified?   Size before   Size after   Saving
  ------------------------------------------------------------
  speed          no               719066       716063    0.42%
  speed          yes              188998       180202    4.65%
  size           no               194810       197813    1.52%
  size           yes              108782        99947    8.12%

(Minification was done using "uglify --mangle --compress" with
uglify-js 2.4.24.)
8 years ago
David Majda e7d03825e0 AST: Remove the "rawText" property from "class" nodes
It isn't used anymore.
8 years ago
David Majda 35c8280743 Expectation refactoring 7/7: Regenerate lib/parser.js 8 years ago
David Majda 8639cf6d61 Expectation refactoring 6/7: Move "buildMessage" to SyntaxError
The "buildMessage" utility function, which was previously internal, is
now exposed as SyntaxError.buildMessage in generated parsers.

The motivation behind this is two-fold:

  1. Building of a syntax error message is a responsibility of the
     SyntaxError class, meaning the code should be placed there.

  2. By exposing the message building code, parser users can use it to
     generate customized error messages without duplicating PEG.js's code.

Note that helper functions inside "buildMessage" ("describeExpected",
"describeFound", etc.) currently aren't exposed. They may become exposed
in the future if there is enough demand.
8 years ago
David Majda 999cc7be74 Expectation refactoring 5/7: Refactor "buildMesage"
Mostly just extract few functions, increasing readability.
8 years ago
David Majda 319931876d Expectation refactoring 4/7: Generate descriptions dynamically
Instead of pre-generating expectation descriptions when generating
parsers, generate them dynamically from structured information contained
in the expectations.

This change makes descriptions a presentation-only concept. It also
makes generated parsers smaller.
8 years ago
David Majda 22cb123479 Expectation refactoring 3/7: Change expectation processing
Before this commit, expectations were sorted and de-duplicated before
they were passed to "buildMessage" and exposed in the "expected"
property of syntax errors. This commit moves this processing into
"buildMessage" and rewrites it to process only expectation descriptions.
This means expectations exposed in the "expected" property are "raw"
(not sorted and de-duplicated).

This change will allow us to get rid of the "description" property of
expectations and compute descriptions dynamically from structured
information in the expectations. This will make descriptions a
presentation-only concept. It will also make generated parsers smaller.

Note that to keep expectations in the "expected" property sorted even
without the "description" property, some sorting scheme based on
structured information in the expectations would have to be devised,
which would complicate things with only a little benefit. Therefore I
chose to keep the expectations there "raw".
8 years ago
David Majda c6e8c53f1b Expectation refactoring 2/7: Restructure "class" expectations
Changes:

  * Remove the "value" property (it is replaced by other properties).

  * Add the "parts", "inverted", and "ignoreCase" properties (which
    allow more structured access to expectation data).
8 years ago
David Majda eda2a34c7f Expectation refactoring 1/7: Restructure "literal" expectations
Changes:

  * Rename the "value" property to "text" (because it doesn't contain
    the whole value, which also includes the case sensitivity flag).

  * Add the "ignoreCase" property (which was missing).
8 years ago
David Majda d48983dd6a Don't use the "i" suffix for case-insensitive class descriptions
If the described class is case-sensitive, nothing changes.

If the described class is case-insensitive, its description doesn't
indicate that anymore. The indication was awkward and it was meaningful
only for parser users familiar with PEG.js grammar syntax (typically a
minority). For cases where case insensitivity indication is vital, named
rules can be used to customize the reporting.

Note that literal descriptions already ignore the case-sensitivity flag;
this commit only makes things consistent.
8 years ago
David Majda b2d7f9e02f Fix comment typo 8 years ago
David Majda d73a5208a0 Simplify various escaping functions
Simplify regexps that specify ranges of characters to escape with "\xXX"
and "\uXXXX" in various escaping functions. Until now, these regexps
were (mostly) mutually exclusive with more selective regexps applied
before them, but this became a maintenance headache. I decided to
abandon the exclusivity, which allowed to simplify these regexps (at the
cost of introducing an ordering dependency).
8 years ago
David Majda b31436d778 Escape also DEL (U+007F) when generating JavaScript strings & regexps
It is a control character.
8 years ago
David Majda 1f7efd57c0 Remove various JSHint-related cruft
We use ESLint now, which is smarter about some things.
8 years ago
David Majda 75cedcb7d8 Harmonize found string escaping with expectation escaping
Change how found strings are escaped when building syntax error
messages:

  * Do not escape non-ASCII characters (U+0100-U+FFFF). They are
    typically more readable in their raw form.

  * Escape DEL (U+007F). It is a control character.

  * Escape NUL (U+0000) as "\0", not "\x00".

  * Do not use less known shortcut escape sequences ("\b", "\f"), only the
    well-known ones ("\0", "\t", "\n", "\r").

These changes mirror expectation escaping changes done in
4fe682794d.

Part of work on #428.
8 years ago
David Majda 6b60896216 Revert "Remove info about found string from syntax errors"
This reverts commit 25ab98027d.

Part of work on #428.
8 years ago
David Majda 4fe682794d Improve expression descriptions in error messages
Before this commit, descriptions of literals used in error messages were
built by applying JavaScript string escaping to their values, making the
descriptions look like JavaScript strings. Descriptions of character
classes were built using their raw text. These approaches were mutually
inconsistent and lead to descriptions which were over-escaped and not
necessarily human-friendly (in case of literals) or coupled with details
of the grammar (in case of character classes).

This commit changes description building code in both cases and unifies
it. The intent is to generate human-friendly descriptions of matched
expressions which are clean, unambiguous, and which don't escape too
many characters, while handling special characters such as newlines
well.

Fixes #127.
8 years ago
David Majda 2fd77b96fc Revert "Use literal raw text in error messages"
I no longer think that using raw literal texts in error messages is the
right thing to do. The main reason is that it couples error messages
with details of the grammar such as use of single or double quotes in
literals. A better solution is coming in the next commit.

This reverts commit 69a0f769fc.
8 years ago
David Majda f4504a93fe Rename the "buildParser" function to "generate"
In most places, we talk about "generating a parser", not "building a
parser", which the function name should reflect. Also, mentioning a
parser in the name is not necessary as in case of a parser generator
it's pretty clear what is generated.
8 years ago
David Majda 0847a69643 Rename the "PEG" variable to "peg"
So far, PEG.js was exported in a "PEG" global variable when no module
loader was detected. The same variable name was also conventionally used
when requiring it in Node.js or otherwise referring to it. This was
reflected in various places in the code, documentation, examples, etc.

This commit changes the variable name to "peg" and fixes all relevant
occurrences. The main reason for the change is that in Node.js, modules
are generally referred to by lower-case variable names, so "PEG" was
sticking out when used in Node.js projects.
8 years ago
David Majda 057a93fbc7 Move the "Generated by ..." comment out of wrapping functions
The wrapping functions are also generated by PEG.js, so the comment
should be above them to mark them as such. This shouldn't cause any
problems technically.
8 years ago
David Majda f934199fba Simplify code which generates parser wrappers 8 years ago
David Majda 810567d865 UMD parsers: Allow specifying parser dependencies
Introduce two ways of specifying parser dependencies: the "dependencies"
option of PEG.buildParser and the -d/--dependency CLI option. Specified
dependencies are translated into AMD dependencies and Node.js's
"require" calls when generating an UMD parser.

Part of work on #362.
8 years ago
David Majda fe6ce38d08 UMD parsers: Regenerate lib/parser.js
Part of work on #362.
8 years ago
David Majda b87268ade6 UMD parsers: Allow generating parsers in UMD format from the API
Introduce new "format" and "exportVar" options to PEG.buildParser which
together allow generating parsers in UMD format.

Part of work on #362.
8 years ago
David Majda ab0e85b006 UMD parsers: Refactor "generateWrapper"
Extract "generateWrapper" code which generates code of the intro and the
returned parser object into helper functions. This is pure refactoring,
generated parser code is exactly the same as before.

This change will make it easier to modifiy "generateWrapper" to produce
UMD modules.

Part of work on #362.
8 years ago
David Majda 7f8b3f7012 UMD parsers: Generate parser wrapper separately from its toplevel code
Code which was at the toplevel of the "generateJS" function in the code
generator is now split into "generateToplevel" (which genreates parser
toplevel code) and "generateWrapper" (which generates a wrapper around
it). This is pure refactoring, generated parser code is exactly the same
as before.

This change will make it easier to modifiy the code genreator to produce
UMD modules.

Part of work on #362.
8 years ago