simplify build time pending check
This commit is contained in:
parent
1ed65518e6
commit
062ad5b046
14
choice.go
14
choice.go
@ -139,12 +139,12 @@ func (p *choiceParser) parse(c *context) {
|
||||
return
|
||||
}
|
||||
|
||||
if c.pending(c.offset, p.id) {
|
||||
if c.results.pending(c.offset, p.id) {
|
||||
c.fail(c.offset)
|
||||
return
|
||||
}
|
||||
|
||||
c.markPending(c.offset, p.id)
|
||||
c.results.markPending(c.offset, p.id)
|
||||
from := c.offset
|
||||
to := c.offset
|
||||
|
||||
@ -180,13 +180,13 @@ func (p *choiceParser) parse(c *context) {
|
||||
|
||||
if match {
|
||||
c.success(to)
|
||||
c.unmarkPending(from, p.id)
|
||||
c.results.unmarkPending(from, p.id)
|
||||
return
|
||||
}
|
||||
|
||||
c.results.setNoMatch(from, p.id)
|
||||
c.fail(from)
|
||||
c.unmarkPending(from, p.id)
|
||||
c.results.unmarkPending(from, p.id)
|
||||
}
|
||||
|
||||
func (b *choiceBuilder) nodeName() string { return b.name }
|
||||
@ -204,11 +204,11 @@ func (b *choiceBuilder) build(c *context) ([]*Node, bool) {
|
||||
if parsed {
|
||||
c.results.dropMatchTo(c.offset, b.id, to)
|
||||
} else {
|
||||
if c.pending(c.offset, b.id) {
|
||||
if c.results.pending(c.offset, b.id) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
c.markPending(c.offset, b.id)
|
||||
c.results.markPending(c.offset, b.id)
|
||||
}
|
||||
|
||||
var option builder
|
||||
@ -221,7 +221,7 @@ func (b *choiceBuilder) build(c *context) ([]*Node, bool) {
|
||||
|
||||
n, _ := option.build(c)
|
||||
if !parsed {
|
||||
c.unmarkPending(from, b.id)
|
||||
c.results.unmarkPending(from, b.id)
|
||||
}
|
||||
|
||||
if b.commit&Alias != 0 {
|
||||
|
@ -14,7 +14,6 @@ type context struct {
|
||||
results *results
|
||||
tokens []rune
|
||||
matchLast bool
|
||||
isPending [][]int
|
||||
}
|
||||
|
||||
func newContext(r io.RuneReader) *context {
|
||||
@ -78,11 +77,6 @@ func (c *context) fromResults(id int) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// - try to move this to the parsers
|
||||
// - try to move more
|
||||
// - if doens't help performance, try move more from there to here
|
||||
|
||||
func (c *context) success(to int) {
|
||||
c.offset = to
|
||||
c.matchLast = true
|
||||
|
@ -66,33 +66,3 @@ func TestFailingRead(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestPendingWithinCap(t *testing.T) {
|
||||
c := newContext(bytes.NewBuffer(nil))
|
||||
|
||||
t.Run("parse", func(t *testing.T) {
|
||||
for i := 0; i < 16; i++ {
|
||||
c.markPending(0, i)
|
||||
}
|
||||
|
||||
for i := 0; i < 16; i++ {
|
||||
if !c.pending(0, i) {
|
||||
t.Error("failed to mark pending")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
c.resetPending()
|
||||
|
||||
t.Run("parse", func(t *testing.T) {
|
||||
for i := 0; i < 16; i++ {
|
||||
c.markPending(0, i)
|
||||
}
|
||||
|
||||
for i := 0; i < 16; i++ {
|
||||
if !c.pending(0, i) {
|
||||
t.Error("failed to mark build pending")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -2977,7 +2977,7 @@ func TestMMLFile(t *testing.T) {
|
||||
|
||||
s.Init()
|
||||
|
||||
f, err := os.Open("test.mml")
|
||||
f, err := os.Open("examples/test.mml")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
|
47
results.go
47
results.go
@ -1,8 +1,9 @@
|
||||
package treerack
|
||||
|
||||
type results struct {
|
||||
noMatch []*idSet
|
||||
match [][]int
|
||||
noMatch []*idSet
|
||||
match [][]int
|
||||
isPending [][]int
|
||||
}
|
||||
|
||||
func (r *results) ensureOffset(offset int) {
|
||||
@ -126,17 +127,17 @@ func (r *results) dropMatchTo(offset, id, to int) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *context) resetPending() {
|
||||
c.isPending = nil
|
||||
func (r *results) resetPending() {
|
||||
r.isPending = nil
|
||||
}
|
||||
|
||||
func (c *context) pending(offset, id int) bool {
|
||||
if len(c.isPending) <= id {
|
||||
func (r *results) pending(offset, id int) bool {
|
||||
if len(r.isPending) <= id {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := range c.isPending[id] {
|
||||
if c.isPending[id][i] == offset {
|
||||
for i := range r.isPending[id] {
|
||||
if r.isPending[id][i] == offset {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -144,32 +145,32 @@ func (c *context) pending(offset, id int) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *context) markPending(offset, id int) {
|
||||
if len(c.isPending) <= id {
|
||||
if cap(c.isPending) > id {
|
||||
c.isPending = c.isPending[:id+1]
|
||||
func (r *results) markPending(offset, id int) {
|
||||
if len(r.isPending) <= id {
|
||||
if cap(r.isPending) > id {
|
||||
r.isPending = r.isPending[:id+1]
|
||||
} else {
|
||||
c.isPending = c.isPending[:cap(c.isPending)]
|
||||
for i := cap(c.isPending); i <= id; i++ {
|
||||
c.isPending = append(c.isPending, nil)
|
||||
r.isPending = r.isPending[:cap(r.isPending)]
|
||||
for i := cap(r.isPending); i <= id; i++ {
|
||||
r.isPending = append(r.isPending, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i := range c.isPending[id] {
|
||||
if c.isPending[id][i] == -1 {
|
||||
c.isPending[id][i] = offset
|
||||
for i := range r.isPending[id] {
|
||||
if r.isPending[id][i] == -1 {
|
||||
r.isPending[id][i] = offset
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.isPending[id] = append(c.isPending[id], offset)
|
||||
r.isPending[id] = append(r.isPending[id], offset)
|
||||
}
|
||||
|
||||
func (c *context) unmarkPending(offset, id int) {
|
||||
for i := range c.isPending[id] {
|
||||
if c.isPending[id][i] == offset {
|
||||
c.isPending[id][i] = -1
|
||||
func (r *results) unmarkPending(offset, id int) {
|
||||
for i := range r.isPending[id] {
|
||||
if r.isPending[id][i] == offset {
|
||||
r.isPending[id][i] = -1
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -19,3 +19,33 @@ func TestResults(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestPendingWithinCap(t *testing.T) {
|
||||
r := &results{}
|
||||
|
||||
t.Run("parse", func(t *testing.T) {
|
||||
for i := 0; i < 16; i++ {
|
||||
r.markPending(0, i)
|
||||
}
|
||||
|
||||
for i := 0; i < 16; i++ {
|
||||
if !r.pending(0, i) {
|
||||
t.Error("failed to mark pending")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
r.resetPending()
|
||||
|
||||
t.Run("parse", func(t *testing.T) {
|
||||
for i := 0; i < 16; i++ {
|
||||
r.markPending(0, i)
|
||||
}
|
||||
|
||||
for i := 0; i < 16; i++ {
|
||||
if !r.pending(0, i) {
|
||||
t.Error("failed to mark build pending")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
17
sequence.go
17
sequence.go
@ -173,12 +173,12 @@ func (p *sequenceParser) nodeID() int { return p.id }
|
||||
|
||||
func (p *sequenceParser) parse(c *context) {
|
||||
if !p.allChars {
|
||||
if c.pending(c.offset, p.id) {
|
||||
if c.results.pending(c.offset, p.id) {
|
||||
c.fail(c.offset)
|
||||
return
|
||||
}
|
||||
|
||||
c.markPending(c.offset, p.id)
|
||||
c.results.markPending(c.offset, p.id)
|
||||
}
|
||||
|
||||
itemIndex := 0
|
||||
@ -192,9 +192,8 @@ func (p *sequenceParser) parse(c *context) {
|
||||
if !c.matchLast {
|
||||
if currentCount < p.ranges[itemIndex][0] {
|
||||
c.fail(from)
|
||||
|
||||
if !p.allChars {
|
||||
c.unmarkPending(from, p.id)
|
||||
c.results.unmarkPending(from, p.id)
|
||||
}
|
||||
|
||||
return
|
||||
@ -219,7 +218,7 @@ func (p *sequenceParser) parse(c *context) {
|
||||
}
|
||||
|
||||
for _, g := range p.generalizations {
|
||||
if c.pending(from, g) {
|
||||
if c.results.pending(from, g) {
|
||||
c.results.setMatch(from, g, to)
|
||||
}
|
||||
}
|
||||
@ -227,7 +226,7 @@ func (p *sequenceParser) parse(c *context) {
|
||||
c.results.setMatch(from, p.id, to)
|
||||
c.success(to)
|
||||
if !p.allChars {
|
||||
c.unmarkPending(from, p.id)
|
||||
c.results.unmarkPending(from, p.id)
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,11 +257,11 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) {
|
||||
} else if parsed {
|
||||
c.results.dropMatchTo(c.offset, b.id, to)
|
||||
} else {
|
||||
if c.pending(c.offset, b.id) {
|
||||
if c.results.pending(c.offset, b.id) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
c.markPending(c.offset, b.id)
|
||||
c.results.markPending(c.offset, b.id)
|
||||
}
|
||||
|
||||
var (
|
||||
@ -303,7 +302,7 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) {
|
||||
}
|
||||
|
||||
if !parsed {
|
||||
c.unmarkPending(from, b.id)
|
||||
c.results.unmarkPending(from, b.id)
|
||||
}
|
||||
|
||||
if b.commit&Alias != 0 {
|
||||
|
Loading…
Reference in New Issue
Block a user