Commit graph

281 commits

Author SHA1 Message Date
David Majda ffd90a8c9e Label scope specs: Add negative specs (sequences)
So far, semantic predicate and action specs which verified scope of
labels from containing or outer sequences exercised only cases where
label variables were defined. This commit adds also some negative cases.

The idea comes from @Mingun.
2016-03-06 17:29:24 +01:00
David Majda 7229318671 Label scope specs: Don't exercise all expression types
Semantic predicate and action specs which verified scope of labels from
outer sequences exercised all relevant expression types. This is not
needed as the behavior is common for all expression types and no extra
code needs to be written to make it work for each of them.

This commit changes the specs to verify scope of labels from outer
sequences using only one expression type.
2016-03-06 17:29:20 +01:00
David Majda a20d04edf4 Label scope specs: Remove redundant sequence elements
Semantic predicate specs which verified scope of labels from containing
sequences used 3 elements where 1 is enough.

This commit removes the redundant elements.
2016-03-06 17:29:16 +01:00
David Majda 6bc91c010d Label scope specs: Tweak spec descriptions 2016-03-06 17:29:15 +01:00
David Majda 921f1fa8fa Label scope specs: Tweak suite descriptions 2016-03-06 17:29:12 +01:00
David Majda 5c5f79519a Label scope specs: Simplify semantic predicate and action specs
Semantic predicate and action specs which verified label scope used
repetitive "it" blocks. Rewrite them to use just one "it" block and a
list of testcases. This makes them more concise.
2016-03-06 17:29:11 +01:00
David Majda 31e7147081 Label scope specs: No result checks in semantic predicate specs
Semantic predicate specs which verified label scope also checked parser
results. This is not necessary because for the purpose of these specs it
is enough to verify that label variables have correct values, which is
done in predicate code already.

This commit removes parser result checks from these specs.
2016-03-06 17:28:37 +01:00
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).
2016-02-05 17:53:13 +01:00
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.
2016-01-29 14:50:38 +01:00
David Majda 00faf20fe1 Fix ESLint errors in spec/behavior/generated-parser-behavior.spec.js
Fix the following errors:

   24:46  error  Unexpected trailing comma  comma-dangle
  403:26  error  Unexpected trailing comma  comma-dangle
  414:26  error  Unexpected trailing comma  comma-dangle
2016-01-22 14:15:42 +01:00
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.
2016-01-22 14:15:34 +01:00
David Majda 47ac688ce9 Fix ESLint errors in spec/api/generated-parser-api.spec.js
Fix the following errors:

  65:20  error  Unexpected console statement  no-console
  66:20  error  Unexpected console statement  no-console
  67:20  error  Unexpected console statement  no-console
  68:20  error  Unexpected console statement  no-console
  69:20  error  Unexpected console statement  no-console
  70:20  error  Unexpected console statement  no-console
