find bug with min, max and sequence includes

This commit is contained in:
Arpad Ryszka 2017-08-06 21:47:53 +02:00
parent 246b68b0c2
commit 35a42d7dba
5 changed files with 87 additions and 107 deletions

View File

@ -3,7 +3,6 @@ package treerack
import ( import (
"os" "os"
"testing" "testing"
"time"
) )
func TestBoot(t *testing.T) { func TestBoot(t *testing.T) {
@ -21,73 +20,65 @@ func TestBoot(t *testing.T) {
defer f.Close() defer f.Close()
var d time.Duration
const n = 120
var n0 *Node
for i := 0; i < n; i++ {
if _, err := f.Seek(0, 0); err != nil { if _, err := f.Seek(0, 0); err != nil {
t.Error(err) t.Error(err)
return return
} }
start := time.Now() b.trace = NewTrace(1)
n0, err = b.Parse(f) _, err = b.Parse(f)
d += time.Now().Sub(start)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
return return
} }
}
t.Log("duration:", d/n) // s0 := NewSyntax()
// if err := define(s0, n0); err != nil {
// t.Error(err)
// return
// }
s0 := NewSyntax() // _, err = f.Seek(0, 0)
if err := define(s0, n0); err != nil { // if err != nil {
t.Error(err) // t.Error(err)
return // return
} // }
_, err = f.Seek(0, 0) // err = s0.Init()
if err != nil { // if err != nil {
t.Error(err) // t.Error(err)
return // return
} // }
err = s0.Init() // n1, err := s0.Parse(f)
if err != nil { // if err != nil {
t.Error(err) // t.Error(err)
return // return
} // }
n1, err := s0.Parse(f) // checkNode(t, n1, n0)
if err != nil { // if t.Failed() {
t.Error(err) // return
return // }
}
checkNode(t, n1, n0) // s1 := NewSyntax()
if t.Failed() { // if err := define(s1, n1); err != nil {
return // t.Error(err)
} // return
// }
s1 := NewSyntax() // _, err = f.Seek(0, 0)
if err := define(s1, n1); err != nil { // if err != nil {
t.Error(err) // t.Error(err)
return // return
} // }
_, err = f.Seek(0, 0) // n2, err := s1.Parse(f)
if err != nil { // if err != nil {
t.Error(err) // t.Error(err)
return // return
} // }
n2, err := s1.Parse(f) // checkNode(t, n2, n1)
if err != nil {
t.Error(err)
return
}
checkNode(t, n2, n1)
} }

View File

