Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-pyleri for openSUSE:Factory checked in at 2024-01-07 21:41:07 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pyleri (Old) and /work/SRC/openSUSE:Factory/.python-pyleri.new.28375 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pyleri" Sun Jan 7 21:41:07 2024 rev:2 rq:1137430 version:1.4.2 Changes: -------- --- /work/SRC/openSUSE:Factory/python-pyleri/python-pyleri.changes 2021-07-31 18:51:23.370530553 +0200 +++ /work/SRC/openSUSE:Factory/.python-pyleri.new.28375/python-pyleri.changes 2024-01-07 21:41:23.454395009 +0100 @@ -1,0 +2,16 @@ +Sun Jan 7 19:54:30 UTC 2024 - Dirk Müller <dmuel...@suse.com> + +- update to 1.4.2: + * Fixed typing for delimiter on the List type. + * Small PEP-8 fix. +- update to 1.4.1: + * Added typing hints +- update to 1.4.0: + * Extra keyword argument `line_number` to `.as_str(..)` method + to include the line number with the error. + * Regular expression object not with flags before the required + `^` character. +- update to 1.3.4: + * Fixed bug with recursion in Prio element. (issue #18) + +------------------------------------------------------------------- Old: ---- pyleri-1.3.3.tar.gz New: ---- pyleri-1.4.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pyleri.spec ++++++ --- /var/tmp/diff_new_pack.j5jNPK/_old 2024-01-07 21:41:23.894411015 +0100 +++ /var/tmp/diff_new_pack.j5jNPK/_new 2024-01-07 21:41:23.894411015 +0100 @@ -1,6 +1,7 @@ # # spec file for package python-pyleri # +# Copyright (c) 2024 SUSE LLC # Copyright (c) 2021, Martin Hauke <mar...@gmx.de> # # All modifications and additions to the file contributed by third parties @@ -18,16 +19,18 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-pyleri -Version: 1.3.3 +Version: 1.4.2 Release: 0 Summary: Python Left-Right Parser License: MIT URL: https://github.com/transceptor-technology/pyleri Source: https://github.com/transceptor-technology/pyleri/archive/refs/tags/%{version}.tar.gz#/pyleri-%{version}.tar.gz -BuildRequires: python-rpm-macros -BuildRequires: %{python_module setuptools} +BuildRequires: %{python_module pip} BuildRequires: %{python_module pytest} +BuildRequires: %{python_module setuptools} +BuildRequires: %{python_module wheel} BuildRequires: fdupes +BuildRequires: python-rpm-macros BuildArch: noarch %python_subpackages @@ -38,10 +41,10 @@ %setup -q -n pyleri-%{version} %build -%python_build +%pyproject_wheel %install -%python_install +%pyproject_install %python_expand %fdupes %{buildroot}%{$python_sitelib} %check @@ -49,6 +52,7 @@ %files %{python_files} %license LICENSE.txt -%doc ChangeLog README.md -%{python_sitelib}/pyleri* +%doc README.md +%{python_sitelib}/pyleri +%{python_sitelib}/pyleri-%{version}.dist-info ++++++ pyleri-1.3.3.tar.gz -> pyleri-1.4.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/.github/FUNDING.yml new/pyleri-1.4.2/.github/FUNDING.yml --- old/pyleri-1.3.3/.github/FUNDING.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/pyleri-1.4.2/.github/FUNDING.yml 2023-03-16 09:49:04.000000000 +0100 @@ -0,0 +1 @@ +github: cesbit diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/.github/workflows/ci.yml new/pyleri-1.4.2/.github/workflows/ci.yml --- old/pyleri-1.3.3/.github/workflows/ci.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/pyleri-1.4.2/.github/workflows/ci.yml 2023-03-16 09:49:04.000000000 +0100 @@ -0,0 +1,33 @@ +name: CI +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.7", "3.8", "3.9", "3.10"] + + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest pycodestyle + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + - name: Run tests with pytest + run: | + pytest + - name: Lint with PyCodeStyle + run: | + find . -name \*.py -exec pycodestyle {} + \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/.travis.yml new/pyleri-1.4.2/.travis.yml --- old/pyleri-1.3.3/.travis.yml 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/.travis.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,10 +0,0 @@ -language: python -python: - - "3.4" - - "3.5" - - "3.6" -before_install: - - pip install pycodestyle -script: - - pytest -v - - find . -name \*.py -exec pycodestyle {} + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/ChangeLog new/pyleri-1.4.2/ChangeLog --- old/pyleri-1.3.3/ChangeLog 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/ChangeLog 1970-01-01 01:00:00.000000000 +0100 @@ -1,79 +0,0 @@ -2020.12.01, Version 1.3.3 (Stable) - - * Fixed bug with single and double quote characters in export. (issue #16) - -2018.10.29, Version 1.3.2 (Stable) - - * Replace / with _ in function name. - -2018.10.25, Version 1.3.1 (Stable) - - * Fixed exporting `Repeat` element to C. (issue #9) - * Added header file name option to `export_c()` method. - -2018.10.15, Version 1.3.0 (Stable) - - * Added element properties: - - `Keyword.ign_case` - - `Choice.most_greedy` - - `List.min`, `List.max`, `List.opt_closing` - - `Repeat.min`, 'Repeat.max` - * Added `Result.as_str` for returning a textual parse result. - * Fixed correct expecting for `List` element. - * Added `MaxRecursionError` exception for `Prio` element. - -2018.07.09, Version 1.2.2 (Stable) - - * Added export to JavaScript using class (es6) syntax. - * Use jsleri Ref.set() method instead of Object.assign. - -2018.07.05, Version 1.2.1 (Stable) - - * Format readme on PyPi - -2018.07.05, Version 1.2.0 (Stable) - - * Fixed typo in List mi/ma exception. - * Do not allow duplicate names in lower or upper case. - * Added export to Java for the jleri module. - * Fixed typo indentation. - * Added grammar check for missing START point. - -2017.06.23, Version 1.1.8 (Stable) - - * Rename cleri_object_t to cleri_t. - -2017.06.22, Version 1.1.7 (Stable) - - * Added support for cleri_dup() in export to C. (issue #5) - * Fixed header guards while exporting to C. (issue #6) - -2017.06.20, Version 1.1.6 (Stable) - - * Fixed exporting ref to C. (issue #4) - -2017.03.13, Version 1.1.5 (Stable) - - * Fixed exporting keywords (case sensitive) to C. - * Added export to Go language for the goleri module. - -2016.10.25, Version 1.1.4 (Stable) - - * Fixed exporting Tokens to JavaScript and Python. (issue #2) - -2016.10.24, Version 1.1.3 (Stable) - - * Added export to Python method. This can be useful even if the source is - already defined in Python language. (see issue #1) - -2016.07.02, Version 1.1.2 (Stable) - - * Fixed export_c() to support Ref(). An update to cleri is not needed since - in C we can simply pre-define a variable and later assign the actual - object. - -2016.03.07, Version 1.1.0 (BETA) - - * Added Ref() support which can be used to create forward references. - * Updated jsleri to support Ref() and updated export_js() method to support - this new class. \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/LICENSE.txt new/pyleri-1.4.2/LICENSE.txt --- old/pyleri-1.3.3/LICENSE.txt 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/LICENSE.txt 2023-03-16 09:49:04.000000000 +0100 @@ -1,19 +1,19 @@ -Copyright (c) 2016 Jeroen van der Heijden / Transceptor Technology +Copyright (c) 2021 Jeroen van der Heijden <jer...@cesbit.com> -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/README.md new/pyleri-1.4.2/README.md --- old/pyleri-1.3.3/README.md 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/README.md 2023-03-16 09:49:04.000000000 +0100 @@ -1,6 +1,11 @@ +[](https://github.com/cesbit/pyleri/actions) +[](https://github.com/cesbit/pyleri/releases) + Python Left-Right Parser ======================== -Pyleri is an easy-to-use parser created for [SiriDB](http://siridb.net/). We first used [lrparsing](http://lrparsing.sourceforge.net/doc/html/) and wrote [jsleri](https://github.com/transceptor-technology/jsleri) for auto-completion and suggestions in our web console. Later we found small issues within the `lrparsing` module and also had difficulties keeping the language the same in all projects. That is when we decided to create Pyleri which can export a created grammar to JavaScript, C, Python, Go and Java. +Pyleri is an easy-to-use parser created for [SiriDB](http://siridb.net/). We first used [lrparsing](http://lrparsing.sourceforge.net/doc/html/) and wrote [jsleri](https://github.com/cesbit/jsleri) for auto-completion and suggestions in our web console. Later we found small issues within the `lrparsing` module and also had difficulties keeping the language the same in all projects. That is when we decided to create Pyleri which can export a created grammar to JavaScript, C, Python, Go and Java. + +Gabriele Tomassetti [wrote a tutorial](https://tomassetti.me/pyleri-tutorial/) about the pyleri library. --------------------------------------- * [Related projects](#related-projects) @@ -34,10 +39,10 @@ --------------------------------------- ## Related projects -- [jsleri](https://github.com/transceptor-technology/jsleri): JavaScript parser -- [libcleri](https://github.com/transceptor-technology/libcleri): C parser -- [goleri](https://github.com/transceptor-technology/goleri): Go parser -- [jleri](https://github.com/transceptor-technology/jleri): Java parser +- [jsleri](https://github.com/cesbit/jsleri): JavaScript parser +- [libcleri](https://github.com/cesbit/libcleri): C parser +- [goleri](https://github.com/cesbit/goleri): Go parser +- [jleri](https://github.com/cesbit/jleri): Java parser ## Installation The easiest way is to use PyPI: @@ -240,7 +245,7 @@ import ( "regexp" - "github.com/transceptor-technology/goleri" + "github.com/cesbit/goleri" ) // Element indentifiers diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/examples/json_grammar.py new/pyleri-1.4.2/examples/json_grammar.py --- old/pyleri-1.3.3/examples/json_grammar.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/examples/json_grammar.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,4 +1,4 @@ -'''JSON Grammar.''' +"""JSON Grammar.""" from pyleri import ( Ref, Choice, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/pyleri/__init__.py new/pyleri-1.4.2/pyleri/__init__.py --- old/pyleri-1.3.3/pyleri/__init__.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/pyleri/__init__.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,4 +1,4 @@ -'''Py-LeRi (pyleri) Python LR-parsing module. +"""Py-LeRi (pyleri) Python LR-parsing module. This module is inspired by lrparsing (http://lrparsing.sourceforge.net/), a Python parser written by Russell Stuart, 2014-05-29. @@ -8,9 +8,9 @@ Javascript JS-LeRi (jsleri) module so we can exchange grammars written by this module with JavaScript projects. -:copyright: 2016, Jeroen van der Heijden (Transceptor Technology) +:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com> :license: MIT -''' +""" from .choice import Choice from .endofstatement import end_of_statement @@ -40,5 +40,5 @@ __author__ = 'Jeroen van der Heijden' __maintainer__ = 'Jeroen van der Heijden' -__email__ = 'jeroen@transceptor.technology' -__version__ = '1.3.3' +__email__ = 'jer...@cesbit.com' +__version__ = '1.4.2' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/pyleri/choice.py new/pyleri-1.4.2/pyleri/choice.py --- old/pyleri-1.3.3/pyleri/choice.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/pyleri/choice.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,27 +1,29 @@ -'''pyleri.Choice Class. +"""pyleri.Choice Class. Choose one of the given elements. When most_greedy is True we will choose the 'longest' element when multiple elements are valid. If most_greedy is False we will return the first match. -:copyright: 2018, Jeroen van der Heijden (Transceptor Technology) -''' - -from .elements import NamedElement, c_export, go_export, java_export +:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com> +""" +from .elements import Element, NamedElement, c_export, go_export, java_export class Choice(NamedElement): __slots__ = ('_elements', '_get_node_result') - def __init__(self, *elements, most_greedy=True): + def __init__( + self, + *elements: Element, + most_greedy: bool = True): self._elements = self._validate_elements(elements) self._get_node_result = \ self._most_greedy_result if most_greedy else \ self._stop_at_first_match @property - def most_greedy(self): + def most_greedy(self) -> bool: return self._get_node_result == self._most_greedy_result def _most_greedy_result(self, root, tree, rule, s, node): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/pyleri/elements.py new/pyleri-1.4.2/pyleri/elements.py --- old/pyleri-1.3.3/pyleri/elements.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/pyleri/elements.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,18 +1,19 @@ -'''Element and NamedElement Class. +"""Element and NamedElement Class. These are the base classes used for all other elements. -:copyright: 2018, Jeroen van der Heijden (Transceptor Technology) -''' +:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com> +""" +import typing as t -def camel_case(s): +def camel_case(s: str) -> str: return ''.join( p[0].upper() + p[1:] if n else p for n, p in enumerate(s.split('_'))) -def cap_case(s): +def cap_case(s: str) -> str: return ''.join(p[0].upper() + p[1:] for p in s.split('_') if p) @@ -63,18 +64,20 @@ __slots__ = tuple() + name: t.Optional[str] + @staticmethod - def _validate_element(element): + def _validate_element(element: t.Union[str, 'Element']) -> 'Element': if isinstance(element, str): return Token(element) if isinstance(element, Element): return element raise TypeError( - 'Expecting an element or string but received type: {}'.format( - type(element))) + 'Expecting an element or string ' + 'but received type: {}'.format(type(element))) @classmethod - def _validate_elements(cls, elements): + def _validate_elements(cls, elements) -> t.List['Element']: return [cls._validate_element(elem) for elem in elements] @@ -82,7 +85,12 @@ __slots__ = ('name',) - def _export_js(self, js_indent, indent, classes, cname): + def _export_js( + self, + js_indent: int, + indent: int, + classes, + cname) -> str: classes.add(self.__class__.__name__.lstrip('_')) if hasattr(self, 'name') and indent > 0: return '{}.{}'.format(cname, self.name) if cname else self.name diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/pyleri/endofstatement.py new/pyleri-1.4.2/pyleri/endofstatement.py --- old/pyleri-1.3.3/pyleri/endofstatement.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/pyleri/endofstatement.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,10 +1,10 @@ -'''end_of_statement Variable. +"""end_of_statement Variable. end_of_statement is an instance of _EndOfStatement and will be added to an 'expecting' in a node result when an 'End of Statement' is possible. -:copyright: 2018, Jeroen van der Heijden (Transceptor Technology) -''' +:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com> +""" class _EndOfStatement: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/pyleri/exceptions.py new/pyleri-1.4.2/pyleri/exceptions.py --- old/pyleri-1.3.3/pyleri/exceptions.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/pyleri/exceptions.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,7 +1,7 @@ -'''Exceptions. +"""Exceptions. -:copyright: 2018, Jeroen van der Heijden (Transceptor Technology) -''' +:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com> +""" class CompileError(Exception): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/pyleri/expecting.py new/pyleri-1.4.2/pyleri/expecting.py --- old/pyleri-1.3.3/pyleri/expecting.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/pyleri/expecting.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,11 +1,14 @@ -'''Expecting Class. +"""Expecting Class. Expecting Class is used to return possible elements at a position when a given statement is not correct. This helps building auto-completion, suggestions or returning nice messages to the user. -:copyright: 2018, Jeroen van der Heijden (Transceptor Technology) -''' +:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com> +""" +import typing as t +if t.TYPE_CHECKING: + from .elements import Element class Expecting: @@ -13,12 +16,12 @@ __slots__ = ('required', 'optional', 'pos', '_modes') def __init__(self): - self.required = set() - self.optional = set() - self.pos = 0 - self._modes = {self.pos: self.required} + self.required: t.Set['Element'] = set() + self.optional: t.Set['Element'] = set() + self.pos: int = 0 + self._modes: t.Dict[int, t.Set['Element']] = {self.pos: self.required} - def set_mode_required(self, pos, is_required): + def set_mode_required(self, pos: int, is_required: bool): # do nothing when mode is already set to optional if pos in self._modes and self._modes[pos] is self.optional: return @@ -29,7 +32,7 @@ self.required.clear() self.optional.clear() - def update(self, element, pos): + def update(self, element: 'Element', pos: int): if pos > self.pos: self.empty() self.pos = pos @@ -37,5 +40,5 @@ if pos == self.pos: self._modes[pos].add(element) - def get_expecting(self): + def get_expecting(self) -> t.Set['Element']: return self.required | self.optional diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/pyleri/grammar.py new/pyleri-1.4.2/pyleri/grammar.py --- old/pyleri-1.3.3/pyleri/grammar.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/pyleri/grammar.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,4 +1,4 @@ -'''pyleri.Grammar Class. +"""pyleri.Grammar Class. When creating a new grammar this class should be used as the base class. @@ -8,8 +8,8 @@ ... -:copyright: 2018, Jeroen van der Heijden (Transceptor Technology) -''' +:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com> +""" import re @@ -284,7 +284,7 @@ import ( \t"regexp" -\t"github.com/transceptor-technology/goleri" +\t"github.com/cesbit/goleri" ) // Element indentifiers @@ -328,11 +328,11 @@ '''.lstrip() def __init__(self): - '''Initialize the grammar. + """Initialize the grammar. Note: usually you should only initialize a Grammar instance once in a project. - ''' + """ self._element = self.START self._string = None self._expecting = None @@ -342,14 +342,14 @@ self, js_module_name=JS_MODULE_NAME, js_template=JS_ES6_IMPORT_EXPORT_TEMPLATE, - js_indent=JS_INDENTATION): - '''Export the grammar to a JavaScript file which can be + js_indent=JS_INDENTATION) -> str: + """Export the grammar to a JavaScript file which can be used with the js-lrparsing module. Two templates are available: Grammar.JS_WINDOW_TEMPLATE Grammar.JS_ES6_IMPORT_EXPORT_TEMPLATE (default) - ''' + """ language = [] refs = [] @@ -405,11 +405,11 @@ self, py_module_name=PY_MODULE_NAME, py_template=PY_TEMPLATE, - py_indent=PY_INDENTATION): - '''Export the grammar to a python file which can be + py_indent=PY_INDENTATION) -> str: + """Export the grammar to a python file which can be used with the pyleri module. This can be useful when python code if used to auto-create a grammar and an export of the final result is - required.''' + required.""" language = [] classes = {'Grammar'} @@ -449,9 +449,13 @@ ' '.join(['from', py_module_name, 'import', n]) for n in classes if n != 'Rule']))) - def export_c(self, target=C_TARGET, c_indent=C_INDENTATION, headerf=None): - '''Export the grammar to a c (source and header) file which can be - used with the libcleri module.''' + def export_c( + self, + target=C_TARGET, + c_indent=C_INDENTATION, + headerf=None) -> str: + """Export the grammar to a c (source and header) file which can be + used with the libcleri module.""" language = [] indent = 0 enums = set() @@ -517,9 +521,9 @@ self, go_template=GO_TEMPLATE, go_indent=GO_INDENTATION, - go_package=GO_PACKAGE): - '''Export the grammar to a Go file which can be - used with the goleri module.''' + go_package=GO_PACKAGE) -> str: + """Export the grammar to a Go file which can be + used with the goleri module.""" language = [] enums = set() @@ -568,9 +572,9 @@ java_template=JAVA_TEMPLATE, java_indent=JAVA_INDENTATION, java_package=JAVA_PACKAGE, - is_public=True): - '''Export the grammar to a Java file which can be - used with the jleri module.''' + is_public=True) -> str: + """Export the grammar to a Java file which can be + used with the jleri module.""" language = [] enums = set() @@ -629,8 +633,8 @@ enums=enum_str, public='public ' if is_public else '') - def parse(self, string): - '''Parse some string to the Grammar. + def parse(self, string) -> Result: + """Parse some string to the Grammar. Returns a nodeResult with the following attributes: - is_valid: True when the string is successfully parsed @@ -641,7 +645,7 @@ 'pos' in the string. - tree: the parse_tree containing a structured result for the given string. - ''' + """ self._string = string self._expecting = Expecting() self._cached_kw_match.clear() @@ -653,7 +657,8 @@ 0, tree.children, self._element, - True)) + True), + tree) # get rest if anything rest = self._string[node_res.pos:].lstrip() @@ -673,8 +678,6 @@ if not node_res.is_valid: node_res.pos = self._expecting.pos - node_res.tree = tree - return node_res def _append_tree(self, tree, node, pos): @@ -693,7 +696,9 @@ return element._get_node_result(self, tree, rule, self._s, node) -def create_grammar(elem, re_keywords=_RE_KEYWORDS): +def create_grammar( + elem: Element, + re_keywords: 're.Pattern' = _RE_KEYWORDS) -> Grammar: class _Grammar(Grammar): RE_KEYWORDS = _RE_KEYWORDS START = elem diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/pyleri/keyword.py new/pyleri-1.4.2/pyleri/keyword.py --- old/pyleri-1.3.3/pyleri/keyword.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/pyleri/keyword.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,11 +1,11 @@ -'''pyleri.Keyword Class. +"""pyleri.Keyword Class. Try matching a given keyword string. The keyword should match Grammer.RE_KEYWORDS otherwise the keyword will not be found. It's possible however to overwrite the default RE_KEYWORDS in you own Grammar class. -:copyright: 2018, Jeroen van der Heijden (Transceptor Technology) -''' +:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com> +""" from .elements import NamedElement, c_export, go_export, java_export @@ -13,7 +13,7 @@ __slots__ = ('_keyword', '_ign_case') - def __init__(self, keyword, ign_case=False): + def __init__(self, keyword: str, ign_case: bool = False): if not isinstance(keyword, str): raise TypeError( @@ -23,7 +23,7 @@ self._ign_case = bool(ign_case) @property - def ign_case(self): + def ign_case(self) -> bool: return self._ign_case def __repr__(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/pyleri/list.py new/pyleri-1.4.2/pyleri/list.py --- old/pyleri-1.3.3/pyleri/list.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/pyleri/list.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,4 +1,4 @@ -'''pyleri.List Class. +"""pyleri.List Class. The grammar must find given elements separated by a delimiter. When no delimiter is given we split using a comma. All arguments: @@ -9,16 +9,23 @@ ma: Maximum elements the parser will search for. (default: None, unlimited) opt: When set to True the list may end with a delimiter. (default: False) -:copyright: 2018, Jeroen van der Heijden (Transceptor Technology) -''' -from .elements import NamedElement, c_export, go_export, java_export +:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com> +""" +import typing as t +from .elements import Element, NamedElement, c_export, go_export, java_export class List(NamedElement): __slots__ = ('_element', '_delimiter', '_min', '_max', '_opt') - def __init__(self, element, delimiter=',', mi=0, ma=None, opt=False): + def __init__( + self, + element: Element, + delimiter: t.Union[str, Element] = ',', + mi: int = 0, + ma: t.Optional[int] = None, + opt: bool = False): self._element, self._delimiter = \ map(self._validate_element, (element, delimiter)) @@ -38,15 +45,15 @@ self._opt = bool(opt) @property - def min(self): + def min(self) -> int: return self._min @property - def max(self): + def max(self) -> t.Optional[int]: return self._max @property - def opt_closing(self): + def opt_closing(self) -> bool: return self._opt @property diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/pyleri/node.py new/pyleri-1.4.2/pyleri/node.py --- old/pyleri-1.3.3/pyleri/node.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/pyleri/node.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,20 +1,28 @@ -'''Node class. +"""Node class. -:copyright: 2018, Jeroen van der Heijden (Transceptor Technology) -''' +:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com> +""" +import typing as t +if t.TYPE_CHECKING: + from .elements import Element class Node: __slots__ = ('element', '_string', 'start', 'end', 'children') - def __init__(self, element, string, start, end=None): + def __init__( + self, + element: 'Element', + string: str, + start: int, + end: t.Optional[int] = None): self.element = element self.start = start self.end = end self._string = string - self.children = [] + self.children: t.List['Node'] = [] @property - def string(self): + def string(self) -> str: return self._string[self.start:self.end] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/pyleri/optional.py new/pyleri-1.4.2/pyleri/optional.py --- old/pyleri-1.3.3/pyleri/optional.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/pyleri/optional.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,7 +1,7 @@ -'''Optional class. +"""Optional class. -:copyright: 2018, Jeroen van der Heijden (Transceptor Technology) -''' +:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com> +""" from .elements import NamedElement, c_export, go_export, java_export diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/pyleri/prio.py new/pyleri-1.4.2/pyleri/prio.py --- old/pyleri-1.3.3/pyleri/prio.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/pyleri/prio.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,8 +1,8 @@ -'''Prio class. +"""Prio class. -:copyright: 2018, Jeroen van der Heijden (Transceptor Technology) -''' -from .elements import NamedElement +:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com> +""" +from .elements import NamedElement, Element from .rule import Rule from .exceptions import MaxRecursionError @@ -13,7 +13,7 @@ __slots__ = ('_elements', '_name') - def __init__(self, *elements): + def __init__(self, *elements: Element): self._elements = self._validate_elements(elements) def _get_node_result(self, root, tree, rule, s, node): @@ -34,6 +34,8 @@ node.children = rule._tree[node.start] = children rule._tested[node.start] = is_valid, pos + rule._depth -= 1 + if rule._tested[node.start][0]: root._append_tree(tree, node, rule._tested[node.start][1]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/pyleri/ref.py new/pyleri-1.4.2/pyleri/ref.py --- old/pyleri-1.3.3/pyleri/ref.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/pyleri/ref.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,16 +1,16 @@ -'''pyleri.Ref Class. +"""pyleri.Ref Class. When a forward reference is used the grammar must contain a final reference with the same name. The Grammar class is used to validate a valid grammer and set element. -:copyright: 2018, Jeroen van der Heijden (Transceptor Technology) -''' -from .elements import NamedElement +:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com> +""" +from .elements import NamedElement, Element class Ref(NamedElement): - '''Ref class.''' + """Ref class.""" __slots__ = ('_element', '_get_node_result') @@ -19,7 +19,7 @@ return getattr(self, '_element', None) @element.setter - def element(self, element): + def element(self, element: Element): self._element = self._validate_element(element) self._get_node_result = self._element._get_node_result diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/pyleri/regex.py new/pyleri-1.4.2/pyleri/regex.py --- old/pyleri-1.3.3/pyleri/regex.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/pyleri/regex.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,18 +1,35 @@ -'''Regex class. +"""Regex class. -:copyright: 2018, Jeroen van der Heijden (Transceptor Technology) -''' +:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com> +""" import re from .elements import NamedElement, c_export, go_export, java_export +_RE_FLAGS = re.compile( + r'^(' + r'(\(\?i\))|' + r'(\(\?m\))|' + r'(\(\?s\))|' + r'(\(\?A\))|' + r'(\(\?x\))|' + r'(\(\?X\))|' + r'(\(\?U\))|' + r'(\(\?:\))' + r')(.)') + class Regex(NamedElement): __slots__ = ('_compiled',) - def __init__(self, pattern, flags=0): + def __init__(self, pattern: str, flags: int = 0): if not pattern.startswith('^'): - pattern = '^' + pattern + m = _RE_FLAGS.match(pattern) + if not m: + pattern = '^' + pattern + elif m.group(2) != '^': + pos = m.end() - 1 + pattern = pattern[:pos] + '^' + pattern[pos:] assert flags == 0 or flags == re.IGNORECASE, \ 'Only re.IGNORECASE is currently accepted as flag' self._compiled = re.compile(pattern, flags=flags) @@ -44,7 +61,7 @@ @c_export def _run_export_c(self, c_indent, indent, enums, gid): - assert not(self._compiled.flags & re.IGNORECASE), \ + assert not (self._compiled.flags & re.IGNORECASE), \ 'libcleri has currently no support for the re.IGNORECASE flag' return 'cleri_regex({}, "{}")'.format( gid, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/pyleri/repeat.py new/pyleri-1.4.2/pyleri/repeat.py --- old/pyleri-1.3.3/pyleri/repeat.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/pyleri/repeat.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,20 +1,25 @@ -'''Repeat class. +"""Repeat class. -:copyright: 2018, Jeroen van der Heijden (Transceptor Technology) -''' -from .elements import NamedElement, c_export, go_export, java_export +:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com> +""" +import typing as t +from .elements import Element, NamedElement, c_export, go_export, java_export class Repeat(NamedElement): __slots__ = ('_element', '_min', '_max') - def __init__(self, element, mi=0, ma=None): + def __init__( + self, + element: Element, + mi: int = 0, + ma: t.Optional[int] = None): self._element = self._validate_element(element) if not isinstance(mi, int) or mi < 0: raise TypeError('Repeat(): "mi" must be an integer value larger ' - 'than or equal to 0, got: {}'.format(mi)) + 'than or equal to 0, got: {mi}'.format(mi)) self._min = mi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/pyleri/result.py new/pyleri-1.4.2/pyleri/result.py --- old/pyleri-1.3.3/pyleri/result.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/pyleri/result.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,11 +1,15 @@ -'''Result class. +"""Result class. -:copyright: 2018, Jeroen van der Heijden (Transceptor Technology) -''' +:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com> +""" +import typing as t from .keyword import Keyword from .token import Token from .tokens import Tokens from .endofstatement import _EndOfStatement +if t.TYPE_CHECKING: + from .node import Node + from .expecting import Expecting TOSTR = (Keyword, Token, Tokens, _EndOfStatement) @@ -15,16 +19,22 @@ __slots__ = ('is_valid', 'pos', 'expecting', 'tree') - def __init__(self, is_valid, pos): - self.is_valid = is_valid - self.pos = pos - self.expecting = None - self.tree = None + def __init__(self, is_valid: bool, pos: int, tree: 'Node'): + self.is_valid: bool = is_valid + self.pos: int = pos + self.expecting: t.Optional['Expecting'] = None + self.tree: 'Node' = tree - def as_str(self, translate=None): + def as_str(self, translate=None, line_number=False): if self.is_valid: return 'parsed successfully' - res = ['error at position {}'.format(self.pos)] + if line_number: + string = self.tree._string + lnr = string.count('\n', 0, self.pos) + 1 + pos = self.pos - string.rfind('\n', 0, self.pos) + res = ['error at line {}, col {}'.format(lnr, pos)] + else: + res = ['error at position {}'.format(self.pos)] arr = [] for elem in (self.expecting): expectstr = translate(elem) if translate else None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/pyleri/rule.py new/pyleri-1.4.2/pyleri/rule.py --- old/pyleri-1.3.3/pyleri/rule.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/pyleri/rule.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,15 +1,15 @@ -'''Rule class. +"""Rule class. -:copyright: 2018, Jeroen van der Heijden (Transceptor Technology) -''' -from .elements import NamedElement +:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com> +""" +from .elements import NamedElement, Element class Rule(NamedElement): __slots__ = ('_element', '_tested', '_tree', '_depth') - def __init__(self, element): + def __init__(self, element: Element): self._element = element def _get_node_result(self, root, tree, rule, _s, node): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/pyleri/sequence.py new/pyleri-1.4.2/pyleri/sequence.py --- old/pyleri-1.3.3/pyleri/sequence.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/pyleri/sequence.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,15 +1,15 @@ -'''Sequence class. +"""Sequence class. -:copyright: 2018, Jeroen van der Heijden (Transceptor Technology) -''' -from .elements import NamedElement, c_export +:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com> +""" +from .elements import Element, NamedElement, c_export class Sequence(NamedElement): __slots__ = ('_elements',) - def __init__(self, *elements): + def __init__(self, *elements: Element): self._elements = self._validate_elements(elements) def _get_node_result(self, root, tree, rule, _s, node): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/pyleri/this.py new/pyleri-1.4.2/pyleri/this.py --- old/pyleri-1.3.3/pyleri/this.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/pyleri/this.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,7 +1,7 @@ -'''This class and THIS instance. +"""This class and THIS instance. -:copyright: 2018, Jeroen van der Heijden (Transceptor Technology) -''' +:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com> +""" from .elements import Element diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/pyleri/token.py new/pyleri-1.4.2/pyleri/token.py --- old/pyleri-1.3.3/pyleri/token.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/pyleri/token.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,7 +1,7 @@ -'''Token class. +"""Token class. -:copyright: 2018, Jeroen van der Heijden (Transceptor Technology) -''' +:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com> +""" from .elements import NamedElement, c_export, go_export, java_export @@ -9,7 +9,7 @@ __slots__ = ('_token',) - def __init__(self, token): + def __init__(self, token: str): if not isinstance(token, str): raise TypeError('Token(): first argument must be a string ' 'value, got {}'.format(token)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/pyleri/tokens.py new/pyleri-1.4.2/pyleri/tokens.py --- old/pyleri-1.3.3/pyleri/tokens.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/pyleri/tokens.py 2023-03-16 09:49:04.000000000 +0100 @@ -1,7 +1,7 @@ -'''Tokens class. +"""Tokens class. -:copyright: 2018, Jeroen van der Heijden (Transceptor Technology) -''' +:copyright: 2021, Jeroen van der Heijden <jer...@cesbit.com> +""" from .elements import NamedElement, c_export, go_export, java_export @@ -9,7 +9,7 @@ __slots__ = ('_tokens',) - def __init__(self, tokens): + def __init__(self, tokens: str): self._tokens = tokens.split() self._tokens.sort(key=len, reverse=True) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/setup.py new/pyleri-1.4.2/setup.py --- old/pyleri-1.3.3/setup.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/setup.py 2023-03-16 09:49:04.000000000 +0100 @@ -23,10 +23,10 @@ long_description=long_description, long_description_content_type='text/markdown', author='Jeroen van der Heijden', - author_email='jeroen@transceptor.technology', - url='https://github.com/transceptor-technology/pyleri', + author_email='jer...@cesbit.com', + url='https://github.com/cesbit/pyleri', download_url=( - 'https://github.com/transceptor-technology/' + 'https://github.com/cesbit/' 'pyleri/tarball/{}'.format(version)), keywords=['parser', 'grammar', 'autocompletion'], classifiers=[ @@ -35,12 +35,10 @@ 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.0', - 'Programming Language :: Python :: 3.1', - 'Programming Language :: Python :: 3.2', - 'Programming Language :: Python :: 3.3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3 :: Only', 'Topic :: Software Development :: Libraries :: Python Modules', 'Topic :: Text Processing :: Linguistic' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/test/test_json_lang.py new/pyleri-1.4.2/test/test_json_lang.py --- old/pyleri-1.3.3/test/test_json_lang.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/test/test_json_lang.py 2023-03-16 09:49:04.000000000 +0100 @@ -17,7 +17,7 @@ def test_json(self): grammar = JsonGrammar() # should be true - self.assertTrue(grammar.parse(''' + self.assertTrue(grammar.parse(""" { "hoi \\"Iris\\"": [ 5, @@ -27,7 +27,7 @@ "b": false } ] - }''').is_valid) + }""").is_valid) # keys must be strings self.assertFalse(grammar.parse('{5: true}').is_valid) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/test/test_list.py new/pyleri-1.4.2/test/test_list.py --- old/pyleri-1.3.3/test/test_list.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/test/test_list.py 2023-03-16 09:49:04.000000000 +0100 @@ -63,6 +63,18 @@ 'error at position 0, expecting: hi' ) + self.assertEqual( + grammar.parse('').as_str(line_number=True), + 'error at line 1, col 1, expecting: hi' + ) + + self.assertEqual( + grammar.parse(""" + hi-hi-hi-hi-hi + """).as_str(line_number=True), + 'error at line 2, col 26, expecting: end_of_statement' + ) + if __name__ == '__main__': unittest.main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/test/test_prio.py new/pyleri-1.4.2/test/test_prio.py --- old/pyleri-1.3.3/test/test_prio.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/test/test_prio.py 2023-03-16 09:49:04.000000000 +0100 @@ -10,6 +10,7 @@ Sequence, Keyword, Prio, + List, THIS, MaxRecursionError, ) # nopep8 @@ -46,6 +47,28 @@ ')))))))))))))))))))))))))))))))))))))))))))))))))))' ) + def test_prio_list(self): + arr = Sequence('[', List(THIS), ']') + prio = Prio(Keyword('nil'), arr) + grammar = create_grammar(prio) + self.assertTrue(grammar.parse('[]').is_valid) + self.assertTrue(grammar.parse('[[nil]]').is_valid) + self.assertTrue( + grammar.parse( + '[' + 'nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,' + 'nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,' + 'nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,' + 'nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,' + 'nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,' + 'nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil' + ']').is_valid) + with self.assertRaises(MaxRecursionError): + grammar.parse( + '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[hi' + ']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' + ) + if __name__ == '__main__': unittest.main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyleri-1.3.3/test/test_regex.py new/pyleri-1.4.2/test/test_regex.py --- old/pyleri-1.3.3/test/test_regex.py 2020-12-01 21:35:27.000000000 +0100 +++ new/pyleri-1.4.2/test/test_regex.py 2023-03-16 09:49:04.000000000 +0100 @@ -28,6 +28,15 @@ if elem is regex else None), 'error at position 0, expecting: single_quoted_string' ) + self.assertTrue(grammar.parse("'hi'").is_valid) + + def test_flags_regex(self): + regex = Regex(r'(?s)//.*?(\r?\n|$)') + grammar = create_grammar(regex) + + self.assertTrue(grammar.parse(""" + //test + """).is_valid) if __name__ == '__main__':