@@ -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 [](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). | |||
@@ -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 | |||
@@ -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) |
@@ -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. |
@@ -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)) |
@@ -15,7 +15,8 @@ setup( | |||
install_requires = [], | |||
extras_require = { | |||
"regex": ["regex"] | |||
"regex": ["regex"], | |||
"nearley": ["js2py"] | |||
}, | |||
package_data = {'': ['*.md', '*.lark'], 'lark-stubs': ['*.pyi']}, | |||