@ -71,16 +71,16 @@ func (p *charParser) match(t rune) bool {
} }
func (p *charParser) parse(t Trace, c *context) { func (p *charParser) parse(t Trace, c *context) {
// t = t.Extend(p.name) t = t.Extend(p.name)
// t.Out1("parsing", c.offset) t.Out1("parsing", c.offset)
if tok, ok := c.token(); !ok || !p.match(tok) { if tok, ok := c.token(); !ok || !p.match(tok) {
// t.Out1("fail") t.Out1("fail")
c.fail(c.offset) c.fail(c.offset)
return return
} }
// t.Out1("success") t.Out1("success")
c.success(c.offset + 1) c.success(c.offset + 1)
for _, includedBy := range p.includedBy { for _, includedBy := range p.includedBy {
c.store.setMatch(c.offset, includedBy, c.offset+1) c.store.setMatch(c.offset, includedBy, c.offset+1)

View File

@ -40,7 +40,7 @@ func (d *choiceDefinition) commitType() CommitType { return d.commit }
func (d *choiceDefinition) validate(r *registry, path *idSet) error { func (d *choiceDefinition) validate(r *registry, path *idSet) error {
for i := range d.elements { for i := range d.elements {
if _, ok := r.definition(d.elements[i]); !ok { if _, ok := r.definitions[d.elements[i]]; !ok {
return parserNotFound(d.elements[i]) return parserNotFound(d.elements[i])
} }
} }
@ -55,12 +55,7 @@ func (d *choiceDefinition) normalize(r *registry, path *idSet) error {
path.set(d.id) path.set(d.id)
for i := range d.elements { for i := range d.elements {
element, ok := r.definition(d.elements[i]) r.definitions[d.elements[i]].normalize(r, path)
if !ok {
return parserNotFound(d.elements[i])
}
element.normalize(r, path)
} }
return nil return nil
@ -77,12 +72,7 @@ func (d *choiceDefinition) init(r *registry) error {
} }
for _, e := range d.elements { for _, e := range d.elements {
def, ok := r.definition(e) d.cbuilder.elements = append(d.cbuilder.elements, r.definitions[e].builder())
if !ok {
return parserNotFound(e)
}
d.cbuilder.elements = append(d.cbuilder.elements, def.builder())
} }
parsers := &idSet{} parsers := &idSet{}
@ -141,12 +131,7 @@ func (d *choiceDefinition) parser(r *registry, parsers *idSet) (parser, error) {
continue continue
} }
elementDefinition, ok := r.definition(e) element, err := r.definitions[e].parser(r, parsers)
if !ok {
return nil, parserNotFound(e)
}
element, err := elementDefinition.parser(r, parsers)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -175,8 +160,8 @@ func (p *choiceParser) nodeName() string { return p.name }
func (p *choiceParser) nodeID() int { return p.id } func (p *choiceParser) nodeID() int { return p.id }
func (p *choiceParser) parse(t Trace, c *context) { func (p *choiceParser) parse(t Trace, c *context) {
// t = t.Extend(p.name) t = t.Extend(p.name)
// t.Out1("parsing choice", c.offset) t.Out1("parsing choice", c.offset)
// TODO: don't add documentation // TODO: don't add documentation
// if p.commit&Documentation != 0 { // if p.commit&Documentation != 0 {
@ -186,12 +171,12 @@ func (p *choiceParser) parse(t Trace, c *context) {
// } // }
if c.fromStore(p.id) { if c.fromStore(p.id) {
// t.Out1("found in store, match:") t.Out1("found in store, match:")
return return
} }
if c.excluded(c.offset, p.id) { if c.excluded(c.offset, p.id) {
// t.Out1("fail, excluded") t.Out1("fail, excluded")
c.fail(c.offset) c.fail(c.offset)
return return
} }
@ -208,6 +193,8 @@ func (p *choiceParser) parse(t Trace, c *context) {
foundMatch = false foundMatch = false
elementIndex = 0 elementIndex = 0
// TODO: avoid double parsing by setting first-from-store in the context
for elementIndex < len(p.elements) { for elementIndex < len(p.elements) {
p.elements[elementIndex].parse(t, c) p.elements[elementIndex].parse(t, c)
elementIndex++ elementIndex++
@ -233,11 +220,11 @@ func (p *choiceParser) parse(t Trace, c *context) {
if match { if match {
c.success(to) c.success(to)
c.include(from, p.id) c.include(from, p.id)
// t.Out1("choice, success") t.Out1("choice, success")
return return
} }
// t.Out1("fail") t.Out1("fail")
c.store.setNoMatch(from, p.id) c.store.setNoMatch(from, p.id)
c.fail(from) c.fail(from)
c.include(from, p.id) c.include(from, p.id)

View File

@ -61,6 +61,10 @@ func (c *context) token() (rune, bool) {
} }
} }
if len(c.tokens) <= c.offset {
println(len(c.tokens), c.offset)
}
return c.tokens[c.offset], true return c.tokens[c.offset], true
} }

View File

@ -54,19 +54,26 @@ func (d *sequenceDefinition) validate(r *registry, path *idSet) error {
return nil return nil
} }
func (d *sequenceDefinition) normalizeItems() {
for i := range d.items {
if d.items[i].Min == 0 && d.items[i].Max == 0 {
d.items[i].Min, d.items[i].Max = 1, 1
} else if d.items[i].Max == 0 {
d.items[i].Max = -1
}
}
}
func (d *sequenceDefinition) normalize(r *registry, path *idSet) error { func (d *sequenceDefinition) normalize(r *registry, path *idSet) error {
if path.has(d.id) { if path.has(d.id) {
return nil return nil
} }
// d.normalizeItems()
path.set(d.id) path.set(d.id)
for i := range d.items { for i := range d.items {
item, ok := r.definition(d.items[i].Name) r.definitions[d.items[i].Name].normalize(r, path)
if !ok {
return parserNotFound(d.items[i].Name)
}
item.normalize(r, path)
} }
return nil return nil
@ -96,11 +103,7 @@ func (d *sequenceDefinition) init(r *registry) error {
d.ranges = append(d.ranges, []int{item.Min, item.Max}) d.ranges = append(d.ranges, []int{item.Min, item.Max})
def, ok := r.definition(item.Name) def := r.definitions[item.Name]
if !ok {
return parserNotFound(item.Name)
}
d.sbuilder.items = append(d.sbuilder.items, def.builder()) d.sbuilder.items = append(d.sbuilder.items, def.builder())
if allChars { if allChars {
@ -180,12 +183,7 @@ func (d *sequenceDefinition) parser(r *registry, parsers *idSet) (parser, error)
continue continue
} }
itemDefinition, ok := r.definition(item.Name) pi, err := r.definitions[item.Name].parser(r, parsers)
if !ok {
return nil, parserNotFound(item.Name)
}
pi, err := itemDefinition.parser(r, parsers)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -215,8 +213,8 @@ func (p *sequenceParser) nodeName() string { return p.name }
func (p *sequenceParser) nodeID() int { return p.id } func (p *sequenceParser) nodeID() int { return p.id }
func (p *sequenceParser) parse(t Trace, c *context) { func (p *sequenceParser) parse(t Trace, c *context) {
// t = t.Extend(p.name) t = t.Extend(p.name)
// t.Out1("parsing sequence", c.offset) t.Out1("parsing sequence", c.offset)
// if p.commit&Documentation != 0 { // if p.commit&Documentation != 0 {
// // t.Out1("fail, doc") // // t.Out1("fail, doc")
@ -226,7 +224,7 @@ func (p *sequenceParser) parse(t Trace, c *context) {
if !p.allChars { if !p.allChars {
if c.excluded(c.offset, p.id) { if c.excluded(c.offset, p.id) {
// t.Out1("fail, excluded") t.Out1("fail, excluded")
c.fail(c.offset) c.fail(c.offset)
return return
} }
@ -252,7 +250,7 @@ func (p *sequenceParser) parse(t Trace, c *context) {
c.include(from, p.id) c.include(from, p.id)
} }
// t.Out1("fail, not enough items") t.Out1("fail, not enough items")
return return
} }
@ -277,13 +275,13 @@ func (p *sequenceParser) parse(t Trace, c *context) {
if !p.allChars { if !p.allChars {
for _, includedBy := range p.includedBy { for _, includedBy := range p.includedBy {
if c.excluded(from, includedBy) { if c.excluded(from, includedBy) {
// t.Out1("storing included", includedBy) t.Out1("storing included", includedBy)
c.store.setMatch(from, includedBy, to) c.store.setMatch(from, includedBy, to)
} }
} }
} }
// t.Out1("success") t.Out1("success")
c.store.setMatch(from, p.id, to) c.store.setMatch(from, p.id, to)
c.success(to) c.success(to)