mirror of
https://github.com/golang/go
synced 2024-11-21 15:44:44 -07:00
template: fix deadlock.
No need for lexInsideAction to loop. Fixes #2217. R=golang-dev, bradfitz CC=golang-dev https://golang.org/cl/4963054
This commit is contained in:
parent
5edeef214d
commit
2cf66c1d94
@ -278,53 +278,51 @@ func lexInsideAction(l *lexer) stateFn {
|
||||
// Either number, quoted string, or identifier.
|
||||
// Spaces separate and are ignored.
|
||||
// Pipe symbols separate and are emitted.
|
||||
for {
|
||||
if strings.HasPrefix(l.input[l.pos:], rightDelim) {
|
||||
return lexRightDelim
|
||||
}
|
||||
switch r := l.next(); {
|
||||
case r == eof || r == '\n':
|
||||
return l.errorf("unclosed action")
|
||||
case isSpace(r):
|
||||
l.ignore()
|
||||
case r == ':':
|
||||
if l.next() != '=' {
|
||||
return l.errorf("expected :=")
|
||||
}
|
||||
l.emit(itemColonEquals)
|
||||
case r == '|':
|
||||
l.emit(itemPipe)
|
||||
case r == '"':
|
||||
return lexQuote
|
||||
case r == '`':
|
||||
return lexRawQuote
|
||||
case r == '$':
|
||||
return lexIdentifier
|
||||
case r == '\'':
|
||||
return lexChar
|
||||
case r == '.':
|
||||
// special look-ahead for ".field" so we don't break l.backup().
|
||||
if l.pos < len(l.input) {
|
||||
r := l.input[l.pos]
|
||||
if r < '0' || '9' < r {
|
||||
return lexIdentifier // itemDot comes from the keyword table.
|
||||
}
|
||||
}
|
||||
fallthrough // '.' can start a number.
|
||||
case r == '+' || r == '-' || ('0' <= r && r <= '9'):
|
||||
l.backup()
|
||||
return lexNumber
|
||||
case isAlphaNumeric(r):
|
||||
l.backup()
|
||||
return lexIdentifier
|
||||
case r <= unicode.MaxASCII && unicode.IsPrint(r):
|
||||
l.emit(itemChar)
|
||||
return lexInsideAction
|
||||
default:
|
||||
return l.errorf("unrecognized character in action: %#U", r)
|
||||
}
|
||||
if strings.HasPrefix(l.input[l.pos:], rightDelim) {
|
||||
return lexRightDelim
|
||||
}
|
||||
return nil
|
||||
switch r := l.next(); {
|
||||
case r == eof || r == '\n':
|
||||
return l.errorf("unclosed action")
|
||||
case isSpace(r):
|
||||
l.ignore()
|
||||
case r == ':':
|
||||
if l.next() != '=' {
|
||||
return l.errorf("expected :=")
|
||||
}
|
||||
l.emit(itemColonEquals)
|
||||
case r == '|':
|
||||
l.emit(itemPipe)
|
||||
case r == '"':
|
||||
return lexQuote
|
||||
case r == '`':
|
||||
return lexRawQuote
|
||||
case r == '$':
|
||||
return lexIdentifier
|
||||
case r == '\'':
|
||||
return lexChar
|
||||
case r == '.':
|
||||
// special look-ahead for ".field" so we don't break l.backup().
|
||||
if l.pos < len(l.input) {
|
||||
r := l.input[l.pos]
|
||||
if r < '0' || '9' < r {
|
||||
return lexIdentifier // itemDot comes from the keyword table.
|
||||
}
|
||||
}
|
||||
fallthrough // '.' can start a number.
|
||||
case r == '+' || r == '-' || ('0' <= r && r <= '9'):
|
||||
l.backup()
|
||||
return lexNumber
|
||||
case isAlphaNumeric(r):
|
||||
l.backup()
|
||||
return lexIdentifier
|
||||
case r <= unicode.MaxASCII && unicode.IsPrint(r):
|
||||
l.emit(itemChar)
|
||||
return lexInsideAction
|
||||
default:
|
||||
return l.errorf("unrecognized character in action: %#U", r)
|
||||
}
|
||||
return lexInsideAction
|
||||
}
|
||||
|
||||
// lexIdentifier scans an alphanumeric or field.
|
||||
|
@ -184,6 +184,20 @@ var lexTests = []lexTest{
|
||||
tLeft,
|
||||
{itemError, `bad number syntax: "3k"`},
|
||||
}},
|
||||
|
||||
// Fixed bugs
|
||||
// Many elements in an action blew the lookahead until
|
||||
// we made lexInsideAction not loop.
|
||||
{"long pipeline deadlock", "{{|||||}}", []item{
|
||||
tLeft,
|
||||
tPipe,
|
||||
tPipe,
|
||||
tPipe,
|
||||
tPipe,
|
||||
tPipe,
|
||||
tRight,
|
||||
tEOF,
|
||||
}},
|
||||
}
|
||||
|
||||
// collect gathers the emitted items into a slice.
|
||||
|
Loading…
Reference in New Issue
Block a user