From 9ec9acf11550c824338473e71b29891e7c8bbc8a Mon Sep 17 00:00:00 2001 From: Erez Sh Date: Sun, 23 Feb 2020 17:30:18 +0200 Subject: [PATCH] The standalone parser is now licensed under MPL2 (instead of GPL) (Issue #507) --- README.md | 2 +- examples/standalone/json_parser.py | 115 ++++++++++++++++------------- lark/tools/standalone.py | 25 ++----- 3 files changed, 73 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index dae1fca..0162e84 100644 --- a/README.md +++ b/README.md @@ -176,7 +176,7 @@ You can use the output as a regular python module: Lark uses the [MIT license](LICENSE). -(The standalone tool is under GPL2) +(The standalone tool is under MPL2) ## Contribute diff --git a/examples/standalone/json_parser.py b/examples/standalone/json_parser.py index 04fd6ac..5b3e06c 100644 --- a/examples/standalone/json_parser.py +++ b/examples/standalone/json_parser.py @@ -1,4 +1,4 @@ -# The file was automatically generated by Lark v0.8.0 +# The file was automatically generated by Lark v0.8.1 # # # Lark Stand-alone Generator Tool @@ -11,27 +11,16 @@ # # >>> LICENSE # -# This tool and its generated code use a separate license from Lark. -# -# It is licensed under GPLv2 or above. +# This tool and its generated code use a separate license from Lark, +# and are subject to the terms of the Mozilla Public License, v. 2.0. +# If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. # # If you wish to purchase a commercial license for this tool and its -# generated code, contact me via email. +# generated code, you may contact me via email or otherwise. # -# If GPL is incompatible with your free or open-source project, -# contact me and we'll work it out (for free). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# See . +# If MPL2 is incompatible with your free or open-source project, +# contact me and we'll work it out. # # @@ -356,7 +345,33 @@ class Discard(Exception): # Transformers -class Transformer: +class _Decoratable: + @classmethod + def _apply_decorator(cls, decorator, **kwargs): + mro = getmro(cls) + assert mro[0] is cls + libmembers = {name for _cls in mro[1:] for name, _ in getmembers(_cls)} + for name, value in getmembers(cls): + + # Make sure the function isn't inherited (unless it's overwritten) + if name.startswith('_') or (name in libmembers and name not in cls.__dict__): + continue + if not callable(cls.__dict__[name]): + continue + + # Skip if v_args already applied (at the function level) + if hasattr(cls.__dict__[name], 'vargs_applied'): + continue + + static = isinstance(cls.__dict__[name], (staticmethod, classmethod)) + setattr(cls, name, decorator(value, static=static, **kwargs)) + return cls + + def __class_getitem__(cls, _): + return cls + + +class Transformer(_Decoratable): """Visits the tree recursively, starting with the leaves and finally the root (bottom-up) Calls its methods (provided by user via inheritance) according to tree.data @@ -364,8 +379,8 @@ class Transformer: Can be used to implement map or reduce. """ - __visit_tokens__ = True # For backwards compatibility + def __init__(self, visit_tokens=True): self.__visit_tokens__ = visit_tokens @@ -433,27 +448,6 @@ class Transformer: return token - @classmethod - def _apply_decorator(cls, decorator, **kwargs): - mro = getmro(cls) - assert mro[0] is cls - libmembers = {name for _cls in mro[1:] for name, _ in getmembers(_cls)} - for name, value in getmembers(cls): - - # Make sure the function isn't inherited (unless it's overwritten) - if name.startswith('_') or (name in libmembers and name not in cls.__dict__): - continue - if not callable(cls.__dict__[name]): - continue - - # Skip if v_args already applied (at the function level) - if hasattr(cls.__dict__[name], 'vargs_applied'): - continue - - static = isinstance(cls.__dict__[name], (staticmethod, classmethod)) - setattr(cls, name, decorator(value, static=static, **kwargs)) - return cls - class InlineTransformer(Transformer): # XXX Deprecated def _call_userfunc(self, tree, new_children=None): @@ -510,6 +504,9 @@ class VisitorBase: "Default operation on tree (for override)" return tree + def __class_getitem__(cls, _): + return cls + class Visitor(VisitorBase): """Bottom-up visitor, non-recursive @@ -518,7 +515,6 @@ class Visitor(VisitorBase): Calls its methods (provided by user via inheritance) according to tree.data """ - def visit(self, tree): for subtree in tree.iter_subtrees(): self._call_userfunc(subtree) @@ -564,7 +560,7 @@ def visit_children_decor(func): return inner -class Interpreter: +class Interpreter(_Decoratable): """Top-down visitor, recursive Visits the tree, starting with the root and finally the leaves (top-down) @@ -573,8 +569,14 @@ class Interpreter: Unlike Transformer and Visitor, the Interpreter doesn't automatically visit its sub-branches. The user has to explicitly call visit_children, or use the @visit_children_decor """ + def visit(self, tree): - return getattr(self, tree.data)(tree) + f = getattr(self, tree.data) + wrapper = getattr(f, 'visit_wrapper', None) + if wrapper is not None: + return f.visit_wrapper(f, tree.data, tree.children, tree.meta) + else: + return f(tree) def visit_children(self, tree): return [self.visit(child) if isinstance(child, Tree) else child @@ -1817,7 +1819,7 @@ class LarkOptions(Serialize): 'ambiguity': 'auto', 'propagate_positions': False, 'lexer_callbacks': {}, - 'maybe_placeholders': True, + 'maybe_placeholders': False, 'edit_terminals': None, } @@ -1991,8 +1993,10 @@ class Lark(Serialize): memo = SerializeMemoizer.deserialize(memo, namespace, {}) inst = cls.__new__(cls) options = dict(data['options']) - options['transformer'] = transformer - options['postlex'] = postlex + if transformer is not None: + options['transformer'] = transformer + if postlex is not None: + options['postlex'] = postlex inst.options = LarkOptions.deserialize(options, memo) inst.rules = [Rule.deserialize(r, memo) for r in data['rules']] inst.source = '' @@ -2000,6 +2004,17 @@ class Lark(Serialize): inst.parser = inst.parser_class.deserialize(data['parser'], memo, inst._callbacks, inst.options.postlex) return inst + def save(self, f): + data, m = self.memo_serialize([TerminalDef, Rule]) + pickle.dump({'data': data, 'memo': m}, f) + + @classmethod + def load(cls, f): + d = pickle.load(f) + namespace = {'Rule': Rule, 'TerminalDef': TerminalDef} + memo = d['memo'] + return Lark.deserialize(d['data'], namespace, memo) + @classmethod def open(cls, grammar_filename, rel_to=None, **options): @@ -2047,10 +2062,10 @@ class Lark(Serialize): DATA = ( -{'rules': [{'@': 26}, {'@': 30}, {'@': 25}, {'@': 31}, {'@': 23}, {'@': 19}, {'@': 14}, {'@': 22}, {'@': 27}, {'@': 16}, {'@': 28}, {'@': 12}, {'@': 24}, {'@': 29}, {'@': 20}, {'@': 21}, {'@': 15}, {'@': 13}, {'@': 17}, {'@': 18}], 'parser': {'lexer_conf': {'tokens': [{'@': 0}, {'@': 1}, {'@': 2}, {'@': 3}, {'@': 4}, {'@': 5}, {'@': 6}, {'@': 7}, {'@': 8}, {'@': 9}, {'@': 10}, {'@': 11}], 'ignore': [u'WS'], '__type__': 'LexerConf'}, 'parser': {'tokens': {0: 'RSQB', 1: 'COMMA', 2: 'RBRACE', 3: '$END', 4: u'__array_star_0', 5: 'COLON', 6: u'pair', 7: u'ESCAPED_STRING', 8: u'string', 9: 'LBRACE', 10: u'FALSE', 11: u'object', 12: u'NULL', 13: u'SIGNED_NUMBER', 14: u'value', 15: u'array', 16: u'TRUE', 17: 'LSQB', 18: u'__object_star_1', 19: 'start'}, 'states': {0: {0: (1, {'@': 12}), 1: (1, {'@': 12}), 2: (1, {'@': 12}), 3: (1, {'@': 12})}, 1: {0: (0, 11), 1: (0, 20), 4: (0, 17)}, 2: {1: (0, 23), 2: (0, 0)}, 3: {5: (0, 12)}, 4: {8: (0, 3), 6: (0, 13), 7: (0, 21)}, 5: {8: (0, 3), 2: (0, 30), 6: (0, 19), 7: (0, 21)}, 6: {0: (0, 29), 7: (0, 21), 8: (0, 33), 9: (0, 5), 10: (0, 8), 11: (0, 31), 12: (0, 22), 13: (0, 24), 14: (0, 1), 15: (0, 26), 16: (0, 16), 17: (0, 6)}, 7: {0: (1, {'@': 13}), 1: (1, {'@': 13})}, 8: {0: (1, {'@': 14}), 1: (1, {'@': 14}), 2: (1, {'@': 14}), 3: (1, {'@': 14})}, 9: {0: (1, {'@': 15}), 1: (1, {'@': 15})}, 10: {7: (0, 21), 8: (0, 33), 9: (0, 5), 10: (0, 8), 11: (0, 31), 12: (0, 22), 13: (0, 24), 14: (0, 7), 15: (0, 26), 16: (0, 16), 17: (0, 6)}, 11: {0: (1, {'@': 16}), 1: (1, {'@': 16}), 2: (1, {'@': 16}), 3: (1, {'@': 16})}, 12: {7: (0, 21), 8: (0, 33), 9: (0, 5), 10: (0, 8), 11: (0, 31), 12: (0, 22), 13: (0, 24), 14: (0, 18), 15: (0, 26), 16: (0, 16), 17: (0, 6)}, 13: {1: (1, {'@': 17}), 2: (1, {'@': 17})}, 14: {}, 15: {1: (1, {'@': 18}), 2: (1, {'@': 18})}, 16: {0: (1, {'@': 19}), 1: (1, {'@': 19}), 2: (1, {'@': 19}), 3: (1, {'@': 19})}, 17: {0: (0, 28), 1: (0, 10)}, 18: {1: (1, {'@': 20}), 2: (1, {'@': 20})}, 19: {1: (0, 4), 18: (0, 2), 2: (0, 25)}, 20: {7: (0, 21), 8: (0, 33), 9: (0, 5), 10: (0, 8), 11: (0, 31), 12: (0, 22), 13: (0, 24), 14: (0, 9), 15: (0, 26), 16: (0, 16), 17: (0, 6)}, 21: {0: (1, {'@': 21}), 1: (1, {'@': 21}), 2: (1, {'@': 21}), 3: (1, {'@': 21}), 5: (1, {'@': 21})}, 22: {0: (1, {'@': 22}), 1: (1, {'@': 22}), 2: (1, {'@': 22}), 3: (1, {'@': 22})}, 23: {8: (0, 3), 6: (0, 15), 7: (0, 21)}, 24: {0: (1, {'@': 23}), 1: (1, {'@': 23}), 2: (1, {'@': 23}), 3: (1, {'@': 23})}, 25: {0: (1, {'@': 24}), 1: (1, {'@': 24}), 2: (1, {'@': 24}), 3: (1, {'@': 24})}, 26: {0: (1, {'@': 25}), 1: (1, {'@': 25}), 2: (1, {'@': 25}), 3: (1, {'@': 25})}, 27: {3: (1, {'@': 26})}, 28: {0: (1, {'@': 27}), 1: (1, {'@': 27}), 2: (1, {'@': 27}), 3: (1, {'@': 27})}, 29: {0: (1, {'@': 28}), 1: (1, {'@': 28}), 2: (1, {'@': 28}), 3: (1, {'@': 28})}, 30: {0: (1, {'@': 29}), 1: (1, {'@': 29}), 2: (1, {'@': 29}), 3: (1, {'@': 29})}, 31: {0: (1, {'@': 30}), 1: (1, {'@': 30}), 2: (1, {'@': 30}), 3: (1, {'@': 30})}, 32: {7: (0, 21), 8: (0, 33), 9: (0, 5), 10: (0, 8), 11: (0, 31), 12: (0, 22), 13: (0, 24), 14: (0, 27), 15: (0, 26), 16: (0, 16), 17: (0, 6), 19: (0, 14)}, 33: {0: (1, {'@': 31}), 1: (1, {'@': 31}), 2: (1, {'@': 31}), 3: (1, {'@': 31})}}, 'end_states': {'start': 14}, 'start_states': {'start': 32}}, '__type__': 'LALR_ContextualLexer', 'start': ['start']}, '__type__': 'Lark', 'options': {'transformer': None, 'lexer': 'contextual', 'lexer_callbacks': {}, 'debug': False, 'postlex': None, 'parser': 'lalr', 'cache_grammar': False, 'tree_class': None, 'priority': None, 'start': ['start'], 'keep_all_tokens': False, 'ambiguity': 'auto', 'edit_terminals': None, 'propagate_positions': False, 'maybe_placeholders': True}} +{'rules': [{'@': 27}, {'@': 31}, {'@': 26}, {'@': 13}, {'@': 24}, {'@': 18}, {'@': 14}, {'@': 22}, {'@': 28}, {'@': 23}, {'@': 29}, {'@': 12}, {'@': 25}, {'@': 30}, {'@': 19}, {'@': 21}, {'@': 15}, {'@': 20}, {'@': 16}, {'@': 17}], 'parser': {'lexer_conf': {'tokens': [{'@': 0}, {'@': 1}, {'@': 2}, {'@': 3}, {'@': 4}, {'@': 5}, {'@': 6}, {'@': 7}, {'@': 8}, {'@': 9}, {'@': 10}, {'@': 11}], 'ignore': [u'WS'], '__type__': 'LexerConf'}, 'parser': {'tokens': {0: 'COMMA', 1: 'RSQB', 2: 'RBRACE', 3: '$END', 4: 'LBRACE', 5: u'FALSE', 6: u'string', 7: u'object', 8: u'NULL', 9: u'SIGNED_NUMBER', 10: u'value', 11: u'array', 12: u'ESCAPED_STRING', 13: u'TRUE', 14: 'LSQB', 15: 'COLON', 16: u'pair', 17: u'__array_star_0', 18: u'__object_star_1', 19: 'start'}, 'states': {0: {0: (1, {'@': 12}), 1: (1, {'@': 12}), 2: (1, {'@': 12}), 3: (1, {'@': 12})}, 1: {1: (0, 29), 4: (0, 33), 5: (0, 8), 6: (0, 5), 7: (0, 31), 8: (0, 22), 9: (0, 24), 10: (0, 6), 11: (0, 26), 12: (0, 21), 13: (0, 16), 14: (0, 1)}, 2: {0: (0, 11), 2: (0, 0)}, 3: {15: (0, 12)}, 4: {16: (0, 13), 12: (0, 21), 6: (0, 3)}, 5: {0: (1, {'@': 13}), 1: (1, {'@': 13}), 2: (1, {'@': 13}), 3: (1, {'@': 13})}, 6: {0: (0, 7), 1: (0, 23), 17: (0, 17)}, 7: {4: (0, 33), 5: (0, 8), 6: (0, 5), 7: (0, 31), 8: (0, 22), 9: (0, 24), 10: (0, 9), 11: (0, 26), 12: (0, 21), 13: (0, 16), 14: (0, 1)}, 8: {0: (1, {'@': 14}), 1: (1, {'@': 14}), 2: (1, {'@': 14}), 3: (1, {'@': 14})}, 9: {0: (1, {'@': 15}), 1: (1, {'@': 15})}, 10: {4: (0, 33), 5: (0, 8), 6: (0, 5), 7: (0, 31), 8: (0, 22), 9: (0, 24), 10: (0, 20), 11: (0, 26), 12: (0, 21), 13: (0, 16), 14: (0, 1)}, 11: {16: (0, 15), 12: (0, 21), 6: (0, 3)}, 12: {4: (0, 33), 5: (0, 8), 6: (0, 5), 7: (0, 31), 8: (0, 22), 9: (0, 24), 10: (0, 18), 11: (0, 26), 12: (0, 21), 13: (0, 16), 14: (0, 1)}, 13: {0: (1, {'@': 16}), 2: (1, {'@': 16})}, 14: {}, 15: {0: (1, {'@': 17}), 2: (1, {'@': 17})}, 16: {0: (1, {'@': 18}), 1: (1, {'@': 18}), 2: (1, {'@': 18}), 3: (1, {'@': 18})}, 17: {0: (0, 10), 1: (0, 28)}, 18: {0: (1, {'@': 19}), 2: (1, {'@': 19})}, 19: {0: (0, 4), 18: (0, 2), 2: (0, 25)}, 20: {0: (1, {'@': 20}), 1: (1, {'@': 20})}, 21: {0: (1, {'@': 21}), 1: (1, {'@': 21}), 2: (1, {'@': 21}), 3: (1, {'@': 21}), 15: (1, {'@': 21})}, 22: {0: (1, {'@': 22}), 1: (1, {'@': 22}), 2: (1, {'@': 22}), 3: (1, {'@': 22})}, 23: {0: (1, {'@': 23}), 1: (1, {'@': 23}), 2: (1, {'@': 23}), 3: (1, {'@': 23})}, 24: {0: (1, {'@': 24}), 1: (1, {'@': 24}), 2: (1, {'@': 24}), 3: (1, {'@': 24})}, 25: {0: (1, {'@': 25}), 1: (1, {'@': 25}), 2: (1, {'@': 25}), 3: (1, {'@': 25})}, 26: {0: (1, {'@': 26}), 1: (1, {'@': 26}), 2: (1, {'@': 26}), 3: (1, {'@': 26})}, 27: {3: (1, {'@': 27})}, 28: {0: (1, {'@': 28}), 1: (1, {'@': 28}), 2: (1, {'@': 28}), 3: (1, {'@': 28})}, 29: {0: (1, {'@': 29}), 1: (1, {'@': 29}), 2: (1, {'@': 29}), 3: (1, {'@': 29})}, 30: {0: (1, {'@': 30}), 1: (1, {'@': 30}), 2: (1, {'@': 30}), 3: (1, {'@': 30})}, 31: {0: (1, {'@': 31}), 1: (1, {'@': 31}), 2: (1, {'@': 31}), 3: (1, {'@': 31})}, 32: {4: (0, 33), 5: (0, 8), 6: (0, 5), 7: (0, 31), 8: (0, 22), 9: (0, 24), 10: (0, 27), 11: (0, 26), 12: (0, 21), 13: (0, 16), 14: (0, 1), 19: (0, 14)}, 33: {16: (0, 19), 2: (0, 30), 12: (0, 21), 6: (0, 3)}}, 'end_states': {'start': 14}, 'start_states': {'start': 32}}, '__type__': 'LALR_ContextualLexer', 'start': ['start']}, '__type__': 'Lark', 'options': {'transformer': None, 'lexer': 'contextual', 'lexer_callbacks': {}, 'debug': False, 'postlex': None, 'parser': 'lalr', 'cache_grammar': False, 'tree_class': None, 'priority': None, 'start': ['start'], 'keep_all_tokens': False, 'ambiguity': 'auto', 'edit_terminals': None, 'propagate_positions': False, 'maybe_placeholders': False}} ) MEMO = ( -{0: {'priority': 1, 'pattern': {'__type__': 'PatternRE', '_width': [2, 4294967295], 'flags': [], 'value': u'\\".*?(?>> LICENSE # -# This tool and its generated code use a separate license from Lark. -# -# It is licensed under GPLv2 or above. +# This tool and its generated code use a separate license from Lark, +# and are subject to the terms of the Mozilla Public License, v. 2.0. +# If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. # # If you wish to purchase a commercial license for this tool and its -# generated code, contact me via email. +# generated code, you may contact me via email or otherwise. # -# If GPL is incompatible with your free or open-source project, -# contact me and we'll work it out (for free). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# See . +# If MPL2 is incompatible with your free or open-source project, +# contact me and we'll work it out. # #