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