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: Element-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 translation units organized across multiple workspace roots
- Whitespace Handling: A single visitor mixin supports both insignificant and significant whitespace grammars (e.g., Python-like indentation); grammars that define
INDENT/DEDENTtokens are detected automatically - Multiline String Extraction: Extract multiline string content that must be vertically aligned with its opening token, with detailed errors on misalignment
How to use dbrownell_ParserLib
The typical workflow for creating a parser with this library involves the following steps. For detailed examples, see the test files in the repository, particularly the end-to-end tests that demonstrate complete parsing workflows.
1. Define an ANTLR Grammar
Create a .g4 grammar file defining your language syntax:
grammar Calculator;
expr : expr ('*'|'/') expr # BinaryOp
| expr ('+'|'-') 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 pathlib import Path
from dbrownell_ParserLib.antlr.build_antlr_grammar import BuildAntlrGrammar
BuildAntlrGrammar(
dm, # DoneManager instance
Path("Calculator.g4"),
Path("output_dir"),
)
3. Create Custom Visitor
Implement a visitor that converts ANTLR parse trees to Element objects:
from dataclasses import dataclass
from dbrownell_ParserLib.antlr.antlr_visitor_mixin import AntlrVisitorMixin
from dbrownell_ParserLib.element import Element
from dbrownell_ParserLib.terminal_element import TerminalElement
from CalculatorVisitor import CalculatorVisitor as GeneratedVisitor
@dataclass(eq=False)
class BinaryExpression(Element):
left: Element
operator: TerminalElement[str]
right: Element
def _GenerateAcceptDetails(self):
yield "left", self.left
yield "operator", self.operator
yield "right", self.right
class CalculatorVisitor(AntlrVisitorMixin, GeneratedVisitor):
def visitBinaryOp(self, ctx):
operator = TerminalElement[str](self.CreateRegion(ctx.children[1]), ctx.children[1].getText())
children = self.GetChildren(ctx)
assert len(children) == 2, children
self._stack.append(
BinaryExpression(
self.CreateRegion(ctx),
children[0],
operator,
children[1],
)
)
def visitNumber(self, ctx):
self._stack.append(
TerminalElement[int](self.CreateRegion(ctx), int(ctx.getText()))
)
4. Create Parser Instance
Use CreateAntlrParser to build a callable parser. Grammars that define INDENT and DEDENT tokens (significant whitespace) are detected automatically; no additional configuration is required.
from dbrownell_ParserLib.antlr.antlr_parser import CreateAntlrParser
parser = CreateAntlrParser(
CalculatorLexer,
CalculatorParser,
CalculatorVisitor,
lambda p: p.expr(), # Entry point rule
)
5. Parse Files
Parse single files, multiple files, or entire workspaces:
from dbrownell_ParserLib.errors import Error
# 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
6. Traverse the AST
Use the visitor pattern to process your AST:
from contextlib import contextmanager
from dbrownell_ParserLib.visitors import ElementVisitorHelper, VisitResult
class EvaluatorVisitor(ElementVisitorHelper):
@contextmanager
def OnBinaryExpression(self, element):
# Process binary expressions
yield VisitResult.Continue
ast.Accept(EvaluatorVisitor())
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.
Metadata
Release files for dbrownell-parserlib 0.13.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| dbrownell_parserlib-0.13.5.tar.gz | 2.0 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dbrownell_parserlib-0.13.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 4.0 MB
Release files / dbrownell_parserlib-0.13.5.tar.gz
| Download URL | dbrownell_parserlib-0.13.5.tar.gz |
|---|---|
| Size | 2.0 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1541a1c09d55ecf27d681bac163564edefcdf3a4c8529233090c836ba76b97f0
|
|
BLAKE2b-256 checksum How to use checksums |
b102fac85250b474008158500c13e4e8a05f82b73483e3634cc29e902eb755ab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","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}
|
Release files / dbrownell_parserlib-0.13.5-py3-none-any.whl
| Download URL | dbrownell_parserlib-0.13.5-py3-none-any.whl |
|---|---|
| Size | 2.0 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fc1a58982e26a9c7895838fcbfca5934cb16e9e5e3e543780e68a08a20296937
|
|
BLAKE2b-256 checksum How to use checksums |
e4b35a3a8243ef78616239f4d9b16139278548b1fffc9d79ce302284f5e01095
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","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}
|