Skip to content

Commit 37afd3e

Browse files
committed
text/template/parse: simplify Tree.pipeline
The pipeline parsing code was unnecessarily complex. It used a for loop with a trailing break, a complex switch, and up to seven levels of indentation. Instead, drop the loop in favor of a single named goto with a comment, and flatten out the complex switch to be easier to follow. Two lines of code are now duplicated, but they're simple and only three lines apart. While at it, move the pipe initialization further up to remove the need for three variables. Change-Id: I07b29de195f4000336219aadeadeacaaa4285c58 Reviewed-on: https://go-review.googlesource.com/c/145285 Reviewed-by: Rob Pike <[email protected]> Run-TryBot: Rob Pike <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 3f3142a commit 37afd3e

File tree

1 file changed

+32
-40
lines changed

1 file changed

+32
-40
lines changed

src/text/template/parse/parse.go

Lines changed: 32 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -380,52 +380,44 @@ func (t *Tree) action() (n Node) {
380380
// Pipeline:
381381
// declarations? command ('|' command)*
382382
func (t *Tree) pipeline(context string) (pipe *PipeNode) {
383-
decl := false
384-
var vars []*VariableNode
385383
token := t.peekNonSpace()
386-
pos := token.pos
384+
pipe = t.newPipeline(token.pos, token.line, nil)
387385
// Are there declarations or assignments?
388-
// TODO(mvdan): simplify the loop break/continue logic
389-
for {
390-
if v := t.peekNonSpace(); v.typ == itemVariable {
391-
t.next()
392-
// Since space is a token, we need 3-token look-ahead here in the worst case:
393-
// in "$x foo" we need to read "foo" (as opposed to ":=") to know that $x is an
394-
// argument variable rather than a declaration. So remember the token
395-
// adjacent to the variable so we can push it back if necessary.
396-
tokenAfterVariable := t.peek()
397-
next := t.peekNonSpace()
398-
switch {
399-
case next.typ == itemAssign, next.typ == itemDeclare,
400-
next.typ == itemChar && next.val == ",":
401-
t.nextNonSpace()
402-
variable := t.newVariable(v.pos, v.val)
403-
vars = append(vars, variable)
404-
t.vars = append(t.vars, v.val)
405-
if next.typ == itemDeclare {
406-
decl = true
407-
}
408-
if next.typ == itemChar && next.val == "," {
409-
if context == "range" && len(vars) < 2 {
410-
switch t.peekNonSpace().typ {
411-
case itemVariable, itemRightDelim, itemRightParen:
412-
continue
413-
default:
414-
t.errorf("range can only initialize variables")
415-
}
416-
}
417-
t.errorf("too many declarations in %s", context)
386+
decls:
387+
if v := t.peekNonSpace(); v.typ == itemVariable {
388+
t.next()
389+
// Since space is a token, we need 3-token look-ahead here in the worst case:
390+
// in "$x foo" we need to read "foo" (as opposed to ":=") to know that $x is an
391+
// argument variable rather than a declaration. So remember the token
392+
// adjacent to the variable so we can push it back if necessary.
393+
tokenAfterVariable := t.peek()
394+
next := t.peekNonSpace()
395+
switch {
396+
case next.typ == itemAssign, next.typ == itemDeclare:
397+
pipe.IsAssign = next.typ == itemAssign
398+
t.nextNonSpace()
399+
pipe.Decl = append(pipe.Decl, t.newVariable(v.pos, v.val))
400+
t.vars = append(t.vars, v.val)
401+
case next.typ == itemChar && next.val == ",":
402+
t.nextNonSpace()
403+
pipe.Decl = append(pipe.Decl, t.newVariable(v.pos, v.val))
404+
t.vars = append(t.vars, v.val)
405+
if context == "range" && len(pipe.Decl) < 2 {
406+
switch t.peekNonSpace().typ {
407+
case itemVariable, itemRightDelim, itemRightParen:
408+
// second initialized variable in a range pipeline
409+
goto decls
410+
default:
411+
t.errorf("range can only initialize variables")
418412
}
419-
case tokenAfterVariable.typ == itemSpace:
420-
t.backup3(v, tokenAfterVariable)
421-
default:
422-
t.backup2(v)
423413
}
414+
t.errorf("too many declarations in %s", context)
415+
case tokenAfterVariable.typ == itemSpace:
416+
t.backup3(v, tokenAfterVariable)
417+
default:
418+
t.backup2(v)
424419
}
425-
break
426420
}
427-
pipe = t.newPipeline(pos, token.line, vars)
428-
pipe.IsAssign = !decl
429421
for {
430422
switch token := t.nextNonSpace(); token.typ {
431423
case itemRightDelim, itemRightParen:

0 commit comments

Comments
 (0)