treerack/sequence.go

212 lines
3.8 KiB
Go
Raw Normal View History

2017-07-15 21:49:08 +02:00
package treerack
2017-06-25 17:51:08 +02:00
type sequenceParser struct {
2017-11-02 22:19:03 +01:00
name string
id int
commit CommitType
items []parser
ranges [][]int
generalizations []int
allChars bool
2017-06-25 17:51:08 +02:00
}
2017-07-29 16:25:17 +02:00
type sequenceBuilder struct {
2018-08-19 22:40:01 +02:00
name string
id int
commit CommitType
items []builder
ranges [][]int
generalizations []int
allChars bool
2017-06-25 17:51:08 +02:00
}
2017-11-25 17:37:05 +01:00
func (p *sequenceParser) nodeName() string { return p.name }
func (p *sequenceParser) nodeID() int { return p.id }
func (p *sequenceParser) commitType() CommitType { return p.commit }
2017-06-25 17:51:08 +02:00
2017-10-31 21:09:30 +01:00
func (p *sequenceParser) parse(c *context) {
2017-08-06 03:42:35 +02:00
if !p.allChars {
2017-11-06 11:41:00 +01:00
if c.results.pending(c.offset, p.id) {
2017-11-25 22:01:02 +01:00
c.fail(c.offset)
2017-08-06 03:42:35 +02:00
return
}
2017-06-25 17:51:08 +02:00
2017-11-06 11:41:00 +01:00
c.results.markPending(c.offset, p.id)
2017-08-06 03:42:35 +02:00
}
2017-06-25 17:51:08 +02:00
2017-12-31 17:34:10 +01:00
var (
currentCount int
parsed bool
)
2017-07-17 04:23:29 +02:00
itemIndex := 0
from := c.offset
to := c.offset
for itemIndex < len(p.items) {
2017-10-31 21:09:30 +01:00
p.items[itemIndex].parse(c)
2017-11-02 20:49:49 +01:00
if !c.matchLast {
2017-12-31 17:34:10 +01:00
if currentCount >= p.ranges[itemIndex][0] {
itemIndex++
currentCount = 0
continue
2017-06-25 23:38:32 +02:00
}
c.offset = from
if c.fromResults(p) {
if to > c.failOffset {
c.failOffset = -1
c.failingParser = nil
}
if !p.allChars {
c.results.unmarkPending(from, p.id)
}
return
}
2017-12-31 17:34:10 +01:00
if c.failingParser == nil &&
2018-01-04 18:36:59 +01:00
p.commit&userDefined != 0 &&
p.commit&Whitespace == 0 &&
p.commit&FailPass == 0 {
2017-12-31 17:34:10 +01:00
c.failingParser = p
}
c.fail(from)
if !p.allChars {
c.results.unmarkPending(from, p.id)
}
return
2017-06-25 17:51:08 +02:00
}
2017-07-30 02:35:51 +02:00
parsed = c.offset > to
2017-07-17 04:23:29 +02:00
if parsed {
2017-06-25 23:38:32 +02:00
currentCount++
}
2017-07-17 04:23:29 +02:00
to = c.offset
2017-11-04 22:49:42 +01:00
if !parsed || p.ranges[itemIndex][1] > 0 && currentCount == p.ranges[itemIndex][1] {
2017-07-17 04:23:29 +02:00
itemIndex++
2017-06-25 23:38:32 +02:00
currentCount = 0
2017-06-25 17:51:08 +02:00
}
}
2017-11-02 22:19:03 +01:00
for _, g := range p.generalizations {
2017-11-06 11:41:00 +01:00
if c.results.pending(from, g) {
2017-11-02 22:19:03 +01:00
c.results.setMatch(from, g, to)
}
2017-06-25 17:51:08 +02:00
}
if to > c.failOffset {
c.failOffset = -1
c.failingParser = nil
}
2017-11-02 20:49:49 +01:00
c.results.setMatch(from, p.id, to)
2017-07-17 04:23:29 +02:00
c.success(to)
2017-08-06 03:42:35 +02:00
if !p.allChars {
2017-11-06 11:41:00 +01:00
c.results.unmarkPending(from, p.id)
2017-08-06 03:42:35 +02:00
}
2017-06-25 17:51:08 +02:00
}
2017-07-29 16:25:17 +02:00
func (b *sequenceBuilder) nodeName() string { return b.name }
func (b *sequenceBuilder) nodeID() int { return b.id }
2017-07-29 18:40:22 +02:00
func (b *sequenceBuilder) build(c *context) ([]*Node, bool) {
to, ok := c.results.longestMatch(c.offset, b.id)
2017-07-29 18:40:22 +02:00
if !ok {
return nil, false
}
from := c.offset
2017-11-04 22:24:55 +01:00
parsed := to > from
2017-07-30 02:35:51 +02:00
if b.allChars {
c.offset = to
if b.commit&Alias != 0 {
return nil, true
}
return []*Node{{
Name: b.name,
From: from,
To: to,
tokens: c.tokens,
}}, true
2017-11-04 22:24:55 +01:00
} else if parsed {
c.results.dropMatchTo(c.offset, b.id, to)
2018-08-19 22:40:01 +02:00
for _, g := range b.generalizations {
c.results.dropMatchTo(c.offset, g, to)
}
2017-11-04 22:24:55 +01:00
} else {
2017-11-06 11:41:00 +01:00
if c.results.pending(c.offset, b.id) {
2017-11-04 22:24:55 +01:00
return nil, false
}
2017-11-06 11:41:00 +01:00
c.results.markPending(c.offset, b.id)
2018-08-19 22:40:01 +02:00
for _, g := range b.generalizations {
c.results.markPending(c.offset, g)
}
2017-07-29 20:04:22 +02:00
}
2017-07-29 18:40:22 +02:00
var (
itemIndex int
currentCount int
nodes []*Node
)
for itemIndex < len(b.items) {
itemFrom := c.offset
n, ok := b.items[itemIndex].build(c)
if !ok {
itemIndex++
currentCount = 0
continue
}
2017-11-04 22:24:55 +01:00
if c.offset > itemFrom {
2017-07-29 18:40:22 +02:00
nodes = append(nodes, n...)
currentCount++
2017-11-04 22:49:42 +01:00
if b.ranges[itemIndex][1] > 0 && currentCount == b.ranges[itemIndex][1] {
2017-11-04 22:24:55 +01:00
itemIndex++
currentCount = 0
}
continue
}
2017-11-04 22:24:55 +01:00
if currentCount < b.ranges[itemIndex][0] {
for i := 0; i < b.ranges[itemIndex][0]-currentCount; i++ {
nodes = append(nodes, n...)
}
2017-07-29 18:40:22 +02:00
}
2017-11-04 22:24:55 +01:00
itemIndex++
currentCount = 0
2017-07-29 18:40:22 +02:00
}
2017-11-04 22:24:55 +01:00
if !parsed {
2017-11-06 11:41:00 +01:00
c.results.unmarkPending(from, b.id)
2018-08-19 22:40:01 +02:00
for _, g := range b.generalizations {
c.results.unmarkPending(from, g)
}
2017-11-04 22:24:55 +01:00
}
2017-07-29 18:40:22 +02:00
if b.commit&Alias != 0 {
return nodes, true
2017-06-25 17:51:08 +02:00
}
2017-07-29 18:40:22 +02:00
return []*Node{{
Name: b.name,
From: from,
To: to,
Nodes: nodes,
tokens: c.tokens,
}}, true
2017-06-25 17:51:08 +02:00
}