@eryx/template/parser Module

JSON

Summary

Exported Class

cursor: number
line: number
source: string
filepath: string?
Parser.new(source: string, filepath: string?)Parser
Parser:cur(n: number?)string
Parser:tryConsume(match: string)boolean
Parser:consume(match: string)()
Parser:pos()(number, number)
Parser:consumeName()string
Parser:consumeUntil(match: { string })(AstSuite, AstNode)

API Reference

Exported Class

Parser

Properties

cursor: number
line: number
source: string
filepath: string?

Parser.new

Creates a new Parser for the given template source string.

Parser.new(source: string, filepath: string?)Parser

Parameters

source: string

The template source to parse.

filepath: string?

Optional file path of the template, used for resolving {% include %} paths.

Returns

A new parser instance.

Parser:cur

Parser:cur(n: number?)string

Parser:tryConsume

Parser:tryConsume(match: string)boolean

Parser:consume

Parser:consume(match: string)()

Parser:skipWhitespace

Parser:skipWhitespace()()

Parser:pos

Returns the (line, col) of the current cursor position by scanning from the start of the source string.

O(n) in the number of characters consumed so far. Only called when creating AST nodes or when an error is about to be raised, so the cost is negligible in practice.

Parser:pos()(number, number)

Parser:consumeName

Parser:consumeName()string

Parser:consumeExpr

Consumes an expression: either a numeric literal (integer or decimal) or a dotted identifier path (e.g. user.profile.name), optionally followed by one or more pipe-separated filter names.

Parser:consumeExpr()AstExpression

Returns

The parsed expression node.

Parser:consumeCondition

Consumes a full condition chain used in {% if %} / {% elseif %}.

Each link is an expression optionally compared to another via a relational operator (==, ~=, <, >, <=, >=), and links are joined by and or or.

Parser:consumeCondition(){ TCondition }

Returns

The parsed condition chain.

Parser:consumeStmt

Consumes a statement block opened by {%.

Dispatches to the appropriate handler based on the keyword: if, elseif, else, for, end, macro, use, slot, fill, or include.

Parser:consumeStmt()AstNode

Returns

The parsed statement node.

Parser:consumeComment

Consumes a comment block ({# ... #}).

Advances the cursor past the closing #} and returns nil (no AST node is produced).

Parser:consumeComment()nil

Parser:consumeUntil

Parses nodes until a node whose type is in match is encountered.

Returns the collected body nodes and the terminating node. Errors if EOF is reached before finding a match.

Parser:consumeUntil(match: { string })(AstSuite, AstNode)

Parameters

match: { string }

An array of node type strings to stop at.

Returns

The body nodes collected before the match.

The terminating node.

Parser:next

Produces the next AST node from the source.

Determines whether the next significant token is an expression ({{), statement ({%), comment ({#), or plain literal text, and delegates accordingly.

Parser:next()AstNode?

Returns

The next node, or nil for comments.

Types

TCondition

A single link in a condition chain.

lhs is always present; cond/rhs are present for comparisons; chain links to the next condition via "and" or "or".

cond: string?
chain: ("or" | "and")?

TemplateError

A structured error thrown by the parser and evaluator.

Contains the human-readable message and the source location (line, col) where the error occurred, plus the optional filepath of the template file that produced the error.

message: string
line: number
col: number
filepath: string?

AstEof

End-of-file sentinel.

type: "eof"
line: number
col: number
filepath: string?

AstLiteral

Raw text between template delimiters.

type: "literal"
value: string
line: number
col: number
filepath: string?

AstExpression

An interpolated expression: {{ value }} or {{ value | filter }}.

value is either an array of path segments (e.g. {"user", "name"}) for dotted variable access, a number literal, or a double-quoted string literal (with \n, \t, \r, \\, \" escapes).

type: "expression"
value: { string | { dyn: AstExpression } } | { group: { TCondition } } | number | string | boolean

Path values are arrays of segments: strings for .key access, or { dyn: AstExpression } tables for [expr] subscript access.

negate: boolean?
filters: { string }
line: number
col: number
filepath: string?

AstStatementEnd

Marks the end of a control-flow block ({% end %}).

type: "end"
line: number
col: number
filepath: string?

AstStatementElse

The fallback branch of an if/elseif chain ({% else %}).

type: "else"
body: AstSuite
line: number
col: number
filepath: string?

AstStatementElseIf

An {% elseif cond then %} branch, with its own condition and body.

type: "elseif"
conditionChain: { TCondition }
body: AstSuite
line: number
col: number
filepath: string?

AstStatementIf

The opening {% if cond then %} of a conditional chain.

type: "if"
conditionChain: { TCondition }
body: AstSuite
line: number
col: number
filepath: string?

AstStatementForTable

A key/value for-in loop: {% for k, v in expr do %}.

type: "forTable"
var1: string
var2: string
body: AstSuite
line: number
col: number
filepath: string?

AstStatementForNumber

A numeric for loop: {% for i = start, end do %}.

type: "forNumber"
var: string
body: AstSuite
line: number
col: number
filepath: string?

AstMacro

A macro definition: {% macro name(arg1, arg2) %} body {% end %}.

Declares a reusable template block. The macro is registered in the evaluation context and can be invoked via AstMacroCall.

type: "macro"
name: string
args: { string }
body: AstSuite
line: number
col: number
filepath: string?

AstMacroCall

A macro invocation: {% use name(expr, ...) %} body {% end %}.

Calls a previously defined macro. Positional arguments are evaluated and bound to the macro's parameter names. The body between {% use %} and {% end %} is rendered and made available to the macro as the "default" slot.

type: "macroCall"
name: string
args: { AstExpression }
body: AstSuite
line: number
col: number
filepath: string?

AstSlot

A slot placeholder inside a macro body: {% slot name %} default {% end %}.

When the macro is called, the slot is replaced by the caller's corresponding {% fill name %} content. If no fill is provided, the slot's own body is rendered as a default. The name "default" is reserved for the caller's top-level body.

type: "slot"
name: string
body: AstSuite
line: number
col: number
filepath: string?

AstSlotAssign

A slot fill inside a macro call: {% fill name %} content {% end %}.

Provides content for the named AstSlot in the invoked macro.

type: "slotAssign"
name: string
body: AstSuite
line: number
col: number
filepath: string?

AstIncluded

An inlined template file: {% include "path" %}.

At parse time the referenced file is read and recursively parsed. The resolved AST is stored in body. The path is resolved relative to the directory of the file currently being parsed.

type: "included"
path: string
body: AstSuite
passed: AstSuite
line: number
col: number
filepath: string?

AstSet

type: "set"
name: string

AstNode

Union of all possible AST node types the parser can produce.

AstSuite

type AstSuite = { AstNode }