]> Cypherpunks repositories - gostls13.git/commitdiff
text/template: simplify line tracking in the lexer
authorDaniel Martí <mvdan@mvdan.cc>
Thu, 30 Aug 2018 17:02:41 +0000 (11:02 -0600)
committerDaniel Martí <mvdan@mvdan.cc>
Wed, 5 Sep 2018 21:27:04 +0000 (21:27 +0000)
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>
src/text/template/parse/lex.go

index c0843af6ede95b4868ac0615a7144cee7b303487..94a676c579cb48c7b33b3dbba03dae80341ea632 100644 (file)
@@ -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