diff --git a/boot_test.go b/boot_test.go index ff5a192..9b8614e 100644 --- a/boot_test.go +++ b/boot_test.go @@ -3,7 +3,6 @@ package treerack import ( "os" "testing" - "time" ) func TestBoot(t *testing.T) { @@ -21,73 +20,65 @@ func TestBoot(t *testing.T) { 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 { - t.Error(err) - return - } - - start := time.Now() - n0, err = b.Parse(f) - d += time.Now().Sub(start) - - if err != nil { - t.Error(err) - return - } - } - - t.Log("duration:", d/n) - - s0 := NewSyntax() - if err := define(s0, n0); err != nil { + if _, err := f.Seek(0, 0); err != nil { t.Error(err) return } - _, err = f.Seek(0, 0) + b.trace = NewTrace(1) + _, err = b.Parse(f) + if err != nil { t.Error(err) return } - err = s0.Init() - if err != nil { - t.Error(err) - return - } + // s0 := NewSyntax() + // if err := define(s0, n0); err != nil { + // t.Error(err) + // return + // } - n1, err := s0.Parse(f) - if err != nil { - t.Error(err) - return - } + // _, err = f.Seek(0, 0) + // if err != nil { + // t.Error(err) + // return + // } - checkNode(t, n1, n0) - if t.Failed() { - return - } + // err = s0.Init() + // if err != nil { + // t.Error(err) + // return + // } - s1 := NewSyntax() - if err := define(s1, n1); err != nil { - t.Error(err) - return - } + // n1, err := s0.Parse(f) + // if err != nil { + // t.Error(err) + // return + // } - _, err = f.Seek(0, 0) - if err != nil { - t.Error(err) - return - } + // checkNode(t, n1, n0) + // if t.Failed() { + // return + // } - n2, err := s1.Parse(f) - if err != nil { - t.Error(err) - return - } + // s1 := NewSyntax() + // if err := define(s1, n1); err != nil { + // t.Error(err) + // return + // } - checkNode(t, n2, n1) + // _, err = f.Seek(0, 0) + // if err != nil { + // t.Error(err) + // return + // } + + // n2, err := s1.Parse(f) + // if err != nil { + // t.Error(err) + // return + // } + + // checkNode(t, n2, n1) } diff --git a/char.go b/char.go index ff2c184..6fb805b 100644 --- a/char.go +++ b/char.go @@ -71,16 +71,16 @@ func (p *charParser) match(t rune) bool { } func (p *charParser) parse(t Trace, c *context) { - // t = t.Extend(p.name) - // t.Out1("parsing", c.offset) + t = t.Extend(p.name) + t.Out1("parsing", c.offset) if tok, ok := c.token(); !ok || !p.match(tok) { - // t.Out1("fail") + t.Out1("fail") c.fail(c.offset) return } - // t.Out1("success") + t.Out1("success") c.success(c.offset + 1) for _, includedBy := range p.includedBy { c.store.setMatch(c.offset, includedBy, c.offset+1) diff --git a/choice.go b/choice.go index ed1e98a..2ef334d 100644 --- a/choice.go +++ b/choice.go @@ -40,7 +40,7 @@ func (d *choiceDefinition) commitType() CommitType { return d.commit } func (d *choiceDefinition) validate(r *registry, path *idSet) error { 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]) } } @@ -55,12 +55,7 @@ func (d *choiceDefinition) normalize(r *registry, path *idSet) error { path.set(d.id) for i := range d.elements { - element, ok := r.definition(d.elements[i]) - if !ok { - return parserNotFound(d.elements[i]) - } - - element.normalize(r, path) + r.definitions[d.elements[i]].normalize(r, path) } return nil @@ -77,12 +72,7 @@ func (d *choiceDefinition) init(r *registry) error { } for _, e := range d.elements { - def, ok := r.definition(e) - if !ok { - return parserNotFound(e) - } - - d.cbuilder.elements = append(d.cbuilder.elements, def.builder()) + d.cbuilder.elements = append(d.cbuilder.elements, r.definitions[e].builder()) } parsers := &idSet{} @@ -141,12 +131,7 @@ func (d *choiceDefinition) parser(r *registry, parsers *idSet) (parser, error) { continue } - elementDefinition, ok := r.definition(e) - if !ok { - return nil, parserNotFound(e) - } - - element, err := elementDefinition.parser(r, parsers) + element, err := r.definitions[e].parser(r, parsers) if err != nil { 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) parse(t Trace, c *context) { - // t = t.Extend(p.name) - // t.Out1("parsing choice", c.offset) + t = t.Extend(p.name) + t.Out1("parsing choice", c.offset) // TODO: don't add documentation // if p.commit&Documentation != 0 { @@ -186,12 +171,12 @@ func (p *choiceParser) parse(t Trace, c *context) { // } if c.fromStore(p.id) { - // t.Out1("found in store, match:") + t.Out1("found in store, match:") return } if c.excluded(c.offset, p.id) { - // t.Out1("fail, excluded") + t.Out1("fail, excluded") c.fail(c.offset) return } @@ -208,6 +193,8 @@ func (p *choiceParser) parse(t Trace, c *context) { foundMatch = false elementIndex = 0 + // TODO: avoid double parsing by setting first-from-store in the context + for elementIndex < len(p.elements) { p.elements[elementIndex].parse(t, c) elementIndex++ @@ -233,11 +220,11 @@ func (p *choiceParser) parse(t Trace, c *context) { if match { c.success(to) c.include(from, p.id) - // t.Out1("choice, success") + t.Out1("choice, success") return } - // t.Out1("fail") + t.Out1("fail") c.store.setNoMatch(from, p.id) c.fail(from) c.include(from, p.id) diff --git a/context.go b/context.go index 852927c..ee06fe8 100644 --- a/context.go +++ b/context.go @@ -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 } diff --git a/sequence.go b/sequence.go index b8953a1..c4d01ed 100644 --- a/sequence.go +++ b/sequence.go @@ -54,19 +54,26 @@ func (d *sequenceDefinition) validate(r *registry, path *idSet) error { 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 { if path.has(d.id) { return nil } + // d.normalizeItems() + path.set(d.id) for i := range d.items { - item, ok := r.definition(d.items[i].Name) - if !ok { - return parserNotFound(d.items[i].Name) - } - - item.normalize(r, path) + r.definitions[d.items[i].Name].normalize(r, path) } return nil @@ -96,11 +103,7 @@ func (d *sequenceDefinition) init(r *registry) error { d.ranges = append(d.ranges, []int{item.Min, item.Max}) - def, ok := r.definition(item.Name) - if !ok { - return parserNotFound(item.Name) - } - + def := r.definitions[item.Name] d.sbuilder.items = append(d.sbuilder.items, def.builder()) if allChars { @@ -180,12 +183,7 @@ func (d *sequenceDefinition) parser(r *registry, parsers *idSet) (parser, error) continue } - itemDefinition, ok := r.definition(item.Name) - if !ok { - return nil, parserNotFound(item.Name) - } - - pi, err := itemDefinition.parser(r, parsers) + pi, err := r.definitions[item.Name].parser(r, parsers) if err != nil { 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) parse(t Trace, c *context) { - // t = t.Extend(p.name) - // t.Out1("parsing sequence", c.offset) + t = t.Extend(p.name) + t.Out1("parsing sequence", c.offset) // if p.commit&Documentation != 0 { // // t.Out1("fail, doc") @@ -226,7 +224,7 @@ func (p *sequenceParser) parse(t Trace, c *context) { if !p.allChars { if c.excluded(c.offset, p.id) { - // t.Out1("fail, excluded") + t.Out1("fail, excluded") c.fail(c.offset) return } @@ -252,7 +250,7 @@ func (p *sequenceParser) parse(t Trace, c *context) { c.include(from, p.id) } - // t.Out1("fail, not enough items") + t.Out1("fail, not enough items") return } @@ -277,13 +275,13 @@ func (p *sequenceParser) parse(t Trace, c *context) { if !p.allChars { for _, includedBy := range p.includedBy { if c.excluded(from, includedBy) { - // t.Out1("storing included", includedBy) + t.Out1("storing included", includedBy) c.store.setMatch(from, includedBy, to) } } } - // t.Out1("success") + t.Out1("success") c.store.setMatch(from, p.id, to) c.success(to)