Module

parser.statements

Statement parsing for Kida parser.

Provides mixin for parsing template statements (body, data, output, blocks).

Uses inline TYPE_CHECKING declarations for host attributes. See: plan/rfc-mixin-protocol-typing.md

Classes

StatementParsingMixin 15
Mixin for parsing template statements. Host attributes and cross-mixin dependencies are declared v…

Mixin for parsing template statements.

Host attributes and cross-mixin dependencies are declared via inline TYPE_CHECKING blocks.

Attributes

Name Type Description
_END_KEYWORDS frozenset[str]
_CONTINUATION_KEYWORDS frozenset[str]

Methods

Internal Methods 13
_parse_body 1 list[Node]
Parse template body until an end tag or EOF. Uses universal end detection: sto…
def _parse_body(self, stop_on_continuation: bool = False) -> list[Node]

Parse template body until an end tag or EOF.

Uses universal end detection: stops on ANY end keyword (end, endif, endfor, enddef, etc.) or continuation keyword (else, elif, empty) if stop_on_continuation is True.

This enables the unified {% end %} syntax where {% end %} always closes the innermost open block.

Parameters
Name Type Description
stop_on_continuation

If True, also stop on else/elif/empty keywords. Used by if/for blocks that have continuation clauses.

Default:False
Returns
list[Node] List of parsed nodes.
_parse_data 0 Data
Parse raw text data.
def _parse_data(self) -> Data
Returns
Data
_parse_output 0 Output
Parse {{ expression }}.
def _parse_output(self) -> Output
Returns
Output
_parse_block 0 Node | list[Node] | None
Parse {% ... %} block tag.
def _parse_block(self) -> Node | list[Node] | None
Returns
Node | list[Node] | None - Single Node for most blocks - list[Node] for multi-set ({% set a = 1, b = 2 %}) - None for end tags
_parse_block_content 0 Node | list[Node] | None
Parse block content after BLOCK_BEGIN is consumed. This is split from _parse_b…
def _parse_block_content(self) -> Node | list[Node] | None

Parse block content after BLOCK_BEGIN is consumed.

This is split from _parse_block so it can be reused in contexts where BLOCK_BEGIN is already consumed (e.g., inside function bodies).

Uses dispatch table pattern for O(1) keyword lookup instead of 20+ elif branches. See RFC: rfc-code-smell-remediation.md §1.1

Returns
Node | list[Node] | None - Single Node for most blocks - list[Node] for multi-set ({% set a = 1, b = 2 %}) - None for end tags
_handle_end_keyword 1
Handle end keywords (endif, endfor, end, etc.).
def _handle_end_keyword(self, keyword: str) -> None
Parameters
Name Type Description
keyword

The end keyword being processed

Returns
None None for valid end tags (signals parent to close block)
_skip_comment 0
Skip comment block.
def _skip_comment(self) -> None
_get_eof_error_suggestion 1 str
Generate improved error suggestion for EOF errors in blocks. Checks for unclos…
def _get_eof_error_suggestion(self, block_type: str) -> str

Generate improved error suggestion for EOF errors in blocks.

Checks for unclosed comments and provides helpful suggestions.

Parameters
Name Type Description
block_type
Returns
str
_check_unclosed_comment 0 tuple[int, int] | None
Check for unclosed comment in the source. Scans the source for {# without matc…
def _check_unclosed_comment(self) -> tuple[int, int] | None

Check for unclosed comment in the source.

Scans the source for {# without matching #}. Returns (line, col) of unclosed comment start if found, None otherwise.

Returns
tuple[int, int] | None
_parse_tuple_or_name 0 Expr
Parse assignment target (variable or tuple for unpacking). Used by set/let/exp…
def _parse_tuple_or_name(self) -> Expr

Parse assignment target (variable or tuple for unpacking).

Used by set/let/export for patterns like:

  • x (single variable)
  • a, b (comma-separated before '=')
  • (a, b) (parenthesized tuple)
  • (a, b), c (nested/mixed)
Returns
Expr
_parse_tuple_or_expression 0 Expr
Parse expression that may be an implicit tuple. Used for value side of set sta…
def _parse_tuple_or_expression(self) -> Expr

Parse expression that may be an implicit tuple.

Used for value side of set statements like:

{% set a, b = 1, 2 %}

The value1, 2is parsed as a tuple without parentheses.

Returns
Expr
_parse_tuple_or_null_coalesce_no_ternary 0 Expr
Parse null coalescing that may be an implicit tuple, without ternary. Used for…
def _parse_tuple_or_null_coalesce_no_ternary(self) -> Expr

Parse null coalescing that may be an implicit tuple, without ternary.

Used for match subject and case patterns to allow:

{% match a, b %}
{% case 1, 2 %}

while preserving the ability to use 'if' as a guard clause: {% case 1 if x %} <- 'if' is a guard, not a ternary conditional

Returns
Expr
_parse_for_target 0 Expr
Parse for loop target (variable or tuple for unpacking). Handles: - item (…
def _parse_for_target(self) -> Expr

Parse for loop target (variable or tuple for unpacking).

Handles:

  • item (single variable)
  • (a, b) (parenthesized tuple)
  • a, b, c (comma-separated names before 'in')
Returns
Expr