Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

parsita

Package Overview
Dependencies
Maintainers
1
Versions
30
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

parsita - npm Package Compare versions

Comparing version
2.0.0
to
2.1.0
+1
-1
PKG-INFO
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

[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 (