mirror of
https://github.com/golang/go
synced 2024-11-13 19:20:31 -07:00
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í <mvdan@mvdan.cc> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
parent
2524ed1994
commit
98fd66808f
@ -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.
|
||||
@ -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.
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -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)
|
||||
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user