parsita
Advanced tools
+1
-1
| Metadata-Version: 2.1 | ||
| Name: parsita | ||
| Version: 2.0.0 | ||
| Version: 2.1.0 | ||
| Summary: Parser combinator library for Python | ||
@@ -5,0 +5,0 @@ Home-page: https://github.com/drhagen/parsita |
+1
-1
| [tool.poetry] | ||
| name = "parsita" | ||
| version = "2.0.0" | ||
| version = "2.1.0" | ||
| description = "Parser combinator library for Python" | ||
@@ -5,0 +5,0 @@ authors = ["David Hagen <david@drhagen.com>"] |
| from ._alternative import FirstAlternativeParser, LongestAlternativeParser, first, longest | ||
| from ._any import AnyParser, any1 | ||
| from ._base import Parser | ||
| from ._base import Parser, wrap_literal | ||
| from ._conversion import ConversionParser, TransformationParser | ||
@@ -5,0 +5,0 @@ from ._debug import DebugParser, debug |
@@ -6,4 +6,3 @@ __all__ = ["FirstAlternativeParser", "first", "LongestAlternativeParser", "longest"] | ||
| from ..state import Continue, Input, Output, Reader, State | ||
| from ._base import Parser | ||
| from ._literal import lit | ||
| from ._base import Parser, wrap_literal | ||
@@ -16,5 +15,5 @@ | ||
| def consume(self, state: State[Input], reader: Reader[Input]): | ||
| def _consume(self, state: State[Input], reader: Reader[Input]): | ||
| for parser in self.parsers: | ||
| status = parser.cached_consume(state, reader) | ||
| status = parser.consume(state, reader) | ||
| if isinstance(status, Continue): | ||
@@ -51,5 +50,3 @@ return status | ||
| """ | ||
| cleaned_parsers = [ | ||
| lit(parser_i) if isinstance(parser_i, str) else parser_i for parser_i in [parser, *parsers] | ||
| ] | ||
| cleaned_parsers = [wrap_literal(parser_i) for parser_i in [parser, *parsers]] | ||
| return FirstAlternativeParser(*cleaned_parsers) | ||
@@ -63,6 +60,6 @@ | ||
| def consume(self, state: State[Input], reader: Reader[Input]): | ||
| def _consume(self, state: State[Input], reader: Reader[Input]): | ||
| longest_success: Optional[Continue] = None | ||
| for parser in self.parsers: | ||
| status = parser.cached_consume(state, reader) | ||
| status = parser.consume(state, reader) | ||
| if isinstance(status, Continue): | ||
@@ -104,5 +101,3 @@ if ( | ||
| """ | ||
| cleaned_parsers = [ | ||
| lit(parser_i) if isinstance(parser_i, str) else parser_i for parser_i in [parser, *parsers] | ||
| ] | ||
| cleaned_parsers = [wrap_literal(parser_i) for parser_i in [parser, *parsers]] | ||
| return LongestAlternativeParser(*cleaned_parsers) |
@@ -21,3 +21,3 @@ __all__ = ["AnyParser", "any1"] | ||
| def consume( | ||
| def _consume( | ||
| self, state: State[Input], reader: Reader[Input] | ||
@@ -24,0 +24,0 @@ ) -> Optional[Continue[Input, Input]]: |
| from __future__ import annotations | ||
| __all__ = ["Parser"] | ||
| __all__ = ["Parser", "wrap_literal"] | ||
| from abc import abstractmethod | ||
| from typing import Any, Generic, List, Optional, Sequence, Union | ||
@@ -26,2 +27,11 @@ | ||
| def wrap_literal(obj: Any) -> Parser: | ||
| from ._literal import LiteralParser | ||
| if isinstance(obj, Parser): | ||
| return obj | ||
| else: | ||
| return LiteralParser(obj, options.whitespace) | ||
| class Parser(Generic[Input, Output]): | ||
@@ -32,7 +42,7 @@ """Abstract base class for all parser combinators. | ||
| 1. Implement the ``consume`` method | ||
| 1. Implement the ``_consume`` method | ||
| 2. Implement the ``__repr__`` method | ||
| Attributes: | ||
| protected (bool): The context classes set this flag to true whenever a | ||
| protected (bool): The metaclasses set this flag to true whenever a | ||
| parser is assigned to a name. Operators that flatten the parsers | ||
@@ -60,3 +70,3 @@ they receive (``__or__`` and ``__and__``) will not flatten parsers | ||
| def cached_consume( | ||
| def consume( | ||
| self, state: State[Input], reader: Reader[Input] | ||
@@ -76,5 +86,5 @@ ) -> Optional[Continue[Input, Output]]: | ||
| Individual parsers need to implement ``consume``, but not | ||
| ``cached_consume``. But all combinations should invoke | ||
| ``cached_consume`` instead of ``consume`` on their member parsers. | ||
| Individual parsers need to implement ``_consume``, but not ``consume``. | ||
| But all combinations should invoke ``consume`` instead of ``_consume`` | ||
| on their member parsers. | ||
@@ -97,3 +107,3 @@ Args: | ||
| result = self.consume(state, reader) | ||
| result = self._consume(state, reader) | ||
@@ -104,3 +114,4 @@ state.memo[key] = result | ||
| def consume( | ||
| @abstractmethod | ||
| def _consume( | ||
| self, state: State[Input], reader: Reader[Input] | ||
@@ -123,3 +134,3 @@ ) -> Optional[Continue[Input, Output]]: | ||
| def parse(self, source: Union[Sequence[Input], Reader]) -> Result[Output]: | ||
| """Abstract method for completely parsing a source. | ||
| """Completely parse a source. | ||
@@ -132,6 +143,7 @@ Args: | ||
| the value from ``Continue`` is copied to make a ``Success``. If the | ||
| parser failed in matching, the error message is copied to a | ||
| ``Failure``. If the parser succeeded but the source was not | ||
| completely consumed, a ``Failure`` with a message indicating this | ||
| is returned. | ||
| parser failed in matching, the expected patterns at the farthest | ||
| point in the source are used to construct a ``ParseError`, which is | ||
| then used to contruct a ``Failure``. If the parser succeeded but the | ||
| source was not completely consumed, it returns a ``Failure`` with a | ||
| ``ParseError` indicating this. | ||
@@ -153,3 +165,3 @@ If a ``Reader`` is passed in, it is used directly. Otherwise, the source | ||
| status = (self << eof).cached_consume(state, reader) | ||
| status = (self << eof).consume(state, reader) | ||
@@ -184,15 +196,6 @@ if isinstance(status, Continue): | ||
| @staticmethod | ||
| def handle_other(obj: Any) -> Parser: | ||
| from ._literal import LiteralParser | ||
| if isinstance(obj, Parser): | ||
| return obj | ||
| else: | ||
| return LiteralParser(obj, options.whitespace) | ||
| def __or__(self, other) -> Parser: | ||
| from ._alternative import LongestAlternativeParser | ||
| other = self.handle_other(other) | ||
| other = wrap_literal(other) | ||
| parsers: List[Parser] = [] | ||
@@ -210,3 +213,3 @@ if isinstance(self, LongestAlternativeParser) and not self.protected: | ||
| def __ror__(self, other) -> Parser: | ||
| other = self.handle_other(other) | ||
| other = wrap_literal(other) | ||
| return other.__or__(self) | ||
@@ -217,3 +220,3 @@ | ||
| other = self.handle_other(other) | ||
| other = wrap_literal(other) | ||
| if isinstance(self, SequentialParser) and not self.protected: | ||
@@ -225,3 +228,3 @@ return SequentialParser(*self.parsers, other) | ||
| def __rand__(self, other) -> Parser: | ||
| other = self.handle_other(other) | ||
| other = wrap_literal(other) | ||
| return other.__and__(self) | ||
@@ -232,7 +235,7 @@ | ||
| other = self.handle_other(other) | ||
| other = wrap_literal(other) | ||
| return DiscardLeftParser(self, other) | ||
| def __rrshift__(self, other) -> Parser: | ||
| other = self.handle_other(other) | ||
| other = wrap_literal(other) | ||
| return other.__rshift__(self) | ||
@@ -243,7 +246,7 @@ | ||
| other = self.handle_other(other) | ||
| other = wrap_literal(other) | ||
| return DiscardRightParser(self, other) | ||
| def __rlshift__(self, other) -> Parser: | ||
| other = self.handle_other(other) | ||
| other = wrap_literal(other) | ||
| return other.__lshift__(self) | ||
@@ -250,0 +253,0 @@ |
@@ -17,6 +17,6 @@ __all__ = ["ConversionParser", "TransformationParser"] | ||
| def consume( | ||
| def _consume( | ||
| self, state: State[Input], reader: Reader[Input] | ||
| ) -> Optional[Continue[Input, Convert]]: | ||
| status = self.parser.cached_consume(state, reader) | ||
| status = self.parser.consume(state, reader) | ||
@@ -42,10 +42,10 @@ if isinstance(status, Continue): | ||
| def consume( | ||
| def _consume( | ||
| self, state: State[Input], reader: Reader[Input] | ||
| ) -> Optional[Continue[Input, Convert]]: | ||
| status = self.parser.cached_consume(state, reader) | ||
| status = self.parser.consume(state, reader) | ||
| if isinstance(status, Continue): | ||
| return self.transformer(status.value).cached_consume(state, status.remainder) | ||
| return self.transformer(status.value).consume(state, status.remainder) | ||
| else: | ||
| return status |
@@ -6,4 +6,3 @@ __all__ = ["DebugParser", "debug"] | ||
| from ..state import Input, Output, Reader, State | ||
| from ._base import Parser | ||
| from ._literal import lit | ||
| from ._base import Parser, wrap_literal | ||
@@ -24,3 +23,3 @@ | ||
| def consume(self, state: State[Input], reader: Reader[Input]): | ||
| def _consume(self, state: State[Input], reader: Reader[Input]): | ||
| if self.verbose: | ||
@@ -32,3 +31,3 @@ print(f"""Evaluating token {reader.next_token()} using parser {self._parser_string}""") | ||
| result = self.parser.cached_consume(state, reader) | ||
| result = self.parser.consume(state, reader) | ||
@@ -68,4 +67,2 @@ if self.verbose: | ||
| """ | ||
| if isinstance(parser, str): | ||
| parser = lit(parser) | ||
| return DebugParser(parser, verbose, callback) | ||
| return DebugParser(wrap_literal(parser), verbose, callback) |
@@ -13,3 +13,3 @@ __all__ = ["EndOfSourceParser", "eof"] | ||
| def consume( | ||
| def _consume( | ||
| self, state: State[Input], reader: Reader[Input] | ||
@@ -16,0 +16,0 @@ ) -> Optional[Continue[Input, None]]: |
@@ -16,5 +16,5 @@ __all__ = ["LiteralParser", "lit"] | ||
| def consume(self, state: State[Input], reader: Reader[Input]): | ||
| def _consume(self, state: State[Input], reader: Reader[Input]): | ||
| if self.whitespace is not None: | ||
| status = self.whitespace.cached_consume(state, reader) | ||
| status = self.whitespace.consume(state, reader) | ||
| reader = status.remainder | ||
@@ -40,3 +40,3 @@ | ||
| if self.whitespace is not None: | ||
| status = self.whitespace.cached_consume(state, reader) | ||
| status = self.whitespace.consume(state, reader) | ||
| reader = status.remainder | ||
@@ -43,0 +43,0 @@ |
@@ -6,4 +6,3 @@ __all__ = ["OptionalParser", "opt"] | ||
| from ..state import Continue, Input, Output, Reader, State | ||
| from ._base import Parser | ||
| from ._literal import lit | ||
| from ._base import Parser, wrap_literal | ||
@@ -16,4 +15,4 @@ | ||
| def consume(self, state: State[Input], reader: Reader[Input]): | ||
| status = self.parser.cached_consume(state, reader) | ||
| def _consume(self, state: State[Input], reader: Reader[Input]): | ||
| status = self.parser.consume(state, reader) | ||
@@ -39,4 +38,2 @@ if isinstance(status, Continue): | ||
| """ | ||
| if isinstance(parser, str): | ||
| parser = lit(parser) | ||
| return OptionalParser(parser) | ||
| return OptionalParser(wrap_literal(parser)) |
@@ -6,3 +6,3 @@ __all__ = ["PredicateParser", "pred"] | ||
| from ..state import Continue, Input, Output, Reader, State | ||
| from ._base import Parser | ||
| from ._base import Parser, wrap_literal | ||
@@ -19,4 +19,4 @@ | ||
| def consume(self, state: State[Input], reader: Reader[Input]): | ||
| status = self.parser.cached_consume(state, reader) | ||
| def _consume(self, state: State[Input], reader: Reader[Input]): | ||
| status = self.parser.consume(state, reader) | ||
| if isinstance(status, Continue): | ||
@@ -41,3 +41,3 @@ if self.predicate(status.value): | ||
| Args: | ||
| parser: Provides the result | ||
| parser: ``Parser`` or literal | ||
| predicate: A predicate for the result to satisfy | ||
@@ -49,2 +49,2 @@ description: Name for the predicate, to use in error reporting | ||
| """ | ||
| return PredicateParser(parser, predicate, description) | ||
| return PredicateParser(wrap_literal(parser), predicate, description) |
@@ -19,5 +19,5 @@ __all__ = ["RegexParser", "reg"] | ||
| def consume(self, state: State[StringType], reader: Reader[StringType]): | ||
| def _consume(self, state: State[StringType], reader: Reader[StringType]): | ||
| if self.whitespace is not None: | ||
| status = self.whitespace.cached_consume(state, reader) | ||
| status = self.whitespace.consume(state, reader) | ||
| reader = status.remainder | ||
@@ -35,3 +35,3 @@ | ||
| if self.whitespace is not None: | ||
| status = self.whitespace.cached_consume(state, reader) | ||
| status = self.whitespace.consume(state, reader) | ||
| reader = status.remainder | ||
@@ -38,0 +38,0 @@ |
@@ -6,4 +6,3 @@ __all__ = ["RepeatedSeparatedParser", "repsep", "RepeatedOnceSeparatedParser", "rep1sep"] | ||
| from ..state import Continue, Input, Output, Reader, RecursionError, State | ||
| from ._base import Parser | ||
| from ._literal import lit | ||
| from ._base import Parser, wrap_literal | ||
@@ -26,4 +25,4 @@ | ||
| def consume(self, state: State[Input], reader: Reader[Input]): | ||
| status = self.parser.cached_consume(state, reader) | ||
| def _consume(self, state: State[Input], reader: Reader[Input]): | ||
| status = self.parser.consume(state, reader) | ||
@@ -42,5 +41,5 @@ if not isinstance(status, Continue): | ||
| # updated until after the parser succeeds. | ||
| status = self.separator.cached_consume(state, remainder) | ||
| status = self.separator.consume(state, remainder) | ||
| if isinstance(status, Continue): | ||
| status = self.parser.cached_consume(state, status.remainder) | ||
| status = self.parser.consume(state, status.remainder) | ||
| if isinstance(status, Continue): | ||
@@ -93,7 +92,3 @@ if remainder.position == status.remainder.position: | ||
| """ | ||
| if isinstance(parser, str): | ||
| parser = lit(parser) | ||
| if isinstance(separator, str): | ||
| separator = lit(separator) | ||
| return RepeatedSeparatedParser(parser, separator, min=min, max=max) | ||
| return RepeatedSeparatedParser(wrap_literal(parser), wrap_literal(separator), min=min, max=max) | ||
@@ -107,4 +102,4 @@ | ||
| def consume(self, state: State[Input], reader: Reader[Input]): | ||
| status = self.parser.cached_consume(state, reader) | ||
| def _consume(self, state: State[Input], reader: Reader[Input]): | ||
| status = self.parser.consume(state, reader) | ||
@@ -122,5 +117,5 @@ if status is None: | ||
| # updated until after the parser succeeds. | ||
| status = self.separator.cached_consume(state, remainder) | ||
| status = self.separator.consume(state, remainder) | ||
| if isinstance(status, Continue): | ||
| status = self.parser.cached_consume(state, status.remainder) | ||
| status = self.parser.consume(state, status.remainder) | ||
| if isinstance(status, Continue): | ||
@@ -157,6 +152,2 @@ if remainder.position == status.remainder.position: | ||
| """ | ||
| if isinstance(parser, str): | ||
| parser = lit(parser) | ||
| if isinstance(separator, str): | ||
| separator = lit(separator) | ||
| return RepeatedOnceSeparatedParser(parser, separator) | ||
| return RepeatedOnceSeparatedParser(wrap_literal(parser), wrap_literal(separator)) |
@@ -6,4 +6,3 @@ __all__ = ["RepeatedOnceParser", "rep1", "RepeatedParser", "rep"] | ||
| from ..state import Continue, Input, Output, Reader, RecursionError, State | ||
| from ._base import Parser | ||
| from ._literal import lit | ||
| from ._base import Parser, wrap_literal | ||
@@ -16,4 +15,4 @@ | ||
| def consume(self, state: State[Input], reader: Reader[Input]): | ||
| status = self.parser.cached_consume(state, reader) | ||
| def _consume(self, state: State[Input], reader: Reader[Input]): | ||
| status = self.parser.consume(state, reader) | ||
@@ -26,3 +25,3 @@ if status is None: | ||
| while True: | ||
| status = self.parser.cached_consume(state, remainder) | ||
| status = self.parser.consume(state, remainder) | ||
| if isinstance(status, Continue): | ||
@@ -54,5 +53,3 @@ if remainder.position == status.remainder.position: | ||
| """ | ||
| if isinstance(parser, str): | ||
| parser = lit(parser) | ||
| return RepeatedOnceParser(parser) | ||
| return RepeatedOnceParser(wrap_literal(parser)) | ||
@@ -67,3 +64,3 @@ | ||
| def consume(self, state: State[Input], reader: Reader[Input]): | ||
| def _consume(self, state: State[Input], reader: Reader[Input]): | ||
| output: List[Output] = [] | ||
@@ -73,3 +70,3 @@ remainder = reader | ||
| while self.max is None or len(output) < self.max: | ||
| status = self.parser.cached_consume(state, remainder) | ||
| status = self.parser.consume(state, remainder) | ||
| if isinstance(status, Continue): | ||
@@ -112,4 +109,2 @@ if remainder.position == status.remainder.position: | ||
| """ | ||
| if isinstance(parser, str): | ||
| parser = lit(parser) | ||
| return RepeatedParser(parser, min=min, max=max) | ||
| return RepeatedParser(wrap_literal(parser), min=min, max=max) |
@@ -15,3 +15,3 @@ __all__ = ["SequentialParser", "DiscardLeftParser", "DiscardRightParser"] | ||
| def consume(self, state: State[Input], reader: Reader[Input]): | ||
| def _consume(self, state: State[Input], reader: Reader[Input]): | ||
| output = [] | ||
@@ -21,3 +21,3 @@ remainder = reader | ||
| for parser in self.parsers: | ||
| status = parser.cached_consume(state, remainder) | ||
| status = parser.consume(state, remainder) | ||
| if isinstance(status, Continue): | ||
@@ -45,6 +45,6 @@ output.append(status.value) | ||
| def consume(self, state: State[Input], reader: Reader[Input]): | ||
| status = self.left.cached_consume(state, reader) | ||
| def _consume(self, state: State[Input], reader: Reader[Input]): | ||
| status = self.left.consume(state, reader) | ||
| if isinstance(status, Continue): | ||
| return self.right.cached_consume(state, status.remainder) | ||
| return self.right.consume(state, status.remainder) | ||
| else: | ||
@@ -64,6 +64,6 @@ return None | ||
| def consume(self, state: State[Input], reader: Reader[Input]): | ||
| status1 = self.left.cached_consume(state, reader) | ||
| def _consume(self, state: State[Input], reader: Reader[Input]): | ||
| status1 = self.left.consume(state, reader) | ||
| if isinstance(status1, Continue): | ||
| status2 = self.right.cached_consume(state, status1.remainder) | ||
| status2 = self.right.consume(state, status1.remainder) | ||
| if isinstance(status2, Continue): | ||
@@ -70,0 +70,0 @@ return Continue(status2.remainder, status1.value) |
@@ -14,3 +14,3 @@ __all__ = ["SuccessParser", "success", "FailureParser", "failure"] | ||
| def consume(self, state: State[Input], reader: Reader[Input]) -> Continue[Input, Output]: | ||
| def _consume(self, state: State[Input], reader: Reader[Input]) -> Continue[Input, Output]: | ||
| return Continue(reader, self.value) | ||
@@ -40,3 +40,3 @@ | ||
| def consume(self, state: State[Input], reader: Reader[Input]) -> None: | ||
| def _consume(self, state: State[Input], reader: Reader[Input]) -> None: | ||
| state.register_failure(self.expected, reader) | ||
@@ -43,0 +43,0 @@ return None |
@@ -6,4 +6,3 @@ __all__ = ["UntilParser", "until"] | ||
| from ..state import Continue, Input, Output, Reader, State | ||
| from ._base import Parser | ||
| from ._literal import lit | ||
| from ._base import Parser, wrap_literal | ||
@@ -16,6 +15,6 @@ | ||
| def consume(self, state: State[Input], reader: Reader[Input]): | ||
| def _consume(self, state: State[Input], reader: Reader[Input]): | ||
| start_position = reader.position | ||
| while True: | ||
| status = self.parser.cached_consume(state, reader) | ||
| status = self.parser.consume(state, reader) | ||
@@ -44,4 +43,2 @@ if isinstance(status, Continue): | ||
| """ | ||
| if isinstance(parser, str): | ||
| parser = lit(parser) | ||
| return UntilParser(parser) | ||
| return UntilParser(wrap_literal(parser)) |
@@ -176,3 +176,3 @@ from __future__ import annotations | ||
| def current_line(self): | ||
| def _current_line(self): | ||
| # StringIO is not consistent in how it treats empty strings | ||
@@ -227,3 +227,3 @@ # and other strings not ending in newlines. Ensure that the | ||
| line_index, character_index, line, pointer = self.current_line() | ||
| line_index, character_index, line, pointer = self._current_line() | ||
@@ -248,3 +248,3 @@ return ( | ||
| """ | ||
| line_index, character_index, line, pointer = self.current_line() | ||
| line_index, character_index, line, pointer = self._current_line() | ||
@@ -251,0 +251,0 @@ return ( |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
68821
-0.98%1368
-1.87%