Involved Source Fileslex.gonode.go
Package parse builds parse trees for templates as defined by text/template
and html/template. Clients should use those packages to construct templates
rather than this one, which provides shared internal data structures not
intended for general use.
Package-Level Type Names (total 31, in which 25 are exported)
/* sort exporteds by: | */
ActionNode holds an action (something bounded by delimiters).
Control actions have their own nodes; ActionNode represents simple
ones such as field evaluations and parenthesized pipelines.
// The line number in the input. Deprecated: Kept for compatibility.
NodeTypeNodeType
// The pipeline in the action.
PosPostr*Tree(*T) Copy() Node( T) Position() Pos(*T) String() string
Type returns itself and provides an easy default implementation
for embedding in a Node. Embedded in all non-trivial Nodes.
(*T) tree() *Tree(*T) writeTo(sb *strings.Builder)
*T : Node
*T : fmt.Stringer
*T : context.stringer
*T : os/signal.stringer
*T : runtime.stringer
func (*Tree).newAction(pos Pos, line int, pipe *PipeNode) *ActionNode
BranchNode is the common representation of if, range, and with.
// What to execute if the value is empty (nil if absent).
// The line number in the input. Deprecated: Kept for compatibility.
// What to execute if the value is non-empty.
NodeTypeNodeType
// The pipeline to be evaluated.
PosPostr*Tree(*T) Copy() Node( T) Position() Pos(*T) String() string
Type returns itself and provides an easy default implementation
for embedding in a Node. Embedded in all non-trivial Nodes.
(*T) tree() *Tree(*T) writeTo(sb *strings.Builder)
*T : Node
*T : fmt.Stringer
*T : context.stringer
*T : os/signal.stringer
*T : runtime.stringer
ChainNode holds a term followed by a chain of field accesses (identifier starting with '.').
The names may be chained ('.x.y').
The periods are dropped from each ident.
// The identifiers in lexical order.
NodeNodeNodeTypeNodeTypePosPostr*Tree
Add adds the named field (which should start with a period) to the end of the chain.
(*T) Copy() Node( T) Position() Pos(*T) String() string
Type returns itself and provides an easy default implementation
for embedding in a Node. Embedded in all non-trivial Nodes.
(*T) tree() *Tree(*T) writeTo(sb *strings.Builder)
*T : Node
*T : fmt.Stringer
*T : context.stringer
*T : os/signal.stringer
*T : runtime.stringer
func (*Tree).newChain(pos Pos, node Node) *ChainNode
CommandNode holds a command (a pipeline inside an evaluating action).
// Arguments in lexical order: Identifier, field, or constant.
NodeTypeNodeTypePosPostr*Tree(*T) Copy() Node( T) Position() Pos(*T) String() string
Type returns itself and provides an easy default implementation
for embedding in a Node. Embedded in all non-trivial Nodes.
(*T) append(arg Node)(*T) tree() *Tree(*T) writeTo(sb *strings.Builder)
*T : Node
*T : fmt.Stringer
*T : context.stringer
*T : os/signal.stringer
*T : runtime.stringer
func (*Tree).command() *CommandNode
func (*Tree).newCommand(pos Pos) *CommandNode
func html/template.appendCmd(cmds []*CommandNode, cmd *CommandNode) []*CommandNode
func html/template.newIdentCmd(identifier string, pos Pos) *CommandNode
func (*PipeNode).append(command *CommandNode)
func html/template.appendCmd(cmds []*CommandNode, cmd *CommandNode) []*CommandNode
func html/template.appendCmd(cmds []*CommandNode, cmd *CommandNode) []*CommandNode
FieldNode holds a field (identifier starting with '.').
The names may be chained ('.x.y').
The period is dropped from each ident.
// Variable name and fields in lexical order.
NodeTypeNodeTypePosPostr*Tree(*T) Copy() Node( T) Position() Pos(*T) String() string
Type returns itself and provides an easy default implementation
for embedding in a Node. Embedded in all non-trivial Nodes.
(*T) tree() *Tree(*T) writeTo(sb *strings.Builder)
*T : Node
*T : fmt.Stringer
*T : context.stringer
*T : os/signal.stringer
*T : runtime.stringer
func (*Tree).newField(pos Pos, ident string) *FieldNode
IdentifierNode holds an identifier.
// The identifier's name.
NodeTypeNodeTypePosPostr*Tree(*T) Copy() Node( T) Position() Pos
SetPos sets the position. NewIdentifier is a public method so we can't modify its signature.
Chained for convenience.
TODO: fix one day?
SetTree sets the parent tree for the node. NewIdentifier is a public method so we can't modify its signature.
Chained for convenience.
TODO: fix one day?
(*T) String() string
Type returns itself and provides an easy default implementation
for embedding in a Node. Embedded in all non-trivial Nodes.
(*T) tree() *Tree(*T) writeTo(sb *strings.Builder)
*T : Node
*T : fmt.Stringer
*T : context.stringer
*T : os/signal.stringer
*T : runtime.stringer
func NewIdentifier(ident string) *IdentifierNode
func (*IdentifierNode).SetPos(pos Pos) *IdentifierNode
func (*IdentifierNode).SetTree(t *Tree) *IdentifierNode
NumberNode holds a number: signed or unsigned integer, float, or complex.
The value is parsed and stored under all the types that can represent the value.
This simulates in a small amount of code the behavior of Go's ideal constants.
// The complex value.
// The floating-point value.
// The signed integer value.
// Number is complex.
// Number has a floating-point value.
// Number has an integral value.
// Number has an unsigned integral value.
NodeTypeNodeTypePosPos
// The original textual representation from the input.
// The unsigned integer value.
tr*Tree(*T) Copy() Node( T) Position() Pos(*T) String() string
Type returns itself and provides an easy default implementation
for embedding in a Node. Embedded in all non-trivial Nodes.
simplifyComplex pulls out any other types that are represented by the complex number.
These all require that the imaginary part be zero.
(*T) tree() *Tree(*T) writeTo(sb *strings.Builder)
*T : Node
*T : fmt.Stringer
*T : context.stringer
*T : os/signal.stringer
*T : runtime.stringer
func (*Tree).newNumber(pos Pos, text string, typ itemType) (*NumberNode, error)
TemplateNode represents a {{template}} action.
// The line number in the input. Deprecated: Kept for compatibility.
// The name of the template (unquoted).
NodeTypeNodeType
// The command to evaluate as dot for the template.
PosPostr*Tree(*T) Copy() Node( T) Position() Pos(*T) String() string
Type returns itself and provides an easy default implementation
for embedding in a Node. Embedded in all non-trivial Nodes.
(*T) tree() *Tree(*T) writeTo(sb *strings.Builder)
*T : Node
*T : fmt.Stringer
*T : context.stringer
*T : os/signal.stringer
*T : runtime.stringer
func (*Tree).newTemplate(pos Pos, line int, name string, pipe *PipeNode) *TemplateNode
Tree is the representation of a single parsed template.
// parsing mode.
// name of the template represented by the tree.
// name of the top-level template during parsing, for error messages.
// top-level root of the tree.
// line of left delim starting action
Parsing only; cleared after parse.
lex*lexermodeModepeekCountint
// text parsed to create the template (or its parent)
// three-token lookahead for parser.
treeSetmap[string]*Tree
// variables defined at the moment.
Copy returns a copy of the Tree. Any parsing state is discarded.
ErrorContext returns a textual representation of the location of the node in the input text.
The receiver is only used when the node does not have a pointer to the tree inside,
which can occur in old code.
Parse parses the template definition string to construct a representation of
the template for execution. If either action delimiter string is empty, the
default ("{{" or "}}") is used. Embedded template definitions are added to
the treeSet map.
Action:
control
command ("|" command)*
Left delim is past. Now get actions.
First word could be a keyword such as range.
add adds tree to t.treeSet.
backup backs the input stream up one token.
backup2 backs the input stream up two tokens.
The zeroth token is already there.
backup3 backs the input stream up three tokens
The zeroth token is already there.
Block:
{{block stringValue pipeline}}
Block keyword is past.
The name must be something that can evaluate to a string.
The pipeline is mandatory.
(*T) checkPipeline(pipe *PipeNode, context string)(*T) clearActionLine()
command:
operand (space operand)*
space-separated arguments up to a pipeline character or right delimiter.
we consume the pipe character but leave the right delim to terminate the action.
Else:
{{else}}
Else keyword is past.
End:
{{end}}
End keyword is past.
error terminates processing.
errorf formats the error and terminates processing.
expect consumes the next token and guarantees it has the required type.
expectOneOf consumes the next token and guarantees it has one of the required types.
hasFunction reports if a function name exists in the Tree's maps.
If:
{{if pipeline}} itemList {{end}}
{{if pipeline}} itemList {{else}} itemList {{end}}
If keyword is past.
itemList:
textOrAction*
Terminates at {{end}} or {{else}}, returned separately.
(*T) newAction(pos Pos, line int, pipe *PipeNode) *ActionNode(*T) newBool(pos Pos, true bool) *BoolNode(*T) newChain(pos Pos, node Node) *ChainNode(*T) newCommand(pos Pos) *CommandNode(*T) newComment(pos Pos, text string) *CommentNode(*T) newDot(pos Pos) *DotNode(*T) newElse(pos Pos, line int) *elseNode(*T) newEnd(pos Pos) *endNode(*T) newField(pos Pos, ident string) *FieldNode(*T) newIf(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *IfNode(*T) newList(pos Pos) *ListNode(*T) newNil(pos Pos) *NilNode(*T) newNumber(pos Pos, text string, typ itemType) (*NumberNode, error)(*T) newPipeline(pos Pos, line int, vars []*VariableNode) *PipeNode(*T) newRange(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *RangeNode(*T) newString(pos Pos, orig, text string) *StringNode(*T) newTemplate(pos Pos, line int, name string, pipe *PipeNode) *TemplateNode(*T) newText(pos Pos, text string) *TextNode(*T) newVariable(pos Pos, ident string) *VariableNode(*T) newWith(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *WithNode
next returns the next token.
nextNonSpace returns the next non-space token.
operand:
term .Field*
An operand is a space-separated component of a command,
a term possibly followed by field accesses.
A nil return means the next item is not an operand.
parse is the top-level parser for a template, essentially the same
as itemList except it also parses {{define}} actions.
It runs to EOF.
(*T) parseControl(allowElseIf bool, context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode)
parseDefinition parses a {{define}} ... {{end}} template definition and
installs the definition in t.treeSet. The "define" keyword has already
been scanned.
(*T) parseTemplateName(token item, context string) (name string)
peek returns but does not consume the next token.
peekNonSpace returns but does not consume the next non-space token.
Pipeline:
declarations? command ('|' command)*
popVars trims the variable list to the specified length
Range:
{{range pipeline}} itemList {{end}}
{{range pipeline}} itemList {{else}} itemList {{end}}
Range keyword is past.
recover is the handler that turns panics into returns from the top level of Parse.
startParse initializes the parser, using the lexer.
stopParse terminates parsing.
Template:
{{template stringValue pipeline}}
Template keyword is past. The name must be something that can evaluate
to a string.
term:
literal (number, string, nil, boolean)
function (identifier)
.
.Field
$
'(' pipeline ')'
A term is a simple "expression".
A nil return means the next item is not a term.
textOrAction:
text | comment | action
unexpected complains about the token and terminates processing.
useVar returns a node for a variable reference. It errors if the
variable is not defined.
With:
{{with pipeline}} itemList {{end}}
{{with pipeline}} itemList {{else}} itemList {{end}}
If keyword is past.
func New(name string, funcs ...map[string]interface{}) *Tree
func Parse(name, text, leftDelim, rightDelim string, funcs ...map[string]interface{}) (map[string]*Tree, error)
func (*Tree).Copy() *Tree
func (*Tree).Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error)
func (*ActionNode).tree() *Tree
func (*BoolNode).tree() *Tree
func (*BranchNode).tree() *Tree
func (*ChainNode).tree() *Tree
func (*CommandNode).tree() *Tree
func (*CommentNode).tree() *Tree
func (*DotNode).tree() *Tree
func (*FieldNode).tree() *Tree
func (*IdentifierNode).tree() *Tree
func (*ListNode).tree() *Tree
func (*NilNode).tree() *Tree
func (*NumberNode).tree() *Tree
func (*PipeNode).tree() *Tree
func (*StringNode).tree() *Tree
func (*TemplateNode).tree() *Tree
func (*TextNode).tree() *Tree
func (*VariableNode).tree() *Tree
func (*IdentifierNode).SetTree(t *Tree) *IdentifierNode
func (*Tree).Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error)
func text/template.(*Template).AddParseTree(name string, tree *Tree) (*template.Template, error)
func html/template.(*Template).AddParseTree(name string, tree *Tree) (*template.Template, error)
func (*Tree).startParse(funcs []map[string]interface{}, lex *lexer, treeSet map[string]*Tree)
func text/template.(*Template).associate(new *template.Template, tree *Tree) bool
lexer holds the state of the scanner.
// emit itemComment tokens.
// the string being scanned
// channel of scanned items
// start of action
// 1+number of newlines seen
// the name of the input; used only for error reports
// nesting depth of ( ) exprs
// current position in the input
// end of action
// start position of this item
// start line of this item
// width of last rune read from input
accept consumes the next rune if it's from the valid set.
acceptRun consumes a run of runes from the valid set.
atRightDelim reports whether the lexer is at a right delimiter, possibly preceded by a trim marker.
atTerminator reports whether the input is at valid termination character to
appear after an identifier. Breaks .X.Y into two pieces. Also catches cases
like "$x+2" not being acceptable without a space, in case we decide one
day to implement arithmetic.
backup steps back one rune. Can only be called once per call of next.
drain drains the output so the lexing goroutine will exit.
Called by the parser, not in the lexing goroutine.
emit passes an item back to the client.
errorf returns an error token and terminates the scan by passing
back a nil pointer that will be the next state, terminating l.nextItem.
ignore skips over the pending input before this point.
next returns the next rune in the input.
nextItem returns the next item from the input.
Called by the parser, not in the lexing goroutine.
peek returns but does not consume the next rune in the input.
run runs the state machine for the lexer.
(*T) scanNumber() bool
func lex(name, input, left, right string, emitComment bool) *lexer
func lexChar(l *lexer) stateFn
func lexComment(l *lexer) stateFn
func lexField(l *lexer) stateFn
func lexFieldOrVariable(l *lexer, typ itemType) stateFn
func lexIdentifier(l *lexer) stateFn
func lexInsideAction(l *lexer) stateFn
func lexLeftDelim(l *lexer) stateFn
func lexNumber(l *lexer) stateFn
func lexQuote(l *lexer) stateFn
func lexRawQuote(l *lexer) stateFn
func lexRightDelim(l *lexer) stateFn
func lexSpace(l *lexer) stateFn
func lexText(l *lexer) stateFn
func lexVariable(l *lexer) stateFn
func (*Tree).startParse(funcs []map[string]interface{}, lex *lexer, treeSet map[string]*Tree)
Package-Level Functions (total 25, in which 4 are exported)
IsEmptyTree reports whether this tree (node) is empty of everything but space or comments.
New allocates a new parse tree with the given name.
NewIdentifier returns a new IdentifierNode with the given identifier name.
Parse returns a map from template name to parse.Tree, created by parsing the
templates described in the argument string. The top-level template will be
given the specified name. If an error is encountered, parsing stops and an
empty map is returned with the error.
isAlphaNumeric reports whether r is an alphabetic, digit, or underscore.
isSpace reports whether r is a space character.
leftTrimLength returns the length of the spaces at the beginning of the string.
lex creates a new scanner for the input string.
lexChar scans a character constant. The initial quote is already
scanned. Syntax checking is done by the parser.
lexComment scans a comment. The left comment marker is known to be present.
lexField scans a field: .Alphanumeric.
The . has been scanned.
lexVariable scans a field or variable: [.$]Alphanumeric.
The . or $ has been scanned.
lexIdentifier scans an alphanumeric.
lexInsideAction scans the elements inside action delimiters.
lexLeftDelim scans the left delimiter, which is known to be present, possibly with a trim marker.
lexNumber scans a number: decimal, octal, hex, float, or imaginary. This
isn't a perfect number scanner - for instance it accepts "." and "0x0.2"
and "089" - but when it's wrong the input is invalid and the parser (via
strconv) will notice.
lexQuote scans a quoted string.
lexRawQuote scans a raw quoted string.
lexRightDelim scans the right delimiter, which is known to be present, possibly with a trim marker.
lexSpace scans a run of space characters.
We have not consumed the first space, which is known to be present.
Take care if there is a trim-marked right delimiter, which starts with a space.
lexText scans until an opening action delimiter, "{{".
lexVariable scans a Variable: $Alphanumeric.
The $ has been scanned.
rightTrimLength returns the length of the spaces at the end of the string.
Package-Level Variables (total 2, neither is exported)
Trimming spaces.
If the action begins "{{- " rather than "{{", then all space/tab/newlines
preceding the action are trimmed; conversely if it ends " -}}" the
leading spaces are trimmed. This is done entirely in the lexer; the
parser never sees it happen. We require an ASCII space (' ', \t, \r, \n)
to be present to avoid ambiguity with things like "{{-3}}". It reads
better with the space present anyway. For simplicity, only ASCII
does the job.
Trimming spaces.
If the action begins "{{- " rather than "{{", then all space/tab/newlines
preceding the action are trimmed; conversely if it ends " -}}" the
leading spaces are trimmed. This is done entirely in the lexer; the
parser never sees it happen. We require an ASCII space (' ', \t, \r, \n)
to be present to avoid ambiguity with things like "{{-3}}". It reads
better with the space present anyway. For simplicity, only ASCII
does the job.
Trimming spaces.
If the action begins "{{- " rather than "{{", then all space/tab/newlines
preceding the action are trimmed; conversely if it ends " -}}" the
leading spaces are trimmed. This is done entirely in the lexer; the
parser never sees it happen. We require an ASCII space (' ', \t, \r, \n)
to be present to avoid ambiguity with things like "{{-3}}". It reads
better with the space present anyway. For simplicity, only ASCII
does the job.
The pages are generated with Goldsv0.3.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds.