Module

parser

Recursive descent parser producing typed AST.

Consumes token stream from Lexer and builds typed AST nodes. Produces immutable (frozen) dataclass nodes for thread-safety.

Architecture:

The parser uses a mixin-based design for separation of concerns:

  • TokenNavigationMixin: Token stream traversal
  • InlineParsingMixin: Inline content (emphasis, links, code spans)
  • BlockParsingMixin: Block-level content (paragraphs, lists, tables)

Thread Safety:

  • Parser produces immutable AST (frozen dataclasses)
  • Configuration is read from ContextVar (thread-local)
  • Safe to share AST across threads

Classes

Parser 14
Recursive descent parser for Markdown. Consumes tokens from Lexer and builds typed AST. A…

Recursive descent parser for Markdown.

Consumes tokens from Lexer and builds typed AST.

Architecture:
    Uses mixin inheritance to separate concerns while maintaining
    a single entry point. Each mixin handles one aspect of the grammar:
  • TokenNavigationMixin: Token stream access, advance, peek

  • InlineParsingMixin: Emphasis, links, code spans, etc.

  • BlockParsingMixin: Lists, tables, code blocks, directives, etc.

    Usage:

    >> parser = Parser("# Hello

    World")

    >> ast = parser.parse() >> ast[0]

    Heading(level=1, children=(Text(content='Hello'),), ...)
    

    Thread Safety:

    Parser instances are single-use and not thread-safe. Create one per
    
    parse operation. Configuration is read from ContextVar (thread-local).
    
    The resulting AST is immutable and thread-safe.
    

    Configuration:

    Parser reads configuration from ContextVar instead of instance attributes.
    
    This provides:
    
  • 50% smaller memory footprint (9 vs 18 slots)

  • Faster instantiation (no config copying)

  • Automatic config inheritance for sub-parsers

  • Thread-safe by design

Methods

parse 0 Sequence[Block]
Parse source into AST blocks. **Thread Safety:** Returns immutable AST (frozen…
def parse(self) -> Sequence[Block]

Parse source into AST blocks.

Thread Safety: Returns immutable AST (frozen dataclasses).

Returns
Sequence[Block] Sequence of Block nodes
Internal Methods 13
_config 0 ParseConfig
Get current parse configuration (cached for parse duration).
property
def _config(self) -> ParseConfig
Returns
ParseConfig
_tables_enabled 0 bool
Whether GFM table parsing is enabled.
property
def _tables_enabled(self) -> bool
Returns
bool
_strikethrough_enabled 0 bool
Whether ~~strikethrough~~ syntax is enabled.
property
def _strikethrough_enabled(self) -> bool
Returns
bool
_task_lists_enabled 0 bool
Whether - [ ] task list items are enabled.
property
def _task_lists_enabled(self) -> bool
Returns
bool
_footnotes_enabled 0 bool
Whether [^ref] footnote references are enabled.
property
def _footnotes_enabled(self) -> bool
Returns
bool
_math_enabled 0 bool
Whether $inline$ and $$block$$ math is enabled.
property
def _math_enabled(self) -> bool
Returns
bool
_autolinks_enabled 0 bool
Whether automatic URL linking is enabled.
property
def _autolinks_enabled(self) -> bool
Returns
bool
_directive_registry 0 DirectiveRegistry | None
Registry for directive handlers.
property
def _directive_registry(self) -> DirectiveRegistry | None
Returns
DirectiveRegistry | None
_strict_contracts 0 bool
Whether to raise errors on directive contract violations.
property
def _strict_contracts(self) -> bool
Returns
bool
_text_transformer 0 Callable[[str], str] | N…
Optional callback to transform plain text lines.
property
def _text_transformer(self) -> Callable[[str], str] | None
Returns
Callable[[str], str] | None
__init__ 2
Initialize parser with source text. Configuration is read from ContextVar, not…
def __init__(self, source: str, source_file: str | None = None) -> None

Initialize parser with source text.

Configuration is read from ContextVar, not passed as parameters. Use set_parse_config() or parse_config_context() before creating a Parser if you need non-default configuration.

Parameters
Name Type Description
source

Markdown source text

source_file

Optional source file path for error messages

Default:None
_reinit 2
Reinitialize parser for reuse (enables pooling). Resets all per-parse state wh…
def _reinit(self, source: str, source_file: str | None = None) -> None

Reinitialize parser for reuse (enables pooling).

Resets all per-parse state while keeping the instance allocated. This enables frameworks like Bengal to pool Parser instances and avoid allocation overhead for high-volume parsing.

Thread Safety: Parser instances are single-use per thread. Pooling is thread-local.

Parameters
Name Type Description
source

New Markdown source text

source_file

Optional source file path for error messages

Default:None
_parse_nested_content 3 tuple[Block, ...]
Parse nested content as blocks (for block quotes, list items). Creates a sub-p…
def _parse_nested_content(self, content: str, location: SourceLocation, *, allow_setext_headings: bool = True) -> tuple[Block, ...]

Parse nested content as blocks (for block quotes, list items).

Creates a sub-parser to handle nested block-level content. Configuration is automatically inherited via ContextVar—no copying needed!

Thread Safety: Sub-parser reads config from the same ContextVar as parent, ensuring consistent configuration without manual copying.

Parameters
Name Type Description
content

The markdown content to parse as blocks

location

Source location for error reporting

allow_setext_headings

If False, disable setext heading detection (used for blockquote content with lazy continuation lines)

Default:True
Returns
tuple[Block, ...] Tuple of Block nodes