Documentation
¶
Index ¶
- func HasRef(segs []TextSegment) bool
- func IsFlexBlock(toks []RefNode) bool
- func IsFmtBlock(toks []RefNode) bool
- func IsPureReference(tree []RefNode) bool
- func IsPureSegs(segs []TextSegment) bool
- func IsPureTextSegs(segs []TextSegment) bool
- type FlexBlock
- type FlexVarRef
- type FmtBlock
- type RefNode
- type TextSegment
- type TokenType
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func HasRef ¶
func HasRef(segs []TextSegment) bool
HasRef returns true if any segment is a reference.
func IsFlexBlock ¶
IsFlexBlock reports whether the token slice begins with a flexion sigil (`%`, `@`, `~`, or `#N`), meaning ParseFlexBlock should be used instead of ParseReference. A lone `%var` (with optional path) is NOT a FlexBlock — it is a FmtBlock (see IsFmtBlock), routed to FmtPrinter for locale-aware formatting.
func IsFmtBlock ¶
IsFmtBlock reports whether toks is a lone %var with an optional path tail and optional :formatName suffix, and nothing else. Malformed path tails (e.g. trailing `.`) return false so the caller surfaces the error via ParseFmtBlock.
func IsPureReference ¶
IsPureReference returns true if the tree contains no literals (str/num/txt), i.e., it is a pure path of identifiers/expr (useful for two-way binding).
func IsPureSegs ¶
func IsPureSegs(segs []TextSegment) bool
IsPureSegs returns true if there is exactly one IsRef segment with a pure reference.
func IsPureTextSegs ¶
func IsPureTextSegs(segs []TextSegment) bool
IsPureTextSegs returns true if all segments are literals (no references).
Types ¶
type FlexBlock ¶
type FlexBlock struct {
GenderVar string // @var root ident, "" when absent (degenerate-gender block)
GenderPath []RefNode // full @-path (root ident + optional .ident/[expr] tail); nil when @var absent or bare
CountVar string // %var root ident, "" when absent (pure-gender block)
CountPath []RefNode // full %-path; nil when %var absent or bare
Idx int // #N rule index, -1 when absent (pre-gen_i18n form)
TildeWords []string // ~word lemmas in original order (build-time only)
Tokens []RefNode // input token sequence in original order; path-tail tokens consumed
// by @var/%var are NOT re-emitted here (they are metadata attached to the
// sigil RefNode that precedes them). For *var/$var/~$var the path tail is
// stored in the token's Sub field, so Tokens carries enough for runtime
// assembly in order.
StarVars []FlexVarRef // *var participants (CustomFlex engine/selector), in order
DollarVars []FlexVarRef // $var plain dynamic binds (emitted verbatim), in order
FlexBinds []FlexVarRef // ~$var dynamic values to be inflected at runtime, in order
DefName string // =name: names this block's message for reuse, "" when absent
RefName string // #name: reuse — render the message named here, "" when absent
}
FlexBlock holds the resolved pieces of an i18n flexion reference such as `{{@genero %qt #42}}` or `{{@genero %qt ~o ~aluno ...}}`.
At runtime the rewritten form `{{@var %var #N}}` is what reaches the browser. Build-time (`gen_i18n`) also sees the `~word` form, so TildeWords is populated only when parsing the pre-rewrite template.
Tokens preserves the full input token sequence in original order so that build-time dict-consult can re-interleave passthrough words (non-sigil tokens that appear between ~words, e.g., "do terceiro ano que" in "{{@s %q ~o ~aluno do terceiro ano que ~está ~aprovado}}") with the flexed forms pulled from the dictionary.
func ParseFlexBlock ¶
ParseFlexBlock consumes a flat sequence of flexion tokens and returns the composed FlexBlock. Enforces the unicity rules locked in the design:
- at most one %var per block (hard error on second)
- at most one @var per block (hard error on second)
- at most one #N per block (hard error on second)
~word tokens are collected in order; repetitions are allowed since adjectives/verbs can legitimately repeat a lemma. Identifier/number/string tokens that appear between sigils are accepted as passthrough words (see the FlexBlock doc for the "do terceiro ano" example). Structural tokens (`.`, `[`, `]`, sub-expressions) are an error — a flex block cannot mix sigil syntax with path-reference syntax.
type FlexVarRef ¶ added in v0.15.0
FlexVarRef is a resolved variable reference inside a flex block for one of the path-bearing sigils (*var, $var, ~$var). Var is the root identifier; Path is the full reference (root ident + `.field`/`[expr]` tail), nil when the reference is a bare name. Resolution at runtime goes through wings.Solve when Path is non-nil, or the cheap single-level lookup for bare Var.
type FmtBlock ¶
type FmtBlock struct {
Var string // %var root ident
Path []RefNode // full path (root ident + tail); nil when bare
FormatName string // name after ':' (e.g. "km" in %dist:km); "" when absent
}
FmtBlock holds the resolved pieces of a locale-aware formatting reference such as `{{%preco}}`, `{{%cart[i].total}}`, or `{{%dist:km}}`. The value is resolved at sync time from the data context and rendered by wings.FmtPrinter, which chooses the output format from the Go type of the value, the current locale, and the optional format name.
A FmtBlock is the lone-%var form, with an optional `:formatName` suffix. When %var co-occurs with @var/~word/#N (or passthrough literals) inside the same {{...}} block, it is a FlexBlock count axis instead — routed to SynPrinter.
func ParseFmtBlock ¶
ParseFmtBlock consumes a lone-%var FmtBlock token sequence, including an optional :formatName suffix. Caller should gate on IsFmtBlock first; ParseFmtBlock returns an error on any mismatch so FlexBlocks mis-routed here surface loudly rather than silently.
type RefNode ¶
type RefNode struct {
Type TokenType
StrVal string
IntVal int
Sub []RefNode // populated only when Type == TokExpr
}
RefNode is a node in the parsed reference tree. For TokExpr, Sub contains the sub-expression (e.g. the index in arr[expr]).
func ParseReference ¶
ParseReference builds the reference tree from a list of tokens. Consumes tokens from the beginning of the slice pointed to by toks.
func Tokenize ¶
Tokenize converts a reference expression into a list of RefNodes. First extracts string literals, then tokenizes the remaining fragments.
func TokenizeFlexContent ¶ added in v0.15.0
TokenizeFlexContent tokenizes a flex block authored as inline content: a run of literal text interleaved with flex sigils. Unlike Tokenize (which discards whitespace, treating the block as a reference expression), this preserves the authored text faithfully, following HTML text-node semantics:
- a whitespace run (\s+: spaces, tabs, newlines) collapses to a single TokSpace token (the browser collapses it anyway in a text node);
- a run of non-whitespace, non-sigil characters becomes one TokTxt token, preserving punctuation and non-ASCII (e.g. Japanese) verbatim;
- a sigil ($var, ~$var, ~word, @var, %var, *var, #N) becomes its token; path-bearing sigils ($/*/~$/@/%) carry their `.field`/`[expr]` tail in Sub. `$$`/`**`/`~~`/`%%`/`@@` are escapes → literal text.
A sigil character that does not form a valid sigil (e.g. a lone `$` before a digit, as in a price "US$ 5") is treated as literal text. This is the tokenizer for the per-locale content phrase of a programmable flex rule; the legacy `{{@g %c ~word}}` path keeps using Tokenize + ParseFlexBlock.
type TextSegment ¶
type TextSegment struct {
IsRef bool
Lit string // if !IsRef: literal text
Ref []RefNode // if IsRef: parsed reference tree
}
TextSegment is a template text segment: literal or reference.
func ParseText ¶
func ParseText(s string) ([]TextSegment, error)
ParseText splits a template string into literal segments and references. References are delimited by {{ and }}. Each reference is immediately tokenized and parsed into a RefNode tree.
type TokenType ¶
type TokenType int8
TokenType represents the type of a token in the template parser.
const ( TokTxt TokenType = 0 // literal text TokRef TokenType = 1 // reference {{ }} TokStr TokenType = 2 // string literal in quotes TokDot TokenType = 3 // operator . TokOpen TokenType = 4 // operator [ TokClose TokenType = 5 // operator ] TokNum TokenType = 6 // integer number TokIdent TokenType = 7 // identifier TokWSep TokenType = 8 // internal state: waiting for separator TokExpr TokenType = 9 // sub-expression (dynamic index access) TokAttr TokenType = 10 // attribute node (DOMRefNode type) TokPctVar TokenType = 11 // %ident — count variable + emission TokAtVar TokenType = 12 // @ident — gender variable, no emission TokTildeWord TokenType = 13 // ~ident — flex marker (build-time only) TokFlexIdx TokenType = 14 // #N — inflection rule index TokColon TokenType = 15 // : — format-name separator in %var:name TokStarVar TokenType = 16 // *ident — CustomFlex object (engine/selector) TokDollarVar TokenType = 17 // $ident — dynamic bind value, emitted verbatim TokFlexBind TokenType = 18 // ~$ident — dynamic value to be inflected at runtime TokSpace TokenType = 19 // collapsed whitespace run (\s+ → one space) in flex content TokDefName TokenType = 20 // =ident — names this block's message for reuse TokFlexName TokenType = 21 // #ident — reuse: render the message named by ident )
Token types produced by the expression lexer.