Skip to main content

Functionality useful when creating parsers.

Project description

Project: License

Package: PyPI - Python Version PyPI - Version PyPI - Downloads

Development: uv ruff ty pytest CI Code Coverage GitHub commit activity

Contents

Overview

dbrownell_ParserLib is a Python library that provides utility functionality for creating parsers, with a primary focus on ANTLR (Another Tool for Language Recognition) integration. The library simplifies the process of building parsers that produce strongly-typed abstract syntax trees (ASTs) with comprehensive source location tracking.

Key Features

  • ANTLR Integration: Streamlined wrapper around ANTLR for Python, handling grammar compilation and parser generation
  • AST Representation: Expression-based AST nodes with automatic parent-child relationship management
  • Source Location Tracking: Every AST node tracks its source file location (filename, line, column ranges) for detailed error reporting
  • Visitor Pattern: Flexible visitor pattern implementation with fine-grained traversal control
  • Error Handling: Rich error objects that associate messages with source locations and extract Python exception tracebacks
  • Multi-threaded Parsing: Built-in support for parsing multiple files concurrently
  • Workspace Support: Parse entire directory trees with customizable file filtering
  • Whitespace Handling: Mixins for both insignificant and significant whitespace grammars (e.g., Python-like indentation)

How to use dbrownell_ParserLib

The typical workflow for creating a parser with this library involves:

1. Define an ANTLR Grammar

Create a .g4 grammar file defining your language syntax:

grammar Calculator;

expr : expr op=('*'|'/') expr   # BinaryOp
     | expr op=('+'|'-') expr   # BinaryOp
     | INT                       # Number
     ;

INT : [0-9]+ ;
WS : [ \t\n\r]+ -> skip ;

2. Build the Grammar

Use BuildAntlrGrammar to generate the lexer and parser:

from dbrownell_ParserLib import BuildAntlrGrammar
from pathlib import Path

BuildAntlrGrammar(
    dm,  # DoneManager instance
    Path("Calculator.g4"),
    Path("output_dir"),
)

3. Create Custom Visitor

Implement a visitor that converts ANTLR parse trees to Expression objects:

from dbrownell_ParserLib import (
    Expression,
    InsignificantWhitespaceAntlrVisitorMixin,
    TerminalExpression,
)
from dataclasses import dataclass

from CalculatorVisitor import CalculatorVisitor as GeneratedVisitor



@dataclass(eq=False)
class BinaryExpression(Expression):
    left: Expression
    operator: TerminalExpression[str]
    right: Expression

    def _GenerateAcceptDetails(self):
        yield "left", self.left
        yield "operator", self.operator
        yield "right", self.right

class CalculatorVisitor(InsignificantWhitespaceAntlrVisitorMixin, GeneratedVisitor):

    def visitBinaryOp(self, ctx):
        children = self.GetChildren(ctx)
        self._stack.append(
            BinaryExpression(
                self.CreateRegion(ctx),
                children[0],
                TerminalExpression[str](self.CreateRegion(ctx.children[1]), ctx.children[1].getText()),

                children[1],
            )
        )

    def visitNumber(self, ctx):
        self._stack.append(
            TerminalExpression(self.CreateRegion(ctx), int(ctx.INT().getText()))
        )

4. Create Parser Instance

Use CreateAntlrParser to build a callable parser:

from dbrownell_ParserLib import CreateAntlrParser

parser = CreateAntlrParser(
    CalculatorLexer,
    CalculatorParser,
    CalculatorVisitor,
    lambda p: p.expr(),  # Entry point rule
)

from pathlib import Path

from dbrownell_ParserLib import Error

5. Parse Files

Parse single files, multiple files, or entire workspaces:

# Parse a single file
results = parser(dm, Path("input.txt"), None)

# Parse multiple files
results = parser(dm, [Path("file1.txt"), Path("file2.txt")], None)

# Check results
for filepath, result in results.items():
    if isinstance(result, Error):
        print(f"Parse error in {filepath}: {result}")
    else:
        # result is the visitor containing the parsed AST
        ast = result._stack[0]
        # Process the AST

from contextlib import contextmanager

6. Traverse the AST

Use the visitor pattern to process your AST:

    @contextmanager

from dbrownell_ParserLib import ExpressionVisitorHelper, VisitResult

class EvaluatorVisitor(ExpressionVisitorHelper):
    def OnBinaryExpression(self, expression):
    @contextmanager

        # Process binary expressions
        yield VisitResult.Continue

        # Process terminal values
        yield VisitResult.Continue

ast.Accept(EvaluatorVisitor())

For detailed examples, see the test files in the repository, particularly the end-to-end tests that demonstrate complete parsing workflows.

Installation

Installation Method Command
Via uv uv add dbrownell_ParserLib
Via pip pip install dbrownell_ParserLib

Verifying Signed Artifacts

Artifacts are signed and verified using py-minisign and the public key in the file ./minisign_key.pub.

To verify that an artifact is valid, visit the latest release and download the .minisign signature file that corresponds to the artifact, then run the following command, replacing <filename> with the name of the artifact to be verified:

uv run --with py-minisign python -c "import minisign; minisign.PublicKey.from_file('minisign_key.pub').verify_file('<filename>'); print('The file has been verified.')"

Development

Please visit Contributing and Development for information on contributing to this project.

Additional Information

Additional information can be found at these locations.

Title Document Description
Code of Conduct CODE_OF_CONDUCT.md Information about the norms, rules, and responsibilities we adhere to when participating in this open source community.
Contributing CONTRIBUTING.md Information about contributing to this project.
Development DEVELOPMENT.md Information about development activities involved in making changes to this project.
Governance GOVERNANCE.md Information about how this project is governed.
Maintainers MAINTAINERS.md Information about individuals who maintain this project.
Security SECURITY.md Information about how to privately report security issues associated with this project.

License

dbrownell_ParserLib is licensed under the MIT license.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dbrownell_parserlib-0.8.3.tar.gz (2.0 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dbrownell_parserlib-0.8.3-py3-none-any.whl (2.0 MB view details)

Uploaded Python 3

File details

Details for the file dbrownell_parserlib-0.8.3.tar.gz.

File metadata

  • Download URL: dbrownell_parserlib-0.8.3.tar.gz
  • Upload date:
  • Size: 2.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.25 {"installer":{"name":"uv","version":"0.11.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for dbrownell_parserlib-0.8.3.tar.gz
Algorithm Hash digest
SHA256 64d48fac1706c03e2a0cfa15c55d29dc3843c80474505d862de6f926565c6096
MD5 86c6204487ef7c30c92ceacbe2f4c90e
BLAKE2b-256 def832880d0f8e292be20ce4dbf9a5e8c5512c146922b40e9b59829b8e62da72

See more details on using hashes here.

File details

Details for the file dbrownell_parserlib-0.8.3-py3-none-any.whl.

File metadata

  • Download URL: dbrownell_parserlib-0.8.3-py3-none-any.whl
  • Upload date:
  • Size: 2.0 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.25 {"installer":{"name":"uv","version":"0.11.25","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for dbrownell_parserlib-0.8.3-py3-none-any.whl
Algorithm Hash digest
SHA256 ceff9b869d2a7ee3b05e833b121fca28e4be86ff2988be15bbf4851095a118a7
MD5 0efccf6e2a2f85bd0fe48183ae95f20c
BLAKE2b-256 564c5d565fc2b4eea76f3012c54de1ff0de61bdb7b5447117ce3ed1dd365c486

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page