262 Commits (b31436d778271fd71ad70521206515a76e0abb05)

Author SHA1 Message Date
David Majda b31436d778 Escape also DEL (U+007F) when generating JavaScript strings & regexps
It is a control character.
9 years ago
David Majda 1f7efd57c0 Remove various JSHint-related cruft
We use ESLint now, which is smarter about some things.
9 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.
9 years ago
David Majda 6b60896216 Revert "Remove info about found string from syntax errors"
This reverts commit 25ab98027d.

Part of work on #428.
9 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.
9 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.
9 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.
9 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.
9 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.
9 years ago
David Majda f934199fba Simplify code which generates parser wrappers 9 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.
9 years ago
David Majda fe6ce38d08 UMD parsers: Regenerate lib/parser.js
Part of work on #362.
9 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.
9 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.
9 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.
9 years ago
David Majda 5e702b5901 lib/compiler.js: Fix indentation 9 years ago
David Majda ce44c62f14 Support passing custom location info to "error" and "expected"
Based on a pull request by Konstantin (@YemSalat):

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

Resolves #390.
9 years ago
David Majda da2378d887 Rewrite handling of optional parameters
Instead of testing arguments.length to see whether an optional parameter
was passed to a function, compare its value to "undefined". This
approach has two advantages:

  * It is in line with handling of default parameters in ES6.

  * Optional parameters are actually spelled out in the parameter
    list.

There is also one important disadvantage, namely that it's impossible to
pass "undefined" as an optional parameter value. This required a small
change in two tests.

Additional notes:

  * Default parameter values are set in assignments immediately
    after the function header. This reflects the fact that these
    assignments really belong to the parameter list (which is where they
    are in ES6).

  * Parameter values are checked against "void 0" in places where
    "undefined" can potentially be redefiend.
9 years ago
David Majda 0c39f1cf86 Fix labels leaking to outer scope
Labels in expressions like "(a:"a")" or "(a:"a" b:"b" c:"c")" were
visible to the outside despite being wrapped in parens. This commit
makes them invisible, as they should be.

Note this required introduction of a new "group" AST node, whose purpose
is purely to provide label scope isolation. This was necessary because
"label" and "sequence" nodes don't (and can't!) provide this isolation
themselves.

Part of a fix of #396.
9 years ago
David Majda 88f1d1369b Detect newlines using charCodeAt instead of charCode
In generated parsers, detect newlines using charCodeAt instead of
charCode. This should be slightly faster.
9 years ago
David Majda 18d266be67 Remove support for newlines other than "\n" and "\r\n"
Before this commit, generated parsers considered the following character
sequences as newlines:

  Sequence   Description
  ------------------------------
  "\n"       Unix
  "\r"       Old Mac
  "\r\n"     Windows
  "\u2028"   line separator
  "\u2029"   paragraph separator

This commit limits the sequences only to "\n" and "\r\n". The reason is
that nobody uses Unicode newlines or "\r" in practice.

A positive side effect of the change is that newline-handling code
became simpler (and likely faster).
9 years ago
David Majda e61c23c634 ESLint: Set environments better
Instead of setting ESLint environment to "node" globally, set it on
per-directory basis using separate .eslintrc.json files:

  Directory   Environment
  -----------------------
  bin         node
  lib         commonjs
  spec        jasmine

It was impossible to use this approach for the "benchmark" directory
which contains a mix of files used in various environments. For
benchmark/run, the environment is set inline. For the other files, as
well as spec/helpers.js, the globals are declared manually (it is
impossible to express how these files are used just by a list of
environments).

Fixes #408.
9 years ago
David Majda ddd4ac3787 Fix ESLint errors in lib/parser.js
Fix the following errors:

    31:9   error  "parser" is defined but never used    no-unused-vars
   406:14  error  "expected" is defined but never used  no-unused-vars
  1304:15  error  "s1" is defined but never used        no-unused-vars
  1386:15  error  "s1" is defined but never used        no-unused-vars
  1442:15  error  "s1" is defined but never used        no-unused-vars
9 years ago
David Majda 88c957c9e8 Fix ESLint errors in lib/compiler/passes/generate-js.js
Fix the following errors:

   65:11  error  Unexpected trailing comma  comma-dangle
  211:40  error  Unexpected trailing comma  comma-dangle
  223:27  error  Unexpected trailing comma  comma-dangle
  233:27  error  Unexpected trailing comma  comma-dangle
