| @@ -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']}, | |||