Module

parser.core

Core parser implementation for Kida.

Combines all parsing mixins into a unified Parser class that transforms a token stream into an immutable Kida AST (Template node).

Design:

The Parser uses mixin inheritance to separate concerns while maintaining a single entry point. Each mixin handles one aspect of the grammar:

  • TokenNavigationMixin: Token stream access, lookahead, expect/match
  • BlockParsingMixin: Template structure (block, extends, include, def)
  • StatementParsingMixin: Control flow (if, for, while), variables (set, let)
  • ExpressionParsingMixin: Expressions, operators, filters, tests

Block Stack:

Uses a stack-based approach for unified{% end %}syntax. When any block is opened, it's pushed onto the stack.{% end %}always closes the innermost open block, like Go templates.

Thread-Safety: Parser instances are single-use and not thread-safe. Create one parser per template compilation. The resulting AST is immutable and thread-safe.

Classes

Parser 9
Recursive descent parser transforming tokens into Kida AST. The Parser consumes a token stream and…

Recursive descent parser transforming tokens into Kida AST.

The Parser consumes a token stream and produces an immutable Template node representing the complete AST. All parsing state is instance-local, so parsers are single-use (create one per template).

Block Stack Architecture: Uses a stack to track open blocks, enabling Kida's unified{% end %} syntax. When{% end %}is encountered, it closes the innermost block:

    ```jinja
    {% if condition %}
        {% for item in items %}
            {{ item }}
        {% end %}  {# closes for #}
    {% end %}  {# closes if #}
    ```

The stack stores `(block_type, lineno, col)` tuples for error reporting.

Error Handling: Parse errors include source snippets with caret pointing to the error, plus contextual suggestions for common mistakes:

    ```
    ParseError: Unclosed 'for' block - missing closing tag
      --> template.html:3:0
       |
     3 | {% for item in items %}
       | ^
    Suggestion: Add '{% end %}' or '{% endfor %}' to close the block
    ```

Attributes

Name Type Description
_tokens

Sequence of Token objects from lexer

_pos

Current position in token stream

_name

Template name for error messages

_filename

Source file path for error messages

_source

Original source text for error context

_autoescape

Whether to auto-escape output expressions

_block_stack list[tuple[str, int, int]]

Stack of open blocks for{% end %}matching

Methods

parse 0 Template
Parse tokens into Template AST.
def parse(self) -> Template
Returns
Template
Internal Methods 1
__init__ 5
def __init__(self, tokens: Sequence[Token], name: str | None = None, filename: str | None = None, source: str | None = None, autoescape: bool = True)
Parameters
Name Type Description
tokens
name Default:None
filename Default:None
source Default:None
autoescape Default:True