mirror of
https://github.com/golang/go
synced 2024-11-22 01:14:40 -07:00
exp/template: remove the need for a goroutine.
R=golang-dev, adg CC=golang-dev https://golang.org/cl/4626095
This commit is contained in:
parent
4657d7d7db
commit
329990d525
@ -113,6 +113,7 @@ type stateFn func(*lexer) stateFn
|
|||||||
type lexer struct {
|
type lexer struct {
|
||||||
name string // the name of the input; used only for error reports.
|
name string // the name of the input; used only for error reports.
|
||||||
input string // the string being scanned.
|
input string // the string being scanned.
|
||||||
|
state stateFn // the next lexing function to enter
|
||||||
pos int // current position in the input.
|
pos int // current position in the input.
|
||||||
start int // start position of this item.
|
start int // start position of this item.
|
||||||
width int // width of last rune read from input.
|
width int // width of last rune read from input.
|
||||||
@ -182,27 +183,27 @@ func (l *lexer) errorf(format string, args ...interface{}) stateFn {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// run lexes the input by executing state functions until nil.
|
|
||||||
func (l *lexer) run() {
|
|
||||||
for state := lexText; state != nil; {
|
|
||||||
state = state(l)
|
|
||||||
}
|
|
||||||
close(l.items)
|
|
||||||
}
|
|
||||||
|
|
||||||
// nextItem returns the next item from the input.
|
// nextItem returns the next item from the input.
|
||||||
func (l *lexer) nextItem() item {
|
func (l *lexer) nextItem() item {
|
||||||
return <-l.items
|
for {
|
||||||
|
select {
|
||||||
|
case item := <-l.items:
|
||||||
|
return item
|
||||||
|
default:
|
||||||
|
l.state = l.state(l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
panic("not reached")
|
||||||
}
|
}
|
||||||
|
|
||||||
// lex launches a new scanner and returns the channel of items.
|
// lex creates a new scanner for the input string.
|
||||||
func lex(name, input string) *lexer {
|
func lex(name, input string) *lexer {
|
||||||
l := &lexer{
|
l := &lexer{
|
||||||
name: name,
|
name: name,
|
||||||
input: input,
|
input: input,
|
||||||
items: make(chan item),
|
state: lexText,
|
||||||
|
items: make(chan item, 2), // Two items of buffering is sufficient for all state functions
|
||||||
}
|
}
|
||||||
go l.run()
|
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,14 +128,19 @@ var lexTests = []lexTest{
|
|||||||
// collect gathers the emitted items into a slice.
|
// collect gathers the emitted items into a slice.
|
||||||
func collect(t *lexTest) (items []item) {
|
func collect(t *lexTest) (items []item) {
|
||||||
l := lex(t.name, t.input)
|
l := lex(t.name, t.input)
|
||||||
for i := range l.items {
|
for {
|
||||||
items = append(items, i)
|
item := l.nextItem()
|
||||||
|
items = append(items, item)
|
||||||
|
if item.typ == itemEOF || item.typ == itemError {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLex(t *testing.T) {
|
func TestLex(t *testing.T) {
|
||||||
for _, test := range lexTests {
|
for _, test := range lexTests {
|
||||||
|
println(test.name)
|
||||||
items := collect(&test)
|
items := collect(&test)
|
||||||
if !reflect.DeepEqual(items, test.items) {
|
if !reflect.DeepEqual(items, test.items) {
|
||||||
t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items)
|
t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items)
|
||||||
|
Loading…
Reference in New Issue
Block a user