Browse Source

Merge branch 'TMiguelT-nearley-es6'

tags/gm/2021-09-23T00Z/github.com--lark-parser-lark/0.10.0
Erez Sh 4 years ago
parent
commit
fe7965999b
6 changed files with 71 additions and 35 deletions
  1. +1
    -20
      README.md
  2. +1
    -1
      docs/features.md
  3. +1
    -0
      docs/index.md
  4. +47
    -0
      docs/nearley.md
  5. +19
    -13
      lark/tools/nearley.py
  6. +2
    -1
      setup.py

+ 1
- 20
README.md View File

@@ -100,7 +100,7 @@ See more [examples here](https://github.com/lark-parser/lark/tree/master/example
- **Python 2 & 3** compatible
- Automatic line & column tracking
- Standard library of terminals (strings, numbers, names, etc.)
- Import grammars from Nearley.js
- Import grammars from Nearley.js ([read more](/docs/nearley.md))
- Extensive test suite [![codecov](https://codecov.io/gh/erezsh/lark/branch/master/graph/badge.svg)](https://codecov.io/gh/erezsh/lark)
- MyPy support using type stubs
- And much more!
@@ -159,25 +159,6 @@ Check out the [JSON tutorial](/docs/json_tutorial.md#conclusion) for more detail

Using Lark? Send me a message and I'll add your project!

### How to use Nearley grammars in Lark

Lark comes with a tool to convert grammars from [Nearley](https://github.com/Hardmath123/nearley), a popular Earley library for Javascript. It uses [Js2Py](https://github.com/PiotrDabkowski/Js2Py) to convert and run the Javascript postprocessing code segments.

Here's an example:
```bash
git clone https://github.com/Hardmath123/nearley
python -m lark.tools.nearley nearley/examples/calculator/arithmetic.ne main nearley > ncalc.py
```

You can use the output as a regular python module:

```python
>>> import ncalc
>>> ncalc.parse('sin(pi/4) ^ e')
0.38981434460254655
```


## License

Lark uses the [MIT license](LICENSE).


+ 1
- 1
docs/features.md View File

@@ -21,7 +21,7 @@
# Extra features

- Import rules and tokens from other Lark grammars, for code reuse and modularity.
- Import grammars from Nearley.js
- Import grammars from Nearley.js ([read more](/docs/nearley.md))
- CYK parser

### Experimental features


+ 1
- 0
docs/index.md View File

@@ -49,6 +49,7 @@ $ pip install lark-parser
* [Visitors & Transformers](visitors.md)
* [Classes](classes.md)
* [Cheatsheet (PDF)](lark_cheatsheet.pdf)
* [Importing grammars from Nearley](nearley.md)
* Discussion
* [Gitter](https://gitter.im/lark-parser/Lobby)
* [Forum (Google Groups)](https://groups.google.com/forum/#!forum/lark-parser)

+ 47
- 0
docs/nearley.md View File

@@ -0,0 +1,47 @@
# Importing grammars from Nearley

Lark comes with a tool to convert grammars from [Nearley](https://github.com/Hardmath123/nearley), a popular Earley library for Javascript. It uses [Js2Py](https://github.com/PiotrDabkowski/Js2Py) to convert and run the Javascript postprocessing code segments.

## Requirements

1. Install Lark with the `nearley` component:
```bash
pip install lark-parser[nearley]
```

2. Acquire a copy of the nearley codebase. This can be done using:
```bash
git clone https://github.com/Hardmath123/nearley
```

## Usage

Here's an example of how to import nearley's calculator example into Lark:

```bash
git clone https://github.com/Hardmath123/nearley
python -m lark.tools.nearley nearley/examples/calculator/arithmetic.ne main nearley > ncalc.py
```

You can use the output as a regular python module:

```python
>>> import ncalc
>>> ncalc.parse('sin(pi/4) ^ e')
0.38981434460254655
```

The Nearley converter also supports an experimental converter for newer JavaScript (ES6+), using the `--es6` flag:

```bash
git clone https://github.com/Hardmath123/nearley
python -m lark.tools.nearley nearley/examples/calculator/arithmetic.ne main nearley --es6 > ncalc.py
```

## Notes

- Lark currently cannot import templates from Nearley

- Lark currently cannot export grammars to Nearley

These might get added in the future, if enough users ask for them.

+ 19
- 13
lark/tools/nearley.py View File

@@ -1,8 +1,9 @@
"Converts between Lark and Nearley grammars. Work in progress!"
"Converts Nearley grammars to Lark"

import os.path
import sys
import codecs
import argparse


from lark import Lark, InlineTransformer
@@ -137,7 +138,7 @@ def _nearley_to_lark(g, builtin_path, n2l, js_code, folder_path, includes):
return rule_defs


def create_code_for_nearley_grammar(g, start, builtin_path, folder_path):
def create_code_for_nearley_grammar(g, start, builtin_path, folder_path, es6=False):
import js2py

emit_code = []
@@ -160,7 +161,10 @@ def create_code_for_nearley_grammar(g, start, builtin_path, folder_path):
for alias, code in n2l.alias_js_code.items():
js_code.append('%s = (%s);' % (alias, code))

emit(js2py.translate_js('\n'.join(js_code)))
if es6:
emit(js2py.translate_js6('\n'.join(js_code)))
else:
emit(js2py.translate_js('\n'.join(js_code)))
emit('class TransformNearley(Transformer):')
for alias in n2l.alias_js_code:
emit(" %s = var.get('%s').to_python()" % (alias, alias))
@@ -173,18 +177,20 @@ def create_code_for_nearley_grammar(g, start, builtin_path, folder_path):

return ''.join(emit_code)

def main(fn, start, nearley_lib):
def main(fn, start, nearley_lib, es6=False):
with codecs.open(fn, encoding='utf8') as f:
grammar = f.read()
return create_code_for_nearley_grammar(grammar, start, os.path.join(nearley_lib, 'builtin'), os.path.abspath(os.path.dirname(fn)))
return create_code_for_nearley_grammar(grammar, start, os.path.join(nearley_lib, 'builtin'), os.path.abspath(os.path.dirname(fn)), es6=es6)

def get_arg_parser():
parser = argparse.ArgumentParser('Reads Nearley grammar (with js functions) outputs an equivalent lark parser.')
parser.add_argument('nearley_grammar', help='Path to the file containing the nearley grammar')
parser.add_argument('start_rule', help='Rule within the nearley grammar to make the base rule')
parser.add_argument('nearley_lib', help='')
parser.add_argument('--es6', help='Enable experimental ES6 support', action='store_true')
return parser

if __name__ == '__main__':
if len(sys.argv) < 4:
print("Reads Nearley grammar (with js functions) outputs an equivalent lark parser.")
print("Usage: %s <nearley_grammar_path> <start_rule> <nearley_lib_path>" % sys.argv[0])
sys.exit(1)

fn, start, nearley_lib = sys.argv[1:]

print(main(fn, start, nearley_lib))
parser = get_arg_parser()
args = parser.parse_args()
print(main(fn=args.nearley_grammar, start=args.start_rule, nearley_lib=args.nearley_lib, es6=args.es6))

+ 2
- 1
setup.py View File

@@ -15,7 +15,8 @@ setup(
install_requires = [],

extras_require = {
"regex": ["regex"]
"regex": ["regex"],
"nearley": ["js2py"]
},

package_data = {'': ['*.md', '*.lark'], 'lark-stubs': ['*.pyi']},


Loading…
Cancel
Save