2016-01-22 14:03:08 +01:00
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.
2016-01-22 13:55:42 +01:00
David Majda 69a0f769fc Use literal raw text in error messages
Fixes #127.
2015-09-18 10:56:05 -07:00
David Majda 36eb7b81b5 Use single quotes for |rawText| in parser specs
PEG.js convention is to use single quotes for code and |rawText| *is* a
piece of code (originally).
2015-09-18 10:17:57 -07:00
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.
2015-09-18 10:01:15 -07:00
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
2015-09-11 15:09:42 +02:00
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.
2015-09-11 14:58:53 +02:00
David Majda ebf5d969b2 s/alwaysAdvancesOnSuccess/alwaysConsumesOnSuccess/
Matches terminology change from the previous commit.
2015-09-04 17:35:37 +02:00
David Majda 6ff005786c Talk about "consuming input", not "advancing parser position"
It's shorter, less technical, and more understandible.
2015-09-04 17:23:42 +02:00
David Majda 60ebd9e695 Simplify JSHint directives 2015-09-04 16:52:38 +02:00
David Majda 20a4fb2e7f Update version to 0.9.0 2015-08-30 08:22:26 +02:00
David Majda a4b4a57569 Custom tracers specs: s/'/"/
The convention is to use single quotes only for strings containing code.
2015-08-21 17:38:04 +02:00
David Majda 1d38b973ee Custom tracers specs: Simplify code slightly 2015-08-21 17:36:34 +02:00
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.
2015-08-21 17:32:37 +02:00
David Majda e8b379f945 Rewrite |trace| option tests to avoid using |console|
This makes them cleaner and also makes them work in IE 8-10.
2015-08-21 17:32:23 +02:00
David Majda 969d39e8d9 Remove trailing commas in object literals
They broke IE 8-9.
2015-08-21 16:02:13 +02:00
David Majda a4772376fb Renumber bytecode instructions sequentially 2015-08-18 10:57:50 +02:00
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.
2015-08-17 10:58:37 +02:00
David Majda 703a352985 Change few testcase descriptions
Reaction to changes in 130cbcfaa3.
2015-08-06 16:38:38 +02:00
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
2015-08-06 16:32:08 +02:00
David Majda 317059760a Fix incorrect pass name in a spec description 2015-07-17 15:37:45 +02:00
David Majda 373f48c10f Fix small error in two testcases
Pointed out by @Mingun:

  6ce97457bf (commitcomment-10548605)
2015-07-17 15:37:26 +02:00
David Majda 6f2c75f7d8 Label specs: Improve structure and descriptions 2015-07-17 14:16:46 +02:00
David Majda 8487c9a0ff Label specs: Add missing test case 2015-07-17 11:43:30 +02:00
David Majda f4385da177 Label specs: Unify formatting with other code 2015-07-17 11:36:35 +02:00
David Majda ddff5feea3 Label specs: Simplify and regularize block-scoped label specs
There is no need to test 3 labels from the outside scope, 1 is enough.
2015-07-17 11:28:15 +02:00
Arlo Breault 12c169e7b5 Convert PEG.js code to strict mode
* Issues #323
2015-06-12 17:34:59 -07:00
Arlo Breault 1a32ae7bd0 Make PEG global explicit in helpers 2015-06-12 17:33:12 -07:00
David Majda eaca5f0acf Add location information to |GrammarError|
This means all errors thrown by |PEG.buildParser| now have associated
location information.
2015-04-06 17:34:37 +02:00
David Majda 89146915ce Add location information to AST nodes
This will allow to add location information to |GrammarError| exceptions
thrown in various passes.
2015-04-06 17:34:37 +02:00
David Majda d1fe86683b Improve location info in tracing events
Replace |line|, |column|, and |offset| properties of tracing events with
the |location| property. It contains an object similar to the one
returned by the |location| function available in action code:

  {
    start: { offset: 23, line: 5, column: 6 },
    end:   { offset: 25, line: 5, column: 8 }
  }

For the |rule.match| event, |start| refers to the position at the
beginning of the matched input and |end| refers to the position after
the end of the matched input.

For |rule.enter| and |rule.fail| events, both |start| and |end| refer to
the current position at the time the rule was entered.
2015-04-04 10:04:09 +02:00
David Majda 065f4e1b75 Improve location info in syntax errors
Replace |line|, |column|, and |offset| properties of |SyntaxError| with
the |location| property. It contains an object similar to the one
returned by the |location| function available in action code:

  {
    start: { offset: 23, line: 5, column: 6 },
    end:   { offset: 25, line: 5, column: 8 }
  }

For syntax errors produced in the middle of the input, |start| refers to
the first unparsed character and |end| refers to the character behind it
(meaning the span is 1 character). This corresponds to the portion of
the input in the |found| property.

For syntax errors produced the end of the input, both |start| and |end|
refer to a character past the end of the input (meaning the span is 0
characters).

For syntax errors produced by calling |expected| or |error| functions in
action code the location info is the same as the |location| function
would return.
2015-04-04 10:04:04 +02:00
David Majda b1ad2a1f61 Rename |reportedPos| to |savedPos|
Preform the following renames:

  * |reportedPos| -> |savedPos| (abstract machine variable)
  * |peg$reportedPos| -> |peg$savedPos| (variable in generated code)
  * |REPORT_SAVED_POS| -> |LOAD_SAVED_POS| (instruction)
  * |REPORT_CURR_POS| -> |UPDATE_SAVED_POS| (instruction)

