refactore included
This commit is contained in:
parent
507299f318
commit
72c8418e45
19
char.go
19
char.go
@ -7,7 +7,7 @@ type charParser struct {
|
|||||||
not bool
|
not bool
|
||||||
chars []rune
|
chars []rune
|
||||||
ranges [][]rune
|
ranges [][]rune
|
||||||
includedBy []parser
|
includedBy []int
|
||||||
}
|
}
|
||||||
|
|
||||||
func newChar(
|
func newChar(
|
||||||
@ -30,6 +30,13 @@ func (p *charParser) nodeName() string { return p.name }
|
|||||||
func (p *charParser) nodeID() int { return p.id }
|
func (p *charParser) nodeID() int { return p.id }
|
||||||
func (p *charParser) setID(id int) { p.id = id }
|
func (p *charParser) setID(id int) { p.id = id }
|
||||||
|
|
||||||
|
func (p *charParser) init(r *registry) error { return nil }
|
||||||
|
|
||||||
|
func (p *charParser) setIncludedBy(r *registry, includedBy int, parsers *idSet) error {
|
||||||
|
p.includedBy = appendIfMissing(p.includedBy, includedBy)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *charParser) parser(r *registry, parsers *idSet) (parser, error) {
|
func (p *charParser) parser(r *registry, parsers *idSet) (parser, error) {
|
||||||
if parsers.has(p.id) {
|
if parsers.has(p.id) {
|
||||||
panic(cannotIncludeParsers(p.name))
|
panic(cannotIncludeParsers(p.name))
|
||||||
@ -47,14 +54,6 @@ func (p *charParser) commitType() CommitType {
|
|||||||
return p.commit
|
return p.commit
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *charParser) setIncludedBy(includedBy parser, parsers *idSet) {
|
|
||||||
if parsers.has(p.id) {
|
|
||||||
panic(cannotIncludeParsers(p.name))
|
|
||||||
}
|
|
||||||
|
|
||||||
p.includedBy = append(p.includedBy, includedBy)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *charParser) storeIncluded(*context, int, int) {
|
func (p *charParser) storeIncluded(*context, int, int) {
|
||||||
panic(cannotIncludeParsers(p.name))
|
panic(cannotIncludeParsers(p.name))
|
||||||
}
|
}
|
||||||
@ -83,6 +82,6 @@ func (p *charParser) parse(t Trace, c *context) {
|
|||||||
|
|
||||||
c.success(c.offset + 1)
|
c.success(c.offset + 1)
|
||||||
for _, includedBy := range p.includedBy {
|
for _, includedBy := range p.includedBy {
|
||||||
includedBy.storeIncluded(c, c.offset, c.offset+1)
|
c.store.setMatch(c.offset, includedBy, c.offset+1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
44
choice.go
44
choice.go
@ -5,6 +5,7 @@ type choiceDefinition struct {
|
|||||||
id int
|
id int
|
||||||
commit CommitType
|
commit CommitType
|
||||||
elements []string
|
elements []string
|
||||||
|
includedBy []int
|
||||||
}
|
}
|
||||||
|
|
||||||
type choiceParser struct {
|
type choiceParser struct {
|
||||||
@ -12,7 +13,7 @@ type choiceParser struct {
|
|||||||
id int
|
id int
|
||||||
commit CommitType
|
commit CommitType
|
||||||
elements []parser
|
elements []parser
|
||||||
includedBy []parser
|
includedBy []int
|
||||||
}
|
}
|
||||||
|
|
||||||
func newChoice(name string, ct CommitType, elements []string) *choiceDefinition {
|
func newChoice(name string, ct CommitType, elements []string) *choiceDefinition {
|
||||||
@ -27,6 +28,22 @@ func (d *choiceDefinition) nodeName() string { return d.name }
|
|||||||
func (d *choiceDefinition) nodeID() int { return d.id }
|
func (d *choiceDefinition) nodeID() int { return d.id }
|
||||||
func (d *choiceDefinition) setID(id int) { d.id = id }
|
func (d *choiceDefinition) setID(id int) { d.id = id }
|
||||||
|
|
||||||
|
func (d *choiceDefinition) init(r *registry) error {
|
||||||
|
parsers := &idSet{}
|
||||||
|
parsers.set(d.id)
|
||||||
|
return setItemsIncludedBy(r, d.elements, d.id, parsers)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *choiceDefinition) setIncludedBy(r *registry, includedBy int, parsers *idSet) error {
|
||||||
|
if parsers.has(d.id) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
d.includedBy = appendIfMissing(d.includedBy, includedBy)
|
||||||
|
parsers.set(d.id)
|
||||||
|
return setItemsIncludedBy(r, d.elements, includedBy, parsers)
|
||||||
|
}
|
||||||
|
|
||||||
func (d *choiceDefinition) parser(r *registry, parsers *idSet) (parser, error) {
|
func (d *choiceDefinition) parser(r *registry, parsers *idSet) (parser, error) {
|
||||||
p, ok := r.parser(d.name)
|
p, ok := r.parser(d.name)
|
||||||
if ok {
|
if ok {
|
||||||
@ -37,6 +54,7 @@ func (d *choiceDefinition) parser(r *registry, parsers *idSet) (parser, error) {
|
|||||||
name: d.name,
|
name: d.name,
|
||||||
id: d.id,
|
id: d.id,
|
||||||
commit: d.commit,
|
commit: d.commit,
|
||||||
|
includedBy: d.includedBy,
|
||||||
}
|
}
|
||||||
|
|
||||||
r.setParser(cp)
|
r.setParser(cp)
|
||||||
@ -48,7 +66,6 @@ func (d *choiceDefinition) parser(r *registry, parsers *idSet) (parser, error) {
|
|||||||
element, ok := r.parser(e)
|
element, ok := r.parser(e)
|
||||||
if ok {
|
if ok {
|
||||||
elements = append(elements, element)
|
elements = append(elements, element)
|
||||||
element.setIncludedBy(cp, parsers)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +79,6 @@ func (d *choiceDefinition) parser(r *registry, parsers *idSet) (parser, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
element.setIncludedBy(cp, parsers)
|
|
||||||
elements = append(elements, element)
|
elements = append(elements, element)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,26 +93,6 @@ func (d *choiceDefinition) commitType() CommitType {
|
|||||||
func (p *choiceParser) nodeName() string { return p.name }
|
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) setIncludedBy(includedBy parser, parsers *idSet) {
|
|
||||||
if parsers.has(p.id) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
p.includedBy = append(p.includedBy, includedBy)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *choiceParser) storeIncluded(c *context, from, to int) {
|
|
||||||
if !c.excluded(from, p.id) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.store.setMatch(from, p.id, to)
|
|
||||||
|
|
||||||
for _, includedBy := range p.includedBy {
|
|
||||||
includedBy.storeIncluded(c, from, to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *choiceParser) parse(t Trace, c *context) {
|
func (p *choiceParser) parse(t Trace, c *context) {
|
||||||
if p.commit&Documentation != 0 {
|
if p.commit&Documentation != 0 {
|
||||||
c.fail(c.offset)
|
c.fail(c.offset)
|
||||||
@ -140,7 +136,7 @@ func (p *choiceParser) parse(t Trace, c *context) {
|
|||||||
|
|
||||||
c.store.setMatch(from, p.id, to)
|
c.store.setMatch(from, p.id, to)
|
||||||
for _, includedBy := range p.includedBy {
|
for _, includedBy := range p.includedBy {
|
||||||
includedBy.storeIncluded(c, from, to)
|
c.store.setMatch(from, includedBy, to)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
44
parse.go
44
parse.go
@ -6,6 +6,8 @@ type definition interface {
|
|||||||
nodeName() string
|
nodeName() string
|
||||||
nodeID() int
|
nodeID() int
|
||||||
setID(int)
|
setID(int)
|
||||||
|
init(*registry) error
|
||||||
|
setIncludedBy(*registry, int, *idSet) error
|
||||||
parser(*registry, *idSet) (parser, error)
|
parser(*registry, *idSet) (parser, error)
|
||||||
commitType() CommitType
|
commitType() CommitType
|
||||||
// builder() builder
|
// builder() builder
|
||||||
@ -14,8 +16,6 @@ type definition interface {
|
|||||||
type parser interface {
|
type parser interface {
|
||||||
nodeName() string
|
nodeName() string
|
||||||
nodeID() int
|
nodeID() int
|
||||||
setIncludedBy(parser, *idSet)
|
|
||||||
storeIncluded(*context, int, int) // can be just an id set, taking what's excluded from the context
|
|
||||||
parse(Trace, *context)
|
parse(Trace, *context)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,6 +33,46 @@ func cannotIncludeParsers(name string) error {
|
|||||||
return fmt.Errorf("parser: %s cannot include other parsers", name)
|
return fmt.Errorf("parser: %s cannot include other parsers", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func intsContain(is []int, i int) bool {
|
||||||
|
for _, ii := range is {
|
||||||
|
if ii == i {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendIfMissing(is []int, i int) []int {
|
||||||
|
if intsContain(is, i) {
|
||||||
|
return is
|
||||||
|
}
|
||||||
|
|
||||||
|
return append(is, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setItemsIncludedBy(r *registry, items []string, includedBy int, parsers *idSet) error {
|
||||||
|
for _, item := range items {
|
||||||
|
di, ok := r.definition(item)
|
||||||
|
if !ok {
|
||||||
|
return ErrNoParsersDefined
|
||||||
|
}
|
||||||
|
|
||||||
|
di.setIncludedBy(r, includedBy, parsers)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func sequenceItemNames(items []SequenceItem) []string {
|
||||||
|
names := make([]string, len(items))
|
||||||
|
for i := range items {
|
||||||
|
names[i] = items[i].Name
|
||||||
|
}
|
||||||
|
|
||||||
|
return names
|
||||||
|
}
|
||||||
|
|
||||||
func parse(t Trace, p parser, c *context) (*Node, error) {
|
func parse(t Trace, p parser, c *context) (*Node, error) {
|
||||||
p.parse(t, c)
|
p.parse(t, c)
|
||||||
if c.readErr != nil {
|
if c.readErr != nil {
|
||||||
|
67
sequence.go
67
sequence.go
@ -5,6 +5,7 @@ type sequenceDefinition struct {
|
|||||||
id int
|
id int
|
||||||
commit CommitType
|
commit CommitType
|
||||||
items []SequenceItem
|
items []SequenceItem
|
||||||
|
includedBy []int
|
||||||
}
|
}
|
||||||
|
|
||||||
type sequenceParser struct {
|
type sequenceParser struct {
|
||||||
@ -13,7 +14,7 @@ type sequenceParser struct {
|
|||||||
commit CommitType
|
commit CommitType
|
||||||
items []parser
|
items []parser
|
||||||
ranges [][]int
|
ranges [][]int
|
||||||
includedBy []parser
|
includedBy []int
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSequence(name string, ct CommitType, items []SequenceItem) *sequenceDefinition {
|
func newSequence(name string, ct CommitType, items []SequenceItem) *sequenceDefinition {
|
||||||
@ -28,6 +29,42 @@ func (d *sequenceDefinition) nodeName() string { return d.name }
|
|||||||
func (d *sequenceDefinition) nodeID() int { return d.id }
|
func (d *sequenceDefinition) nodeID() int { return d.id }
|
||||||
func (d *sequenceDefinition) setID(id int) { d.id = id }
|
func (d *sequenceDefinition) setID(id int) { d.id = id }
|
||||||
|
|
||||||
|
func (d *sequenceDefinition) includeItems() bool {
|
||||||
|
return len(d.items) == 1 && d.items[0].Min == 1 && d.items[0].Max == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *sequenceDefinition) init(r *registry) error {
|
||||||
|
for _, item := range d.items {
|
||||||
|
if item.Min == 0 && item.Max == 0 {
|
||||||
|
item.Min, item.Max = 1, 1
|
||||||
|
} else if item.Max == 0 {
|
||||||
|
item.Max = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !d.includeItems() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
parsers := &idSet{}
|
||||||
|
parsers.set(d.id)
|
||||||
|
return setItemsIncludedBy(r, sequenceItemNames(d.items), d.id, parsers)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *sequenceDefinition) setIncludedBy(r *registry, includedBy int, parsers *idSet) error {
|
||||||
|
if parsers.has(d.id) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
d.includedBy = appendIfMissing(d.includedBy, includedBy)
|
||||||
|
if !d.includeItems() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
parsers.set(d.id)
|
||||||
|
return setItemsIncludedBy(r, sequenceItemNames(d.items), includedBy, parsers)
|
||||||
|
}
|
||||||
|
|
||||||
func (d *sequenceDefinition) parser(r *registry, parsers *idSet) (parser, error) {
|
func (d *sequenceDefinition) parser(r *registry, parsers *idSet) (parser, error) {
|
||||||
if parsers.has(d.id) {
|
if parsers.has(d.id) {
|
||||||
panic(cannotIncludeParsers(d.name))
|
panic(cannotIncludeParsers(d.name))
|
||||||
@ -42,6 +79,7 @@ func (d *sequenceDefinition) parser(r *registry, parsers *idSet) (parser, error)
|
|||||||
name: d.name,
|
name: d.name,
|
||||||
id: d.id,
|
id: d.id,
|
||||||
commit: d.commit,
|
commit: d.commit,
|
||||||
|
includedBy: d.includedBy,
|
||||||
}
|
}
|
||||||
|
|
||||||
r.setParser(sp)
|
r.setParser(sp)
|
||||||
@ -81,11 +119,6 @@ func (d *sequenceDefinition) parser(r *registry, parsers *idSet) (parser, error)
|
|||||||
ranges = append(ranges, []int{item.Min, item.Max})
|
ranges = append(ranges, []int{item.Min, item.Max})
|
||||||
}
|
}
|
||||||
|
|
||||||
// for single items, acts like a choice
|
|
||||||
if len(items) == 1 && ranges[0][0] == 1 && ranges[0][1] == 1 {
|
|
||||||
items[0].setIncludedBy(sp, parsers)
|
|
||||||
}
|
|
||||||
|
|
||||||
sp.items = items
|
sp.items = items
|
||||||
sp.ranges = ranges
|
sp.ranges = ranges
|
||||||
return sp, nil
|
return sp, nil
|
||||||
@ -98,26 +131,6 @@ func (d *sequenceDefinition) commitType() CommitType {
|
|||||||
func (p *sequenceParser) nodeName() string { return p.name }
|
func (p *sequenceParser) nodeName() string { return p.name }
|
||||||
func (p *sequenceParser) nodeID() int { return p.id }
|
func (p *sequenceParser) nodeID() int { return p.id }
|
||||||
|
|
||||||
func (p *sequenceParser) setIncludedBy(includedBy parser, parsers *idSet) {
|
|
||||||
if parsers.has(p.id) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
p.includedBy = append(p.includedBy, includedBy)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *sequenceParser) storeIncluded(c *context, from, to int) {
|
|
||||||
if !c.excluded(from, p.id) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.store.setMatch(from, p.id, to)
|
|
||||||
|
|
||||||
for _, includedBy := range p.includedBy {
|
|
||||||
includedBy.storeIncluded(c, from, to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *sequenceParser) parse(t Trace, c *context) {
|
func (p *sequenceParser) parse(t Trace, c *context) {
|
||||||
if p.commit&Documentation != 0 {
|
if p.commit&Documentation != 0 {
|
||||||
c.fail(c.offset)
|
c.fail(c.offset)
|
||||||
@ -169,7 +182,7 @@ func (p *sequenceParser) parse(t Trace, c *context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, includedBy := range p.includedBy {
|
for _, includedBy := range p.includedBy {
|
||||||
includedBy.storeIncluded(c, from, to)
|
c.store.setMatch(from, includedBy, to)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.store.setMatch(from, p.id, to)
|
c.store.setMatch(from, p.id, to)
|
||||||
|
@ -143,6 +143,10 @@ func (s *Syntax) Init() error {
|
|||||||
return ErrRootAlias
|
return ErrRootAlias
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, p := range s.registry.definitions {
|
||||||
|
p.init(s.registry)
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
s.parser, err = s.root.parser(s.registry, &idSet{})
|
s.parser, err = s.root.parser(s.registry, &idSet{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user