refactore included

This commit is contained in:
Arpad Ryszka 2017-07-27 01:48:16 +02:00
parent 507299f318
commit 72c8418e45
5 changed files with 129 additions and 77 deletions

19
char.go
View File

@ -7,7 +7,7 @@ type charParser struct {
not bool
chars []rune
ranges [][]rune
includedBy []parser
includedBy []int
}
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) 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) {
if parsers.has(p.id) {
panic(cannotIncludeParsers(p.name))
@ -47,14 +54,6 @@ func (p *charParser) commitType() CommitType {
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) {
panic(cannotIncludeParsers(p.name))
}
@ -83,6 +82,6 @@ func (p *charParser) parse(t Trace, c *context) {
c.success(c.offset + 1)
for _, includedBy := range p.includedBy {
includedBy.storeIncluded(c, c.offset, c.offset+1)
c.store.setMatch(c.offset, includedBy, c.offset+1)
}
}

View File

@ -1,10 +1,11 @@
package treerack
type choiceDefinition struct {
name string
id int
commit CommitType
elements []string
name string
id int
commit CommitType
elements []string
includedBy []int
}
type choiceParser struct {
@ -12,7 +13,7 @@ type choiceParser struct {
id int
commit CommitType
elements []parser
includedBy []parser
includedBy []int
}
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) 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) {
p, ok := r.parser(d.name)
if ok {
@ -34,9 +51,10 @@ func (d *choiceDefinition) parser(r *registry, parsers *idSet) (parser, error) {
}
cp := &choiceParser{
name: d.name,
id: d.id,
commit: d.commit,
name: d.name,
id: d.id,
commit: d.commit,
includedBy: d.includedBy,
}
r.setParser(cp)
@ -48,7 +66,6 @@ func (d *choiceDefinition) parser(r *registry, parsers *idSet) (parser, error) {
element, ok := r.parser(e)
if ok {
elements = append(elements, element)
element.setIncludedBy(cp, parsers)
continue
}
@ -62,7 +79,6 @@ func (d *choiceDefinition) parser(r *registry, parsers *idSet) (parser, error) {
return nil, err
}
element.setIncludedBy(cp, parsers)
elements = append(elements, element)
}
@ -77,26 +93,6 @@ func (d *choiceDefinition) commitType() CommitType {
func (p *choiceParser) nodeName() string { return p.name }
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) {
if p.commit&Documentation != 0 {
c.fail(c.offset)
@ -140,7 +136,7 @@ func (p *choiceParser) parse(t Trace, c *context) {
c.store.setMatch(from, p.id, to)
for _, includedBy := range p.includedBy {
includedBy.storeIncluded(c, from, to)
c.store.setMatch(from, includedBy, to)
}
}

View File

@ -6,6 +6,8 @@ type definition interface {
nodeName() string
nodeID() int
setID(int)
init(*registry) error
setIncludedBy(*registry, int, *idSet) error
parser(*registry, *idSet) (parser, error)
commitType() CommitType
// builder() builder
@ -14,8 +16,6 @@ type definition interface {
type parser interface {
nodeName() string
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)
}
@ -33,6 +33,46 @@ func cannotIncludeParsers(name string) error {
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) {
p.parse(t, c)
if c.readErr != nil {

View File

@ -1,10 +1,11 @@
package treerack
type sequenceDefinition struct {
name string
id int
commit CommitType
items []SequenceItem
name string
id int
commit CommitType
items []SequenceItem
includedBy []int
}
type sequenceParser struct {
@ -13,7 +14,7 @@ type sequenceParser struct {
commit CommitType
items []parser
ranges [][]int
includedBy []parser
includedBy []int
}
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) 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) {
if parsers.has(d.id) {
panic(cannotIncludeParsers(d.name))
@ -39,9 +76,10 @@ func (d *sequenceDefinition) parser(r *registry, parsers *idSet) (parser, error)
}
sp := &sequenceParser{
name: d.name,
id: d.id,
commit: d.commit,
name: d.name,
id: d.id,
commit: d.commit,
includedBy: d.includedBy,
}
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})
}
// 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.ranges = ranges
return sp, nil
@ -98,26 +131,6 @@ func (d *sequenceDefinition) commitType() CommitType {
func (p *sequenceParser) nodeName() string { return p.name }
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) {
if p.commit&Documentation != 0 {
c.fail(c.offset)
@ -169,7 +182,7 @@ func (p *sequenceParser) parse(t Trace, c *context) {
}
for _, includedBy := range p.includedBy {
includedBy.storeIncluded(c, from, to)
c.store.setMatch(from, includedBy, to)
}
c.store.setMatch(from, p.id, to)

View File

@ -143,6 +143,10 @@ func (s *Syntax) Init() error {
return ErrRootAlias
}
for _, p := range s.registry.definitions {
p.init(s.registry)
}
var err error
s.parser, err = s.root.parser(s.registry, &idSet{})
if err != nil {