Skip to content

Commit 98fd668

Browse files
committed
text/template: simplify line tracking in the lexer
First, move the strings.Count logic out of emit, since only itemText requires that. Use it in those call sites. itemLeftDelim and itemRightDelim cannot contain newlines, as they're the "{{" and "}}" tokens. Secondly, introduce a startLine lexer field so that we don't have to keep track of it elsewhere. That's also a requirement to move the strings.Count out of emit, as emit modifies the start position field. Change-Id: I69175f403487607a8e5b561b3f1916ee9dc3c0c6 Reviewed-on: https://go-review.googlesource.com/132275 Run-TryBot: Daniel Martí <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Rob Pike <[email protected]>
1 parent 2524ed1 commit 98fd668

File tree

1 file changed

+9
-13
lines changed

1 file changed

+9
-13
lines changed

src/text/template/parse/lex.go

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ type lexer struct {
117117
items chan item // channel of scanned items
118118
parenDepth int // nesting depth of ( ) exprs
119119
line int // 1+number of newlines seen
120+
startLine int // start line of this item
120121
}
121122

122123
// next returns the next rune in the input.
@@ -152,19 +153,16 @@ func (l *lexer) backup() {
152153

153154
// emit passes an item back to the client.
154155
func (l *lexer) emit(t itemType) {
155-
l.items <- item{t, l.start, l.input[l.start:l.pos], l.line}
156-
// Some items contain text internally. If so, count their newlines.
157-
switch t {
158-
case itemText, itemLeftDelim, itemRightDelim:
159-
l.line += strings.Count(l.input[l.start:l.pos], "\n")
160-
}
156+
l.items <- item{t, l.start, l.input[l.start:l.pos], l.startLine}
161157
l.start = l.pos
158+
l.startLine = l.line
162159
}
163160

164161
// ignore skips over the pending input before this point.
165162
func (l *lexer) ignore() {
166163
l.line += strings.Count(l.input[l.start:l.pos], "\n")
167164
l.start = l.pos
165+
l.startLine = l.line
168166
}
169167

170168
// accept consumes the next rune if it's from the valid set.
@@ -186,7 +184,7 @@ func (l *lexer) acceptRun(valid string) {
186184
// errorf returns an error token and terminates the scan by passing
187185
// back a nil pointer that will be the next state, terminating l.nextItem.
188186
func (l *lexer) errorf(format string, args ...interface{}) stateFn {
189-
l.items <- item{itemError, l.start, fmt.Sprintf(format, args...), l.line}
187+
l.items <- item{itemError, l.start, fmt.Sprintf(format, args...), l.startLine}
190188
return nil
191189
}
192190

@@ -218,6 +216,7 @@ func lex(name, input, left, right string) *lexer {
218216
rightDelim: right,
219217
items: make(chan item),
220218
line: 1,
219+
startLine: 1,
221220
}
222221
go l.run()
223222
return l
@@ -252,16 +251,17 @@ func lexText(l *lexer) stateFn {
252251
}
253252
l.pos -= trimLength
254253
if l.pos > l.start {
254+
l.line += strings.Count(l.input[l.start:l.pos], "\n")
255255
l.emit(itemText)
256256
}
257257
l.pos += trimLength
258258
l.ignore()
259259
return lexLeftDelim
260-
} else {
261-
l.pos = Pos(len(l.input))
262260
}
261+
l.pos = Pos(len(l.input))
263262
// Correctly reached EOF.
264263
if l.pos > l.start {
264+
l.line += strings.Count(l.input[l.start:l.pos], "\n")
265265
l.emit(itemText)
266266
}
267267
l.emit(itemEOF)
@@ -609,14 +609,10 @@ Loop:
609609

610610
// lexRawQuote scans a raw quoted string.
611611
func lexRawQuote(l *lexer) stateFn {
612-
startLine := l.line
613612
Loop:
614613
for {
615614
switch l.next() {
616615
case eof:
617-
// Restore line number to location of opening quote.
618-
// We will error out so it's ok just to overwrite the field.
619-
l.line = startLine
620616
return l.errorf("unterminated raw quoted string")
621617
case '`':
622618
break Loop

0 commit comments

Comments
 (0)