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
|
|
|
}
|
|
|
|
|
2019-01-27 19:06:44 +01: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-07-29 22:31:16 +02:00
|
|
|
}
|
2017-06-25 17:51:08 +02:00
|
|
|
}
|
|
|
|
|
2017-12-29 14:59:13 +01:00
|
|
|
if to > c.failOffset {
|
2017-11-28 20:52:02 +01:00
|
|
|
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) {
|
2017-11-04 22:08:15 +01:00
|
|
|
to, ok := c.results.longestMatch(c.offset, b.id)
|
2017-07-29 18:40:22 +02:00
|
|
|
if !ok {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
|
2017-11-04 22:08:15 +01:00
|
|
|
from := c.offset
|
2017-11-04 22:24:55 +01:00
|
|
|
parsed := to > from
|
2017-11-04 22:08:15 +01:00
|
|
|
|
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
|
2017-11-04 22:08:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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-11-04 22:08:15 +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
|
|
|
}
|