CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-parsec

A universal Python parser combinator library inspired by Parsec library of Haskell

Pending
Overview
Eval results
Files

core-primitives.mddocs/

Core Parsing Primitives

The fundamental classes and types that form the foundation of all parsing operations. These include the main Parser class that wraps parsing functions, the Value type for representing parsing results, and comprehensive error reporting with source location information.

Capabilities

Parser Class

The core parser combinator class that wraps parsing functions and provides the foundation for all parsing operations. Every parser is an instance of this class.

class Parser:
    """
    A Parser wraps a function to do parsing work.
    The wrapped function takes (text, index) and returns Value.success() or Value.failure().
    """
    
    def __init__(self, fn):
        """
        Create a parser from a parsing function.
        
        Args:
            fn: Function that takes (text: str, index: int) -> Value
        """
    
    def __call__(self, text, index):
        """
        Call the wrapped parsing function directly.
        
        Args:
            text (str): Text to parse
            index (int): Starting position
            
        Returns:
            Value: Success or failure result
        """
    
    def parse(self, text):
        """
        Parse a given string completely.
        
        Args:
            text (str): String to parse
            
        Returns:
            Parsed value on success
            
        Raises:
            ParseError: If parsing fails
        """
    
    def parse_partial(self, text):
        """
        Parse the longest possible prefix of a string.
        
        Args:
            text (str): String to parse
            
        Returns:
            tuple: (parsed_value, remaining_text)
            
        Raises:
            ParseError: If parsing fails
        """
    
    def parse_strict(self, text):
        """
        Parse entire string with no remaining text allowed.
        
        Args:
            text (str): String to parse completely
            
        Returns:
            Parsed value on success
            
        Raises:
            ParseError: If parsing fails or text remains
        """

Value Type

Result container that represents the outcome of a parsing operation, containing success/failure status, position information, parsed value, and error expectations.

class Value:
    """
    Represents the result of a parsing operation.
    
    Attributes:
        status (bool): True for success, False for failure
        index (int): Position after parsing
        value: Parsed value (None on failure)
        expected (str): Expected input description (for failures)
    """
    
    @staticmethod
    def success(index, actual):
        """
        Create a successful parsing result.
        
        Args:
            index (int): Position after consuming input
            actual: The parsed value
            
        Returns:
            Value: Success result
        """
    
    @staticmethod
    def failure(index, expected):
        """
        Create a failed parsing result.
        
        Args:
            index (int): Position where parsing failed
            expected (str): Description of what was expected
            
        Returns:
            Value: Failure result
        """
    
    def aggregate(self, other=None):
        """
        Combine results from sequential parsers.
        
        Args:
            other (Value, optional): Other parsing result to combine
            
        Returns:
            Value: Combined result with concatenated values
        """

Parse Error

Comprehensive error reporting with source location information, including line and column numbers for debugging complex parsing failures.

class ParseError(RuntimeError):
    """
    Parser error with detailed location information.
    
    Attributes:
        expected (str): What the parser expected to find
        text (str): Original input text being parsed
        index (int): Position where error occurred
    """
    
    def __init__(self, expected, text, index):
        """
        Create a parsing error.
        
        Args:
            expected (str): Description of expected input
            text (str): The text being parsed
            index (int): Character position of the error
        """
    
    @staticmethod
    def loc_info(text, index):
        """
        Calculate line and column from text position.
        
        Args:
            text (str): Source text
            index (int): Character position
            
        Returns:
            tuple: (line_number, column_number) both 0-based
            
        Raises:
            ValueError: If index is beyond text length
        """
    
    def loc(self):
        """
        Get formatted location string for this error.
        
        Returns:
            str: Location in format "line:column" or error description
        """
    
    def __str__(self):
        """
        Get string representation of the error.
        
        Returns:
            str: Error message with expected input and location
            
        Note:
            The original implementation contains a typo: it returns 
            "excepted X at Y" instead of "expected X at Y".
        """

Utility Exports

Standard library utilities exported for convenience when building parsers.

# From collections module
namedtuple: type
    """
    Factory function for creating tuple subclasses with named fields.
    Exported for creating custom result types in parsers.
    """

# From functools module  
wraps: function
    """
    Decorator to preserve function metadata when creating wrapper functions.
    Exported for use in custom parser decorators.
    """

# Standard library module
re: module
    """
    Regular expression module for pattern matching.
    Used internally by regex() parser and available for custom parsers.
    """

Usage Examples

Basic Parser Creation

from parsec import Parser, Value

# Create a parser that matches single character 'x'
def x_parser_fn(text, index):
    if index < len(text) and text[index] == 'x':
        return Value.success(index + 1, 'x')
    else:
        return Value.failure(index, 'character x')

x_parser = Parser(x_parser_fn)

# Use the parser
result = x_parser.parse("xyz")  # Returns 'x'

Error Handling

from parsec import ParseError, string

parser = string("hello")

try:
    result = parser.parse("world")
except ParseError as e:
    print(f"Expected: {e.expected}")  # Expected: hello
    print(f"At position: {e.index}")  # At position: 0
    print(f"Location: {e.loc()}")     # Location: 0:0

Using Different Parse Methods

from parsec import string, many, letter

parser = many(letter())

# parse() - consume what it can, ignore rest
result = parser.parse("abc123")  # Returns ['a', 'b', 'c']

# parse_partial() - return both result and remaining text  
result, remaining = parser.parse_partial("abc123")  
# result: ['a', 'b', 'c'], remaining: "123"

# parse_strict() - entire input must be consumed
try:
    result = parser.parse_strict("abc123")  # Raises ParseError
except ParseError:
    print("Text remaining after parsing")

Install with Tessl CLI

npx tessl i tessl/pypi-parsec

docs

character-parsing.md

combinators.md

core-primitives.md

index.md

parser-generation.md

parser-operators.md

tile.json