Browse Source

Merge branch 'TMiguelT-nearley-es6'

tags/gm/2021-09-23T00Z/github.com--lark-parser-lark/0.10.0
Erez Sh 5 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 - **Python 2 & 3** compatible
- Automatic line & column tracking - Automatic line & column tracking
- Standard library of terminals (strings, numbers, names, etc.) - 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) - 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 - MyPy support using type stubs
- And much more! - 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! 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 ## License


Lark uses the [MIT license](LICENSE). Lark uses the [MIT license](LICENSE).


+ 1
- 1
docs/features.md View File

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


- Import rules and tokens from other Lark grammars, for code reuse and modularity. - 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 - CYK parser


### Experimental features ### Experimental features


+ 1
- 0
docs/index.md View File

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




from lark import Lark, InlineTransformer 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 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 import js2py


emit_code = [] 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(): for alias, code in n2l.alias_js_code.items():
js_code.append('%s = (%s);' % (alias, code)) 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):') emit('class TransformNearley(Transformer):')
for alias in n2l.alias_js_code: for alias in n2l.alias_js_code:
emit(" %s = var.get('%s').to_python()" % (alias, alias)) 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) 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: with codecs.open(fn, encoding='utf8') as f:
grammar = f.read() 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 __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 = [], install_requires = [],


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


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


Loading…
Cancel
Save