The idea is that the name |reportedPos| is no longer accurate after the
|location| change (seea the previous commit) because now both
|reportedPos| and |currPos| are reported to user code. Renaming to
|savedPos| resolves this inaccuracy.

There is probably some better name for the concept than quite generic
|savedPos|, but it doesn't come to me.
2015-04-03 16:26:34 +02:00
David Majda 4f7145e360 Improve location info available in action code
Replace |line|, |column|, and |offset| functions with the |location|
function. It returns an object like this:

  {
    start: { offset: 23, line: 5, column: 6 },
    end:   { offset: 25, line: 5, column: 8 }
  }

In actions, |start| refers to the position at the beginning of action's
expression and |end| refers to the position after the end of action's
expression. This allows one to easily add location info e.g. to AST
nodes created in actions.

In predicates, both |start| and |end| refer to the current position.

Fixes #246.
2015-04-03 16:26:34 +02:00
David Majda 889563a0ae Add missing ";" 2015-04-02 14:35:06 +02:00
David Majda 3473c6cb64 Remove extra whitespace 2015-04-02 14:34:26 +02:00
David Majda fb320c4c59 Fix small errors in Jasmine matcher messages 2015-04-02 14:32:31 +02:00
David Majda d7fc0b5c3b Implement infinite loop detection
Fixes #26.
2015-04-01 12:21:43 +02:00
David Majda 6ce97457bf Fix left recursion detection
So far, left recursion detector assumed that left recursion occurs only
when the recursive rule is at the very left-hand side of rule's
expression:

  start = start

This didn't catch cases like this:

  start = "a"? start

In general, if a rule reference can be reached without consuming any
input, it can lead to left recursion. This commit fixes the detector to
consider that.

Fixes #190.
2015-04-01 10:10:51 +02:00
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.
2015-03-30 14:00:19 +02:00
David Majda fb5f6c6ee9 Make labels behave like block-scoped variables
Action and predicate code can now see variables defined in expressions
"above" them.

Based on a pull request by Bryon Vandiver (@asterick):

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

