tpl/internal: Sync go_templates

Closes #10411
This commit is contained in:
Bjørn Erik Pedersen
2022-11-14 19:13:09 +01:00
parent 58a98c7758
commit f6ab9553f4
34 changed files with 739 additions and 514 deletions

View File

@@ -210,7 +210,6 @@ func (t *Tree) recover(errp *error) {
panic(e)
}
if t != nil {
t.lex.drain()
t.stopParse()
}
*errp = e.(error)
@@ -224,8 +223,6 @@ func (t *Tree) startParse(funcs []map[string]any, lex *lexer, treeSet map[string
t.vars = []string{"$"}
t.funcs = funcs
t.treeSet = treeSet
lex.breakOK = !t.hasFunction("break")
lex.continueOK = !t.hasFunction("continue")
}
// stopParse terminates parsing.
@@ -243,8 +240,13 @@ func (t *Tree) stopParse() {
func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]any) (tree *Tree, err error) {
defer t.recover(&err)
t.ParseName = t.Name
emitComment := t.Mode&ParseComments != 0
t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim, emitComment), treeSet)
lexer := lex(t.Name, text, leftDelim, rightDelim)
lexer.options = lexOptions{
emitComment: t.Mode&ParseComments != 0,
breakOK: !t.hasFunction("break"),
continueOK: !t.hasFunction("continue"),
}
t.startParse(funcs, lexer, treeSet)
t.text = text
t.parse()
t.add()
@@ -341,7 +343,9 @@ func (t *Tree) parseDefinition() {
}
// itemList:
//
// textOrAction*
//
// Terminates at {{end}} or {{else}}, returned separately.
func (t *Tree) itemList() (list *ListNode, next Node) {
list = t.newList(t.peekNonSpace().pos)
@@ -358,6 +362,7 @@ func (t *Tree) itemList() (list *ListNode, next Node) {
}
// textOrAction:
//
// text | comment | action
func (t *Tree) textOrAction() Node {
switch token := t.nextNonSpace(); token.typ {
@@ -380,8 +385,10 @@ func (t *Tree) clearActionLine() {
}
// Action:
//
// control
// command ("|" command)*
//
// Left delim is past. Now get actions.
// First word could be a keyword such as range.
func (t *Tree) action() (n Node) {
@@ -412,7 +419,9 @@ func (t *Tree) action() (n Node) {
}
// Break:
//
// {{break}}
//
// Break keyword is past.
func (t *Tree) breakControl(pos Pos, line int) Node {
if token := t.nextNonSpace(); token.typ != itemRightDelim {
@@ -425,7 +434,9 @@ func (t *Tree) breakControl(pos Pos, line int) Node {
}
// Continue:
//
// {{continue}}
//
// Continue keyword is past.
func (t *Tree) continueControl(pos Pos, line int) Node {
if token := t.nextNonSpace(); token.typ != itemRightDelim {
@@ -438,6 +449,7 @@ func (t *Tree) continueControl(pos Pos, line int) Node {
}
// Pipeline:
//
// declarations? command ('|' command)*
func (t *Tree) pipeline(context string, end itemType) (pipe *PipeNode) {
token := t.peekNonSpace()
@@ -549,16 +561,20 @@ func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int
}
// If:
//
// {{if pipeline}} itemList {{end}}
// {{if pipeline}} itemList {{else}} itemList {{end}}
//
// If keyword is past.
func (t *Tree) ifControl() Node {
return t.newIf(t.parseControl(true, "if"))
}
// Range:
//
// {{range pipeline}} itemList {{end}}
// {{range pipeline}} itemList {{else}} itemList {{end}}
//
// Range keyword is past.
func (t *Tree) rangeControl() Node {
r := t.newRange(t.parseControl(false, "range"))
@@ -566,22 +582,28 @@ func (t *Tree) rangeControl() Node {
}
// With:
//
// {{with pipeline}} itemList {{end}}
// {{with pipeline}} itemList {{else}} itemList {{end}}
//
// If keyword is past.
func (t *Tree) withControl() Node {
return t.newWith(t.parseControl(false, "with"))
}
// End:
//
// {{end}}
//
// End keyword is past.
func (t *Tree) endControl() Node {
return t.newEnd(t.expect(itemRightDelim, "end").pos)
}
// Else:
//
// {{else}}
//
// Else keyword is past.
func (t *Tree) elseControl() Node {
// Special case for "else if".
@@ -595,7 +617,9 @@ func (t *Tree) elseControl() Node {
}
// Block:
//
// {{block stringValue pipeline}}
//
// Block keyword is past.
// The name must be something that can evaluate to a string.
// The pipeline is mandatory.
@@ -623,7 +647,9 @@ func (t *Tree) blockControl() Node {
}
// Template:
//
// {{template stringValue pipeline}}
//
// Template keyword is past. The name must be something that can evaluate
// to a string.
func (t *Tree) templateControl() Node {
@@ -654,7 +680,9 @@ func (t *Tree) parseTemplateName(token item, context string) (name string) {
}
// 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.
func (t *Tree) command() *CommandNode {
@@ -684,7 +712,9 @@ func (t *Tree) command() *CommandNode {
}
// 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.
@@ -718,12 +748,14 @@ func (t *Tree) operand() Node {
}
// 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.
func (t *Tree) term() Node {