///|
/// The tree both syntaxes read into. Nothing after reading knows which
/// syntax a template was written in.
pub(all) enum Expr {
Lit(@spec.Value)
Name(String)
List(Array[Expr])
Tuple(Array[Expr])
Dict(Array[(Expr, Expr)])
Attr(Expr, String)
Item(Expr, Expr)
/// A slice as a subscript: `a[1:2]` is `Item(a, Slice(1, 2, None))`.
Slice(Expr?, Expr?, Expr?)
Call(Expr, Array[Arg])
Not(Expr)
Neg(Expr)
Pos(Expr)
Binary(Op, Expr, Expr)
Compare(Expr, Array[(Op, Expr)])
Concat(Array[Expr])
Cond(Expr, Expr, Expr?)
Filter(Expr?, String, Array[Arg])
Test(Expr, String, Array[Arg])
/// The attributes of a mixin call, merged the way an element merges its
/// own: classes gather, `&attributes` splats override.
Attributes(Array[Attr], Array[Expr])
}
///|
pub(all) enum Op {
Add
Sub
Mul
Div
FloorDiv
Mod
Pow
And
Or
Eq
Ne
Lt
Gt
Le
Ge
In
NotIn
} derive(Eq)
///|
pub extend Op with Eq::{equal, not_equal}
///|
/// An argument: positional, named, or spread with `*` and `**`.
pub(all) enum Arg {
Pos(Expr)
Named(String, Expr)
Spread(Expr)
SpreadNamed(Expr)
}
///|
/// Where an assignment or a loop binds.
pub(all) enum Target {
Name(String)
Tuple(Array[Target])
Field(String, String)
}
///|
/// A macro or call-block parameter.
pub(all) struct Param {
name : String
default : Expr?
rest : Bool
}
///|
///|
/// A macro, or a mixin of the indentation syntax: a mixin also receives the
/// call's attributes as `attributes` and its block as `block`.
pub(all) struct Macro {
name : String
params : Array[Param]
body : Array[Node]
pug : Bool
}
///|
pub(all) enum Placement {
Replace
Append
Prepend
} derive(Eq)
///|
pub extend Placement with Eq::{equal, not_equal}
///|
pub(all) struct Block {
name : String
body : Array[Node]
scoped : Bool
required : Bool
placement : Placement
}
///|
/// A `{% trans %}`: message ids with `%(name)s` placeholders, the values
/// those names take, the plural count, and the message context.
pub(all) struct Trans {
context : String?
singular : String
plural : String?
vars : Array[(String, Expr)]
count : Expr?
}
///|
/// An attribute of an element in the indentation syntax. `None` is a bare
/// attribute such as `checked`.
pub(all) struct Attr {
name : String
value : Expr?
escape : Bool
}
///|
pub(all) struct Element {
tag : Expr
attrs : Array[Attr]
splats : Array[Expr]
self_close : Bool
body : Array[Node]
}
///|
pub(all) enum Node {
/// The line in the template where the following node starts.
Line(Int32)
Text(String)
Out(Expr)
/// Output never escaped: the indentation syntax's `!=` and `!{…}`.
Raw(Expr)
/// A loop. `each` is the indentation syntax's: with two names the value
/// binds first, then the index or key.
For(
target~ : Target,
iter~ : Expr,
cond~ : Expr?,
recursive~ : Bool,
each~ : Bool,
body~ : Array[Node],
otherwise~ : Array[Node]
)
If(Array[(Expr, Array[Node])], Array[Node])
Set(Target, Expr)
SetBlock(Target, Expr?, Array[Node])
MacroDef(Macro)
CallBlock(Array[Param], Expr, Array[Node])
FilterBlock(Expr, Array[Node])
Extends(Expr)
BlockDef(Block)
/// `raw` includes the text as it stands, as the indentation syntax does
/// for a file that is not a template. `inline` renders the file in place,
/// as the indentation syntax does: what it defines stays defined and its
/// blocks take part in inheritance. `block` is the indentation syntax's
/// body under an include, rendered where the included file says `yield`.
Include(
Expr,
missing~ : Bool,
context~ : Bool,
raw~ : Bool,
inline~ : Bool,
block~ : Array[Node]
)
/// Where an include's block goes.
Yield
Import(Expr, String, context~ : Bool)
FromImport(Expr, Array[(String, String?)], context~ : Bool)
With(Array[(Target, Expr)], Array[Node])
Autoescape(Expr, Array[Node])
Do(Expr)
Debug
Show(Expr, Array[Node])
Once(Expr?, Array[Node])
TransOut(Trans)
Break
Continue
Element(Element)
Doctype(String)
Comment(Array[Node])
Case(Expr, Array[(Array[Expr], Array[Node])], Array[Node])
}