Fixes #316.
2015-02-13 14:10:32 +01:00
David Majda 73795a65cc Behavior specs cleanup: Add group specs
While groups don't create separate nodes on the AST level, they exist
as concept on the user level, so they should be specified.
2015-01-26 09:54:29 +01:00
David Majda e306b58443 Behavior specs cleanup: Improve error reporting specs 2015-01-26 09:54:29 +01:00
David Majda e9d038547d Behavior specs cleanup: Improve semantic predicate specs
Note that use of |text| inside semantic predicate code is no longer
tested and officially supported.
2015-01-26 09:54:29 +01:00
David Majda 3d9600b81b Behavior specs cleanup: Improve action specs 2015-01-26 09:54:29 +01:00
David Majda b623396cb8 Behavior specs cleanup: Improve initializer specs
Note that use of |text|, |offset|, |line|, and |column| inside
initializer code is no longer tested and officially supported.
2015-01-26 09:54:29 +01:00
David Majda fee58d0806 Behavior specs cleanup: Improve rule specs 2015-01-26 09:54:29 +01:00
David Majda fa70e70ddf Behavior specs cleanup: Improve choice specs 2015-01-24 20:04:49 +01:00
David Majda b3828919e2 Behavior specs cleanup: Improve sequence specs 2015-01-24 20:02:06 +01:00
David Majda 548209b48b Behavior specs cleanup: Improve simple predicate specs 2015-01-24 19:57:49 +01:00
David Majda 52144e48cb Behavior specs cleanup: Improve label specs 2015-01-24 19:57:49 +01:00
David Majda c5c44b9d0c Behavior specs cleanup: Improve text specs 2015-01-24 19:57:49 +01:00
David Majda bb708490a0 Behavior specs cleanup: Improve one or more specs 2015-01-24 19:57:49 +01:00
David Majda b9a3b44cf2 Behavior specs cleanup: Improve zero or more specs 2015-01-24 19:57:49 +01:00
David Majda c377eff876 Behavior specs cleanup: Improve optional specs 2015-01-24 19:57:48 +01:00
David Majda ade2c249f2 Behavior specs cleanup: Improve rule reference specs 2015-01-24 19:57:48 +01:00
David Majda 936d6453a5 Behavior specs cleanup: Improve dot specs 2015-01-24 19:57:48 +01:00
David Majda 74be12c657 Behavior specs cleanup: Improve character class specs 2015-01-24 19:57:48 +01:00
David Majda 54191fbf12 Behavior specs cleanup: Improve literal specs 2015-01-24 19:57:48 +01:00
David Majda 2faff0000e Behavior specs cleanup: Make |toParse| work without expected value
This means we can assert just "this string parses" and ignore the
returned value.
2015-01-12 16:40:28 +01:00
David Majda ce91921a1d Behavior specs cleanup: Don't describe named rules separately
While naming a rule creates a separate node on the AST level, it's not a
new concept on the user level, so its specs should be a part of rule
specs.
2015-01-12 16:40:28 +01:00
David Majda a597e65a66 Behavior specs cleanup: Reorder toplevel |describe| blocks
Reorder toplevel |describe| blocks to more closely match ordering used
in the PEG.js grammar and elsewhere in PEG.js.
2015-01-12 16:40:28 +01:00
David Majda 3308807d22 Behavior specs cleanup: Move spec/api/generated-parser-behavior.spec.js
Move spec/api/generated-parser-behavior.spec.js to
spec/behavior/generated-parser-behavior.spec.js. It's not an API test,
strictly speaking.
2015-01-12 16:39:56 +01:00
David Majda 84473db3ce Specs cleanup: Small description cleanups/fixes 2015-01-12 14:18:11 +01:00
David Majda 178d56699a Update GitHub project URLs
See https://groups.google.com/d/msg/pegjs/4a6zWKQSG6U/n8Pm257Lz6wJ.

I didn't update CHANGELOG.md as I consider issue URLs there historical artifacts
;-)
2014-11-28 13:56:47 +01:00
David Majda 5a2ca2abc7 Add two missing blank lines 2014-06-07 14:20:53 +02:00
David Majda 5ce5f7a612 Specs cleanup: Use raw node types in |generateBytecode| specs
Use raw node types instead of humanized node names in |generateBytecode|
specs. This corresponds more closely to the level the specs are written
at.
2014-06-07 14:17:11 +02:00
David Majda 0977dd37a3 Reordering in visitors and their specs
Reorder visiting functions and their specs to more closely match
ordering used in the PEG.js grammar.
2014-06-07 14:06:42 +02:00
David Majda 850ddf5889 Specs cleanup: Simplify compiler passes specs
After 898a7b5a2d the specs mostly tested
the visitor implementation, not actual code in the passes.
2014-06-07 10:50:55 +02:00
David Majda e101e1b6f3 Specs cleanup: Implement generated parser API specs
The generated parser API specs are mostly extracted from
generated-parser.spec.js, which got renamed to
generated-parser-behavior.spec.js to better reflect its purpose.
2014-06-03 20:16:27 +02:00
David Majda 94c8b08acf Specs cleanup: Implement plugin API specs 2014-06-03 20:16:27 +02:00
David Majda d0ff834a3d Specs cleanup: Implement PEG.js API specs
Some parts were previously part of generated parser specs, these were
moved.
2014-06-03 20:16:27 +02:00
David Majda 0306a76152 Specs cleanup: Rename & simplify |varyAll|
Rename |varyAll| to |varyOptimizationOptions|, because that's what the
function does. Simplify as we don't need a fully generic solution.
2014-06-03 20:16:16 +02:00
David Majda 3d637173ee Specs cleanup: Split specs into unit and API specs
Unit specs are unit tests of internal stuff. API specs are tests of the
user-visible APIs and behavior.