9 years ago
David Majda 475215aa52 Expose the AST node visitor builder via PEG.compiler.visitor
This is useful mainly for plugins which manipulate the AST.
9 years ago
David Majda d34faba59e Speed up deduplication of expectations
The expectation deduplication algorithm called |Array.prototype.splice|
to eliminate each individual duplication, which was slow. This caused
problems with grammar/input combinations that generated a lot of
expecations (see #377 for an example).

This commit replaces the algorithm with much faster one, eliminating the
problem.
9 years ago
David Majda a4a66a2e5b Switch from first/rest to head/tail in the PEG.js grammar
In the past year I worked on various grammars where first/rest or
head/tail were used as labels for parts of lists. I found I associate
head/tail with a list immediately, while in case of first/rest I have to
"parse" grammar rules for a while before understanding their structure.

Moreover, I tend to assume that rest is a list of the same thigs as
first, but I don't have such assumption in case of head/tail. This
assumption was in conflict with the grammar structure.

I'm not sure how much these observations are applicable to others, but I
decided to act on them and switch from first/rest to head/tail.
9 years ago
David Majda 69a0f769fc Use literal raw text in error messages
Fixes #127.
9 years ago
David Majda 25ab98027d Remove info about found string from syntax errors
The |found| property wasn't very useful as it mostly contained just one
character or |null| (the exception being syntax errors triggered by
|error| or |expected|). Similarly, the "but XXX found" part of the error
message (based on the |found| property) wasn't much useful and was
redundant in presence of location info.

For these reasons, this commit removes the |found| property and
corresponding part of the error message from syntax errors. It also
modifies error location info slightly to cover a range of 0 characters,
not 1 character (except when the error is triggered by |error| or
|expected|). This corresponds more precisely to the actual situation.

Fixes #372.
9 years ago
David Majda bbb4f006cd Report full rule chain in recursive rule errors
The idea came from a PR by @Mingun:

  https://github.com/pegjs/pegjs/pull/307
9 years ago
David Majda 491106c347 Report left recursion and infinite loops only as "possible"
A semantic predicate can prevent the parser to actually enter infinite
recursion or loop. This is undetectable at compile-time.
9 years ago
David Majda ebf5d969b2 s/alwaysAdvancesOnSuccess/alwaysConsumesOnSuccess/
Matches terminology change from the previous commit.
9 years ago
David Majda 48fe4d6580 Rename generate-javascript.js to generate-js.js
Short & sweet.
9 years ago
David Majda 575883586f Rename javascript.js to js.js
Short & sweet.
9 years ago
David Majda 20a4fb2e7f Update version to 0.9.0 9 years ago
David Majda 671c22e80f Avoid using |console| in default tracer and its tests when not defined
This makes default tracer and its tests work in IE 8-10.
9 years ago
David Majda 6d82422045 Remove trailing comma in an array literal
It caused an additional newline in generated parsers in IE 8.
9 years ago
David Majda 969d39e8d9 Remove trailing commas in object literals
They broke IE 8-9.
9 years ago
David Majda d5f93a8282 Fix comment typo 9 years ago
David Majda a4772376fb Renumber bytecode instructions sequentially 9 years ago
David Majda ad27a300a8 Fix left recursion detection in sequences
Report left recursion also in cases where the recursive rule invocation
is not a direct element of a sequence, but is wrapped inside an
expression.

Fixes #359.
9 years ago
David Majda cdeecf750f reportLeftRecursion: Change handling of the |visitedRules| array
Before this commit, the |reportLeftRecursion| pass was written in
functional style, passing the |visitedRules| array around as a parameter
and making a new copy each time a rule was visited. This apparently
caused performance problems in some deeply recursive grammars.

This commit makes it so that there is just one array which is shared
across all the visitor functions via a closure and modified as rules are
visited.

I don't like losing the functional style (it was elegant) but
performance is more important.

Fixes #203.
9 years ago
David Majda 4b154e177f Update character categories in grammars to Unicode 8.0.0 9 years ago
David Majda d7d7e87874 Make infinite loop and left recursion detectors work with named rules
Add missing |named| case to the visitor in lib/compiler/asts.js, which
makes the infinite loop and left recursion detectors work correctly with
named rules.

The missing case caused |make parser| to fail with:

  140:34: Infinite loop detected.
  make: *** [parser] Error 1
9 years ago
David Majda 130cbcfaa3 Rename asts.matchesEmpty to alwaysAdvancesOnSuccess and negate it
This makes it more clear that the function isn't about the input the
expression *matched* but about the input it *consumed* when it matched.

Based on a comment by @Mingun:

  https://github.com/pegjs/pegjs/pull/307#issuecomment-89512575
9 years ago
David Majda 5e6b5da4e9 Merge pull request #347 from mbaumgartl/errorstack
Add stack trace in engines based on V8
9 years ago
Marco Baumgartl 940a66fb38 Add stack trace in engines based on V8. Fixes #331 10 years ago
Arlo Breault 12c169e7b5 Convert PEG.js code to strict mode
* Issues #323
10 years ago
Arlo Breault 45e39c3ac8 Make generated parsers use strict mode
* Issue #324

 * JSHint complains about two possible strict violations. But are valid
   uses of `this`, so we suppress the warnings.
10 years ago
Arlo Breault 7285ccfd4e Remove block around initialize code
* In strict mode code, functions can only be declared at top level or
   immediately within another function.  This means functions defined in
   the initializer would throw.
10 years ago