refactor parse phase - context
This commit is contained in:
parent
e0f61f9d28
commit
0efa15656d
2
char.go
2
char.go
@ -70,7 +70,7 @@ func (p *charParser) parse(c *context) {
|
||||
}
|
||||
|
||||
for _, includedBy := range p.includedBy {
|
||||
c.store.setMatch(c.offset, includedBy, c.offset+1)
|
||||
c.results.setMatch(c.offset, includedBy, c.offset+1)
|
||||
}
|
||||
|
||||
c.success(c.offset + 1)
|
||||
|
20
choice.go
20
choice.go
@ -141,16 +141,16 @@ func (p *choiceParser) nodeName() string { return p.name }
|
||||
func (p *choiceParser) nodeID() int { return p.id }
|
||||
|
||||
func (p *choiceParser) parse(c *context) {
|
||||
if c.fromStore(p.id) {
|
||||
if c.fromResults(p.id) {
|
||||
return
|
||||
}
|
||||
|
||||
if c.excluded(c.offset, p.id) {
|
||||
if c.pending(c.offset, p.id) {
|
||||
c.fail(c.offset)
|
||||
return
|
||||
}
|
||||
|
||||
c.exclude(c.offset, p.id)
|
||||
c.markPending(c.offset, p.id)
|
||||
from := c.offset
|
||||
to := c.offset
|
||||
|
||||
@ -171,7 +171,7 @@ func (p *choiceParser) parse(c *context) {
|
||||
p.elements[elementIndex].parse(c)
|
||||
elementIndex++
|
||||
|
||||
if !c.match || match && c.offset <= to {
|
||||
if !c.matchLast || match && c.offset <= to {
|
||||
c.offset = from
|
||||
continue
|
||||
}
|
||||
@ -181,7 +181,7 @@ func (p *choiceParser) parse(c *context) {
|
||||
to = c.offset
|
||||
c.offset = from
|
||||
|
||||
c.store.setMatch(from, p.id, to)
|
||||
c.results.setMatch(from, p.id, to)
|
||||
}
|
||||
|
||||
if !foundMatch {
|
||||
@ -191,27 +191,27 @@ func (p *choiceParser) parse(c *context) {
|
||||
|
||||
if match {
|
||||
c.success(to)
|
||||
c.include(from, p.id)
|
||||
c.unmarkPending(from, p.id)
|
||||
return
|
||||
}
|
||||
|
||||
c.store.setNoMatch(from, p.id)
|
||||
c.results.setNoMatch(from, p.id)
|
||||
c.fail(from)
|
||||
c.include(from, p.id)
|
||||
c.unmarkPending(from, p.id)
|
||||
}
|
||||
|
||||
func (b *choiceBuilder) nodeName() string { return b.name }
|
||||
func (b *choiceBuilder) nodeID() int { return b.id }
|
||||
|
||||
func (b *choiceBuilder) build(c *context) ([]*Node, bool) {
|
||||
to, ok := c.store.takeMatch(c.offset, b.id, b.includedBy)
|
||||
to, ok := c.results.takeMatch(c.offset, b.id, b.includedBy)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
var element builder
|
||||
for _, e := range b.elements {
|
||||
if c.store.hasMatchTo(c.offset, e.nodeID(), to) {
|
||||
if c.results.hasMatchTo(c.offset, e.nodeID(), to) {
|
||||
element = e
|
||||
break
|
||||
}
|
||||
|
60
context.go
60
context.go
@ -11,17 +11,16 @@ type context struct {
|
||||
readOffset int
|
||||
readErr error
|
||||
eof bool
|
||||
store *store
|
||||
results *results
|
||||
tokens []rune
|
||||
match bool
|
||||
node *Node
|
||||
isExcluded [][]int
|
||||
matchLast bool
|
||||
isPending [][]int
|
||||
}
|
||||
|
||||
func newContext(r io.RuneReader) *context {
|
||||
return &context{
|
||||
reader: r,
|
||||
store: &store{},
|
||||
reader: r,
|
||||
results: &results{},
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,13 +63,13 @@ func (c *context) token() (rune, bool) {
|
||||
return c.tokens[c.offset], true
|
||||
}
|
||||
|
||||
func (c *context) excluded(offset int, id int) bool {
|
||||
if len(c.isExcluded) <= id {
|
||||
func (c *context) pending(offset int, id int) bool {
|
||||
if len(c.isPending) <= id {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := range c.isExcluded[id] {
|
||||
if c.isExcluded[id][i] == offset {
|
||||
for i := range c.isPending[id] {
|
||||
if c.isPending[id][i] == offset {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -78,40 +77,39 @@ func (c *context) excluded(offset int, id int) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *context) exclude(offset int, id int) {
|
||||
if len(c.isExcluded) <= id {
|
||||
if cap(c.isExcluded) > id {
|
||||
c.isExcluded = c.isExcluded[:id+1]
|
||||
func (c *context) markPending(offset int, id int) {
|
||||
if len(c.isPending) <= id {
|
||||
if cap(c.isPending) > id {
|
||||
c.isPending = c.isPending[:id+1]
|
||||
} else {
|
||||
c.isExcluded = c.isExcluded[:cap(c.isExcluded)]
|
||||
for i := cap(c.isExcluded); i <= id; i++ {
|
||||
c.isExcluded = append(c.isExcluded, nil)
|
||||
c.isPending = c.isPending[:cap(c.isPending)]
|
||||
for i := cap(c.isPending); i <= id; i++ {
|
||||
c.isPending = append(c.isPending, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i := range c.isExcluded[id] {
|
||||
if c.isExcluded[id][i] == -1 {
|
||||
c.isExcluded[id][i] = offset
|
||||
for i := range c.isPending[id] {
|
||||
if c.isPending[id][i] == -1 {
|
||||
c.isPending[id][i] = offset
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.isExcluded[id] = append(c.isExcluded[id], offset)
|
||||
c.isPending[id] = append(c.isPending[id], offset)
|
||||
}
|
||||
|
||||
func (c *context) include(offset int, id int) {
|
||||
for i := range c.isExcluded[id] {
|
||||
if c.isExcluded[id][i] == offset {
|
||||
// c.isExcluded[id] = append(c.isExcluded[id][:i], c.isExcluded[id][i+1:]...)
|
||||
c.isExcluded[id][i] = -1
|
||||
func (c *context) unmarkPending(offset int, id int) {
|
||||
for i := range c.isPending[id] {
|
||||
if c.isPending[id][i] == offset {
|
||||
c.isPending[id][i] = -1
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *context) fromStore(id int) bool {
|
||||
to, m, ok := c.store.getMatch(c.offset, id)
|
||||
func (c *context) fromResults(id int) bool {
|
||||
to, m, ok := c.results.getMatch(c.offset, id)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
@ -127,17 +125,17 @@ func (c *context) fromStore(id int) bool {
|
||||
|
||||
func (c *context) success(to int) {
|
||||
c.offset = to
|
||||
c.match = true
|
||||
c.matchLast = true
|
||||
}
|
||||
|
||||
func (c *context) fail(offset int) {
|
||||
c.offset = offset
|
||||
c.match = false
|
||||
c.matchLast = false
|
||||
}
|
||||
|
||||
func (c *context) finalize(root parser) error {
|
||||
rootID := root.nodeID()
|
||||
to, match, found := c.store.getMatch(0, rootID)
|
||||
to, match, found := c.results.getMatch(0, rootID)
|
||||
if !found || !match || to < c.readOffset {
|
||||
return ErrUnexpectedCharacter
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
package treerack
|
||||
|
||||
type store struct {
|
||||
type results struct {
|
||||
noMatch []*idSet
|
||||
match [][]int
|
||||
}
|
||||
|
||||
func (s *store) getMatch(offset, id int) (int, bool, bool) {
|
||||
func (s *results) getMatch(offset, id int) (int, bool, bool) {
|
||||
if len(s.noMatch) > offset && s.noMatch[offset] != nil && s.noMatch[offset].has(id) {
|
||||
return 0, false, true
|
||||
}
|
||||
@ -33,7 +33,7 @@ func (s *store) getMatch(offset, id int) (int, bool, bool) {
|
||||
return to, found, found
|
||||
}
|
||||
|
||||
func (s *store) hasMatchTo(offset, id, to int) bool {
|
||||
func (s *results) hasMatchTo(offset, id, to int) bool {
|
||||
if len(s.noMatch) > offset && s.noMatch[offset] != nil && s.noMatch[offset].has(id) {
|
||||
return false
|
||||
}
|
||||
@ -55,7 +55,7 @@ func (s *store) hasMatchTo(offset, id, to int) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *store) takeMatch(offset, id int, includedBy *idSet) (int, bool) {
|
||||
func (s *results) takeMatch(offset, id int, includedBy *idSet) (int, bool) {
|
||||
if len(s.match) <= offset {
|
||||
return 0, false
|
||||
}
|
||||
@ -91,7 +91,7 @@ func (s *store) takeMatch(offset, id int, includedBy *idSet) (int, bool) {
|
||||
return to, found
|
||||
}
|
||||
|
||||
func (s *store) takeMatchLength(offset, id, to int) {
|
||||
func (s *results) takeMatchLength(offset, id, to int) {
|
||||
if len(s.match) <= offset {
|
||||
return
|
||||
}
|
||||
@ -104,7 +104,7 @@ func (s *store) takeMatchLength(offset, id, to int) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *store) ensureOffset(offset int) {
|
||||
func (s *results) ensureOffset(offset int) {
|
||||
if len(s.match) > offset {
|
||||
return
|
||||
}
|
||||
@ -120,7 +120,7 @@ func (s *store) ensureOffset(offset int) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *store) setMatch(offset, id, to int) {
|
||||
func (s *results) setMatch(offset, id, to int) {
|
||||
s.ensureOffset(offset)
|
||||
for i := 0; i < len(s.match[offset]); i += 2 {
|
||||
if s.match[offset][i] != id || s.match[offset][i+1] != to {
|
||||
@ -133,7 +133,7 @@ func (s *store) setMatch(offset, id, to int) {
|
||||
s.match[offset] = append(s.match[offset], id, to)
|
||||
}
|
||||
|
||||
func (s *store) setNoMatch(offset, id int) {
|
||||
func (s *results) setNoMatch(offset, id int) {
|
||||
if len(s.match) > offset {
|
||||
for i := 0; i < len(s.match[offset]); i += 2 {
|
||||
if s.match[offset][i] != id {
|
18
sequence.go
18
sequence.go
@ -179,12 +179,12 @@ func (p *sequenceParser) nodeID() int { return p.id }
|
||||
|
||||
func (p *sequenceParser) parse(c *context) {
|
||||
if !p.allChars {
|
||||
if c.excluded(c.offset, p.id) {
|
||||
if c.pending(c.offset, p.id) {
|
||||
c.fail(c.offset)
|
||||
return
|
||||
}
|
||||
|
||||
c.exclude(c.offset, p.id)
|
||||
c.markPending(c.offset, p.id)
|
||||
}
|
||||
|
||||
itemIndex := 0
|
||||
@ -196,12 +196,12 @@ func (p *sequenceParser) parse(c *context) {
|
||||
for itemIndex < len(p.items) {
|
||||
// TODO: is it ok to parse before max range check? what if max=0
|
||||
p.items[itemIndex].parse(c)
|
||||
if !c.match {
|
||||
if !c.matchLast {
|
||||
if currentCount < p.ranges[itemIndex][0] {
|
||||
c.fail(from)
|
||||
|
||||
if !p.allChars {
|
||||
c.include(from, p.id)
|
||||
c.unmarkPending(from, p.id)
|
||||
}
|
||||
|
||||
return
|
||||
@ -227,17 +227,17 @@ func (p *sequenceParser) parse(c *context) {
|
||||
|
||||
if !p.allChars {
|
||||
for _, includedBy := range p.includedBy {
|
||||
if c.excluded(from, includedBy) {
|
||||
c.store.setMatch(from, includedBy, to)
|
||||
if c.pending(from, includedBy) {
|
||||
c.results.setMatch(from, includedBy, to)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.store.setMatch(from, p.id, to)
|
||||
c.results.setMatch(from, p.id, to)
|
||||
c.success(to)
|
||||
|
||||
if !p.allChars {
|
||||
c.include(from, p.id)
|
||||
c.unmarkPending(from, p.id)
|
||||
}
|
||||
}
|
||||
|
||||
@ -245,7 +245,7 @@ func (b *sequenceBuilder) nodeName() string { return b.name }
|
||||
func (b *sequenceBuilder) nodeID() int { return b.id }
|
||||
|
||||
func (b *sequenceBuilder) build(c *context) ([]*Node, bool) {
|
||||
to, ok := c.store.takeMatch(c.offset, b.id, b.includedBy)
|
||||
to, ok := c.results.takeMatch(c.offset, b.id, b.includedBy)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user