diff --git a/char.go b/char.go index 7804fa9..2a4e95f 100644 --- a/char.go +++ b/char.go @@ -29,6 +29,7 @@ func (p *charParser) nodeID() int { return p.id } func (p *charParser) setID(id int) { p.id = id } func (p *charParser) commitType() CommitType { return Alias } func (p *charParser) setCommitType(ct CommitType) {} +func (p *charParser) preinit() {} func (p *charParser) validate(*registry) error { return nil } func (p *charParser) init(*registry) {} diff --git a/choice.go b/choice.go index 84acb47..077a1c8 100644 --- a/choice.go +++ b/choice.go @@ -42,6 +42,7 @@ func (d *choiceDefinition) nodeID() int { return d.id } func (d *choiceDefinition) setID(id int) { d.id = id } func (d *choiceDefinition) commitType() CommitType { return d.commit } func (d *choiceDefinition) setCommitType(ct CommitType) { d.commit = ct } +func (d *choiceDefinition) preinit() {} func (d *choiceDefinition) validate(r *registry) error { if d.validated { diff --git a/sequence.go b/sequence.go index d88a397..6d50f20 100644 --- a/sequence.go +++ b/sequence.go @@ -49,6 +49,29 @@ func (d *sequenceDefinition) setID(id int) { d.id = id } func (d *sequenceDefinition) commitType() CommitType { return d.commit } func (d *sequenceDefinition) setCommitType(ct CommitType) { d.commit = ct } +func (d *sequenceDefinition) initRanges() { + for i, item := range d.items { + if item.Min == 0 && item.Max == 0 { + item.Min, item.Max = 1, 1 + } else { + if item.Min <= 0 { + item.Min = 0 + } + + if item.Max <= 0 { + item.Max = -1 + } + } + + d.items[i] = item + d.ranges = append(d.ranges, []int{item.Min, item.Max}) + } +} + +func (d *sequenceDefinition) preinit() { + d.initRanges() +} + func (d *sequenceDefinition) validate(r *registry) error { if d.validated { return nil @@ -82,18 +105,6 @@ func (d *sequenceDefinition) createBuilder() { } } -func (d *sequenceDefinition) initRanges() { - 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 - } - - d.ranges = append(d.ranges, []int{item.Min, item.Max}) - } -} - func (d *sequenceDefinition) initItems(r *registry) { allChars := true for _, item := range d.items { @@ -181,10 +192,6 @@ func (p *sequenceParser) parse(c *context) { var parsed bool for itemIndex < len(p.items) { - // TODO: - // - is it ok to parse before max range check? what if max=0 - // - validate, normalize and document max=0 - // TODO: test this f(g()) p.items[itemIndex].parse(c) if !c.matchLast { @@ -210,8 +217,7 @@ func (p *sequenceParser) parse(c *context) { to = c.offset - // TODO: max cannot be 0 - if !parsed || p.ranges[itemIndex][1] >= 0 && currentCount == p.ranges[itemIndex][1] { + if !parsed || p.ranges[itemIndex][1] > 0 && currentCount == p.ranges[itemIndex][1] { itemIndex++ currentCount = 0 } @@ -287,7 +293,7 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) { nodes = append(nodes, n...) currentCount++ - if b.ranges[itemIndex][1] >= 0 && currentCount == b.ranges[itemIndex][1] { + if b.ranges[itemIndex][1] > 0 && currentCount == b.ranges[itemIndex][1] { itemIndex++ currentCount = 0 } diff --git a/syntax.go b/syntax.go index 3545de1..7f29b19 100644 --- a/syntax.go +++ b/syntax.go @@ -18,9 +18,12 @@ const ( Root ) +// if min=0&&max=0, it means min=1,max=1 +// else if max<=0, it means no max +// else if min<=0, it means no min type SequenceItem struct { Name string - Min, Max int // 0,0 considered as 1,1, x,0 considered as x,-1 + Min, Max int } type Syntax struct { @@ -40,6 +43,7 @@ type definition interface { commitType() CommitType setCommitType(CommitType) setID(int) + preinit() validate(*registry) error init(*registry) addGeneralization(int) @@ -220,6 +224,8 @@ func (s *Syntax) CharSequence(name string, ct CommitType, chars []rune) error { } func (s *Syntax) sequence(name string, ct CommitType, items ...SequenceItem) error { + citems := make([]SequenceItem, len(items)) + copy(citems, items) return s.register(newSequence(name, ct, items)) } @@ -251,8 +257,6 @@ func (s *Syntax) Read(r io.Reader) error { return ErrNotImplemented } -// TODO: why normalization failed? - func (s *Syntax) Init() error { if s.initFailed { return ErrInitFailed @@ -275,6 +279,9 @@ func (s *Syntax) Init() error { } defs := s.registry.getDefinitions() + for i := range defs { + defs[i].preinit() + } if hasWhitespace(defs) { defs, s.root = applyWhitespace(defs) diff --git a/whitespace.go b/whitespace.go index a85b7da..384255e 100644 --- a/whitespace.go +++ b/whitespace.go @@ -66,8 +66,7 @@ func applyWhitespaceToSeq(s *sequenceDefinition) []definition { whitespace := SequenceItem{Name: whitespaceName, Min: 0, Max: -1} for i, item := range s.items { - // TODO: there should not be max=0 - if item.Max >= 0 && item.Max <= 1 { + if item.Max == 1 { if i > 0 { items = append(items, whitespace) }