25 Commits (73de2c9384159b6afe9153d169e6258b45126c66)

Author SHA1 Message Date
David Majda 73de2c9384 Switch from Jasmine to Mocha & Chai
The switch is mostly mechanical, with assertions translated 1:1. The
biggest non-mechanical part is rewriting Jasmine custom matchers as Chai
helpers. The matchers were streamlined and simplified in the process and
their messages were made more in line with messages produced by built-in
Chai helpers.

Fixes #409.
7 years ago
David Majda 6c3565fc96 Code style: Fix ESLint "func-style" errors
Part of #407.
8 years ago
David Majda 1870308afb Code style: Fix ESLint "object-shorthand" errors
Part of #407.
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 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 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 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 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 5c40fff136 Pass spec code through Babel before serving it to the browser
This will allow to use ES2015 constructs in spec code.

The change required introducing a small server, which serves both PEG.js
and spec code passed through Babel and bundled together. This allowed to
convert the specs to regular modules and get rid of the hackery that was
previously needed to make them run both in Node.js and in the browser.

Note the specs no longer exercise the browser version. This will allow
to spec PEG.js internals in the future.

See #442.
8 years ago
David Majda df5f86103e Replace suitable for loops with Array methods (in /spec)
See #441.
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 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.
8 years ago
David Majda 04f8b50f80 Fix ESLint errors in spec/api/plugin-api.spec.js
Fix the following errors:

   59:35  error  "options" is defined but never used  no-unused-vars
   91:11  error  "plugin" is defined but never used   no-unused-vars
  102:35  error  "options" is defined but never used  no-unused-vars
  128:35  error  "options" is defined but never used  no-unused-vars

Note that ESLint revealed a real problem where the test supposedly
verifying receiving options by a plugin didn't actually verify anything.
8 years ago
David Majda 768ece28e6 Use ESLint instead of JSHint
Implement the swap and change various directives in the source code. The
"make hint" target becomes "make lint".

The change leads to quite some errors being reported by ESLint. These
will be fixed in subsequent commits.

Note the configuration enables just the recommended rules. Later I plan
to enable more rules to enforce the coding standard. The configuration
also sets the environment to "node", which is far from ideal as the
codebase contains a mix of CommonJS, Node.js and browser code. I hope to
clean this up at some point.
8 years ago
David Majda 69a0f769fc Use literal raw text in error messages
Fixes #127.
9 years ago
David Majda 60ebd9e695 Simplify JSHint directives 9 years ago
David Majda 969d39e8d9 Remove trailing commas in object literals
They broke IE 8-9.
9 years ago
Arlo Breault 12c169e7b5 Convert PEG.js code to strict mode
* Issues #323
9 years ago
David Majda da57118a43 Implement basic support for tracing
Parsers can now be generated with support for tracing using the --trace
CLI option or a boolean |trace| option to |PEG.buildParser|. This makes
them trace their progress, which can be useful for debugging. Parsers
generated with tracing support are called "tracing parsers".

When a tracing parser executes, by default it traces the rules it enters
and exits by writing messages to the console. For example, a parser
built from this grammar:

  start = a / b
  a = "a"
  b = "b"

will write this to the console when parsing input "b":

  1:1 rule.enter start
  1:1 rule.enter   a
  1:1 rule.fail    a
  1:1 rule.enter   b
  1:2 rule.match   b
  1:2 rule.match start

You can customize tracing by passing a custom *tracer* to parser's
|parse| method using the |tracer| option:

  parser.parse(input, { trace: tracer });

This will replace the built-in default tracer (which writes to the
console) by the tracer you supplied.

The tracer must be an object with a |trace| method. This method is
called each time a tracing event happens. It takes one argument which is
an object describing the tracing event.

Currently, three events are supported:

  * rule.enter -- triggered when a rule is entered
  * rule.match -- triggered when a rule matches successfully
  * rule.fail  -- triggered when a rule fails to match

These events are triggered in nested pairs -- for each rule.enter event
there is a matching rule.match or rule.fail event.

The event object passed as an argument to |trace| contains these
properties:

  * type   -- event type
  * rule   -- name of the rule the event is related to
  * offset -- parse position at the time of the event
  * line   -- line at the time of the event
  * column -- column at the time of the event
  * result -- rule's match result (only for rule.match event)

The whole tracing API is somewhat experimental (which is why it isn't
documented properly yet) and I expect it will evolve over time as
experience is gained.

The default tracer is also somewhat bare-bones. I hope that PEG.js user
community will develop more sophisticated tracers over time and I'll be
able to integrate their best ideas into the default tracer.
9 years ago
David Majda 84473db3ce Specs cleanup: Small description cleanups/fixes 9 years ago
David Majda 94c8b08acf Specs cleanup: Implement plugin API specs 10 years ago