Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to auto-unwrap rule results #505

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

raphinesse
Copy link

@raphinesse raphinesse commented Apr 8, 2020

Summary

This PR adds an option @autoUnwrap. If enabled, rules that consist of a single symbol will have their results unwrapped automatically (like adding {% id %} to them).

Update: In the meantime, I also implemented this feature as a stand-alone package: nearley-auto-unwrap.

Motivation

@autoUnwrap true

example	-> FOO ( BAR | BAZ )
FOO	-> "foo"i
BAR	-> "bar"i
BAZ	-> "baz"i

Before this PR, parsing the string foobar with the above grammar would yield the following result:

[ [ 'foo' ], [ [ 'bar' ] ] ]

With this PR, the result will be

[ 'foo', 'bar' ]

IMHO this makes postprocessing much more intuitive or completely alleviates the need for it in some cases.

@autoUnwrap true also fixes #498. It generally improves macro usability and makes nested macros feasible:

@autoUnwrap true

id[x]	-> $x
main	-> id[id["foobar"]]

The result of parsing foobar with above grammar is "foobar" while with @autoUnwrap false the result is [[[[[ "foobar" ]]]]] (that is a nesting depth of 5).

Implementation

The implementation is pretty straight forward: during compilation, if @autoUnwrap is true, modify the postprocessing property of every rule that only has one token, such that the original postprocessing function will be called with data[0] instead of data. Thus, there is no need for additional rule properties and there is no runtime overhead compared to manually calling id.

In more detail, if an affected rule had the postprocess property fn, we will replace it with id._auto(fn) where

id._auto = fn => {
  return fn
    ? (d, l, r) => fn(id(d), l, r)
    : id;
};

I have decided to attach this helper function to id to avoid any naming collisions with custom preprocessors of existing grammars. The name also makes some sense since it's an automatic application of the id function.

TODOs

There are still a few things left to do. I will address those if this feature is wanted by the maintainers:

  • Documentation
  • Tests
  • Support for all preprocessors (currently only supports JS)

I hope you think of this as a useful addition. I really liked writing a parser using nearley and this feature would resolve the only thing that bothered me when using it.

@raphinesse
Copy link
Author

Seems the CI is failing since the docs have not been built after the release of v2.19.1

@raphinesse raphinesse marked this pull request as ready for review June 1, 2020 06:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Macro argument expansion is wrapped in array
1 participant