Skip to content

Commit

Permalink
text/template: simplify line tracking in the lexer
Browse files Browse the repository at this point in the history
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í <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
  • Loading branch information
mvdan committed Sep 5, 2018
1 parent 2524ed1 commit 98fd668
Showing 1 changed file with 9 additions and 13 deletions.
22 changes: 9 additions & 13 deletions src/text/template/parse/lex.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ type lexer struct {
items chan item // channel of scanned items
parenDepth int // nesting depth of ( ) exprs
line int // 1+number of newlines seen
startLine int // start line of this item
}

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

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

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

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

Expand Down Expand Up @@ -218,6 +216,7 @@ func lex(name, input, left, right string) *lexer {
rightDelim: right,
items: make(chan item),
line: 1,
startLine: 1,
}
go l.run()
return l
Expand Down Expand Up @@ -252,16 +251,17 @@ func lexText(l *lexer) stateFn {
}
l.pos -= trimLength
if l.pos > l.start {
l.line += strings.Count(l.input[l.start:l.pos], "\n")
l.emit(itemText)
}
l.pos += trimLength
l.ignore()
return lexLeftDelim
} else {
l.pos = Pos(len(l.input))
}
l.pos = Pos(len(l.input))
// Correctly reached EOF.
if l.pos > l.start {
l.line += strings.Count(l.input[l.start:l.pos], "\n")
l.emit(itemText)
}
l.emit(itemEOF)
Expand Down Expand Up @@ -609,14 +609,10 @@ Loop:

// lexRawQuote scans a raw quoted string.
func lexRawQuote(l *lexer) stateFn {
startLine := l.line
Loop:
for {
switch l.next() {
case eof:
// Restore line number to location of opening quote.
// We will error out so it's ok just to overwrite the field.
l.line = startLine
return l.errorf("unterminated raw quoted string")
case '`':
break Loop
Expand Down

0 comments on commit 98fd668

Please sign in to comment.