I think it makes sense to make this distinction because then the public
API line is more clearly visible e.g. when using the specs as
documentation.
2014-05-23 12:57:41 +02:00
David Majda dad1207c46 Improve semantics of the TEXT bytecode instruction
The TEXT instruction now replaces position at the top of the stack with
the input from that position until the current position. This is simpler
and cleaner semantics than the previous one, where TEXT also popped an
additional value from the stack and kept the position there.
2014-05-16 13:30:03 +02:00
David Majda a815a8b902 Implement additional PUSH_* bytecode instructions
Implement the following bytecode instructions:

  * PUSH_UNDEFINED
  * PUSH_NULL
  * PUSH_FAILED
  * PUSH_EMPTY_ARRAY

These instructions push simple JavaSccript values to the stack directly,
without going through constants. This makes the bytecode slightly
shorter and the bytecode generator somewhat simpler.

Also note that PUSH_EMPTY_ARRAY allows us to avoid a hack which protects
the [] constant from modification.
2014-05-16 13:28:29 +02:00
David Majda c6f0818d49 Use sentence case consistently in {spec,benchmark}/README.md headers 2014-05-10 16:40:39 +02:00
David Majda f102814998 Rewrite spec/README.md
More clarity, better grammar (hopefully).
2014-05-09 15:09:53 +02:00
David Majda 24e1644c58 Convert spec/README to Markdown
It will look nicer on GitHub.
2014-05-09 14:37:05 +02:00
David Majda 11aab6374f s/head/first/ & s/tail/rest/ in a testcase
Makes the testcase in sync with example grammars.
2014-04-27 13:44:25 +02:00
David Majda d9354c4632 Standardize on 3 spaces before // comments 2014-04-27 13:42:05 +02:00
David Majda f3a83788aa Inline functions extracted just because of JSHint
Rather than extracting functions just because JSHint complained about
defining functions inside a loop, let's inline then and silence the
warning.
2014-04-27 13:31:49 +02:00
David Majda 39084496ca Expose the parser object in action/predicate code
The action/predicate code didn't have access to the parser object. This
was mostly a side effect actions/predicates being implemented as nested
functions, in which |this| is a reference to the global object (an ugly
JavaScript quirk). The initializer, being implemented differently, had
access to the parser object via |this|, but this was not documented.

Because having access to the parser object can be useful, this commits
introduces a new |parser| variable which holds a reference to it, is
visible in action/predicate/initializer code, and is properly
documented.

See also:

  https://groups.google.com/forum/#!topic/pegjs/Na7YWnz6Bmg
2014-04-19 21:00:40 +02:00
David Majda 7e3b4ec4f8 PEG.js grammar: Remove reserved word detection
This is mostly done for consistency with the JavaScript example grammar,
from which the |Identifier| rule is taken from. See the previous commit
for details.
2014-04-13 20:32:39 +02:00
David Majda e78ffbba9c PEG.js grammar: Improve the |Code| rule a bit
Instead of matching segments between blocks character by character,
match them as a whole. Also align the style with other similar rules
(e.g. the comment ones).
2014-04-06 15:02:51 +02:00
David Majda 64eb5faf54 PEG.js grammar: Fix line continuation handling in character classes
Before this commit, line continuations in character classes contributed
an empty string to the list of characters and character ranges matched
by a class. While this didn't lead to a buggy behavior with the current
code generator, the AST was wrong and the problem could have caused bugs
later.

This commit fixes the problem.
2014-04-06 14:53:57 +02:00
David Majda 421b8d6e51 Clean up parser specs 2014-04-04 20:40:09 +02:00
David Majda 6f2510e49e PEG.js grammar: Make rules with operators more generic 2014-04-04 11:25:21 +02:00
David Majda 45c29a886f PEG.js grammar: Extract the |SemanticPredicateExpression| rule
Semantic predicates are kind of |PrimaryExpression|, not kind of
|PrefixedExpression|. Therefore I extracted a rule for them and
referenced it from the |PrimaryExpression|.
2014-04-04 11:25:21 +02:00