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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.pending(c.offset, p.id) {
|
if c.results.pending(c.offset, p.id) {
|
||||||
c.fail(c.offset)
|
c.fail(c.offset)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.markPending(c.offset, p.id)
|
c.results.markPending(c.offset, p.id)
|
||||||
from := c.offset
|
from := c.offset
|
||||||
to := c.offset
|
to := c.offset
|
||||||
|
|
||||||
@ -180,13 +180,13 @@ func (p *choiceParser) parse(c *context) {
|
|||||||
|
|
||||||
if match {
|
if match {
|
||||||
c.success(to)
|
c.success(to)
|
||||||
c.unmarkPending(from, p.id)
|
c.results.unmarkPending(from, p.id)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.results.setNoMatch(from, p.id)
|
c.results.setNoMatch(from, p.id)
|
||||||
c.fail(from)
|
c.fail(from)
|
||||||
c.unmarkPending(from, p.id)
|
c.results.unmarkPending(from, p.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *choiceBuilder) nodeName() string { return b.name }
|
func (b *choiceBuilder) nodeName() string { return b.name }
|
||||||
@ -204,11 +204,11 @@ func (b *choiceBuilder) build(c *context) ([]*Node, bool) {
|
|||||||
if parsed {
|
if parsed {
|
||||||
c.results.dropMatchTo(c.offset, b.id, to)
|
c.results.dropMatchTo(c.offset, b.id, to)
|
||||||
} else {
|
} else {
|
||||||
if c.pending(c.offset, b.id) {
|
if c.results.pending(c.offset, b.id) {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
c.markPending(c.offset, b.id)
|
c.results.markPending(c.offset, b.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
var option builder
|
var option builder
|
||||||
@ -221,7 +221,7 @@ func (b *choiceBuilder) build(c *context) ([]*Node, bool) {
|
|||||||
|
|
||||||
n, _ := option.build(c)
|
n, _ := option.build(c)
|
||||||
if !parsed {
|
if !parsed {
|
||||||
c.unmarkPending(from, b.id)
|
c.results.unmarkPending(from, b.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.commit&Alias != 0 {
|
if b.commit&Alias != 0 {
|
||||||
|
@ -14,7 +14,6 @@ type context struct {
|
|||||||
results *results
|
results *results
|
||||||
tokens []rune
|
tokens []rune
|
||||||
matchLast bool
|
matchLast bool
|
||||||
isPending [][]int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newContext(r io.RuneReader) *context {
|
func newContext(r io.RuneReader) *context {
|
||||||
@ -78,11 +77,6 @@ func (c *context) fromResults(id int) bool {
|
|||||||
return true
|
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) {
|
func (c *context) success(to int) {
|
||||||
c.offset = to
|
c.offset = to
|
||||||
c.matchLast = true
|
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()
|
s.Init()
|
||||||
|
|
||||||
f, err := os.Open("test.mml")
|
f, err := os.Open("examples/test.mml")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
|
47
results.go
47
results.go
@ -1,8 +1,9 @@
|
|||||||
package treerack
|
package treerack
|
||||||
|
|
||||||
type results struct {
|
type results struct {
|
||||||
noMatch []*idSet
|
noMatch []*idSet
|
||||||
match [][]int
|
match [][]int
|
||||||
|
isPending [][]int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *results) ensureOffset(offset int) {
|
func (r *results) ensureOffset(offset int) {
|
||||||
@ -126,17 +127,17 @@ func (r *results) dropMatchTo(offset, id, to int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) resetPending() {
|
func (r *results) resetPending() {
|
||||||
c.isPending = nil
|
r.isPending = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) pending(offset, id int) bool {
|
func (r *results) pending(offset, id int) bool {
|
||||||
if len(c.isPending) <= id {
|
if len(r.isPending) <= id {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range c.isPending[id] {
|
for i := range r.isPending[id] {
|
||||||
if c.isPending[id][i] == offset {
|
if r.isPending[id][i] == offset {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,32 +145,32 @@ func (c *context) pending(offset, id int) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) markPending(offset, id int) {
|
func (r *results) markPending(offset, id int) {
|
||||||
if len(c.isPending) <= id {
|
if len(r.isPending) <= id {
|
||||||
if cap(c.isPending) > id {
|
if cap(r.isPending) > id {
|
||||||
c.isPending = c.isPending[:id+1]
|
r.isPending = r.isPending[:id+1]
|
||||||
} else {
|
} else {
|
||||||
c.isPending = c.isPending[:cap(c.isPending)]
|
r.isPending = r.isPending[:cap(r.isPending)]
|
||||||
for i := cap(c.isPending); i <= id; i++ {
|
for i := cap(r.isPending); i <= id; i++ {
|
||||||
c.isPending = append(c.isPending, nil)
|
r.isPending = append(r.isPending, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range c.isPending[id] {
|
for i := range r.isPending[id] {
|
||||||
if c.isPending[id][i] == -1 {
|
if r.isPending[id][i] == -1 {
|
||||||
c.isPending[id][i] = offset
|
r.isPending[id][i] = offset
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.isPending[id] = append(c.isPending[id], offset)
|
r.isPending[id] = append(r.isPending[id], offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) unmarkPending(offset, id int) {
|
func (r *results) unmarkPending(offset, id int) {
|
||||||
for i := range c.isPending[id] {
|
for i := range r.isPending[id] {
|
||||||
if c.isPending[id][i] == offset {
|
if r.isPending[id][i] == offset {
|
||||||
c.isPending[id][i] = -1
|
r.isPending[id][i] = -1
|
||||||
break
|
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) {
|
func (p *sequenceParser) parse(c *context) {
|
||||||
if !p.allChars {
|
if !p.allChars {
|
||||||
if c.pending(c.offset, p.id) {
|
if c.results.pending(c.offset, p.id) {
|
||||||
c.fail(c.offset)
|
c.fail(c.offset)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.markPending(c.offset, p.id)
|
c.results.markPending(c.offset, p.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
itemIndex := 0
|
itemIndex := 0
|
||||||
@ -192,9 +192,8 @@ func (p *sequenceParser) parse(c *context) {
|
|||||||
if !c.matchLast {
|
if !c.matchLast {
|
||||||
if currentCount < p.ranges[itemIndex][0] {
|
if currentCount < p.ranges[itemIndex][0] {
|
||||||
c.fail(from)
|
c.fail(from)
|
||||||
|
|
||||||
if !p.allChars {
|
if !p.allChars {
|
||||||
c.unmarkPending(from, p.id)
|
c.results.unmarkPending(from, p.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
@ -219,7 +218,7 @@ func (p *sequenceParser) parse(c *context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, g := range p.generalizations {
|
for _, g := range p.generalizations {
|
||||||
if c.pending(from, g) {
|
if c.results.pending(from, g) {
|
||||||
c.results.setMatch(from, g, to)
|
c.results.setMatch(from, g, to)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -227,7 +226,7 @@ func (p *sequenceParser) parse(c *context) {
|
|||||||
c.results.setMatch(from, p.id, to)
|
c.results.setMatch(from, p.id, to)
|
||||||
c.success(to)
|
c.success(to)
|
||||||
if !p.allChars {
|
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 {
|
} else if parsed {
|
||||||
c.results.dropMatchTo(c.offset, b.id, to)
|
c.results.dropMatchTo(c.offset, b.id, to)
|
||||||
} else {
|
} else {
|
||||||
if c.pending(c.offset, b.id) {
|
if c.results.pending(c.offset, b.id) {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
c.markPending(c.offset, b.id)
|
c.results.markPending(c.offset, b.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -303,7 +302,7 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !parsed {
|
if !parsed {
|
||||||
c.unmarkPending(from, b.id)
|
c.results.unmarkPending(from, b.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.commit&Alias != 0 {
|
if b.commit&Alias != 0 {
|
||||||
|
Loading…
Reference in New Issue
Block a user