1
0
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:
Rob Pike 2011-07-06 11:02:53 +10:00
parent 4657d7d7db
commit 329990d525
2 changed files with 20 additions and 14 deletions

View File

@ -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
} }

View File

@ -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)