add builder definitions
This commit is contained in:
parent
f6761a7e3d
commit
1e7c0e8c28
27
char.go
27
char.go
@ -3,7 +3,6 @@ package treerack
|
|||||||
type charParser struct {
|
type charParser struct {
|
||||||
name string
|
name string
|
||||||
id int
|
id int
|
||||||
commit CommitType
|
|
||||||
not bool
|
not bool
|
||||||
chars []rune
|
chars []rune
|
||||||
ranges [][]rune
|
ranges [][]rune
|
||||||
@ -12,14 +11,12 @@ type charParser struct {
|
|||||||
|
|
||||||
func newChar(
|
func newChar(
|
||||||
name string,
|
name string,
|
||||||
ct CommitType,
|
|
||||||
not bool,
|
not bool,
|
||||||
chars []rune,
|
chars []rune,
|
||||||
ranges [][]rune,
|
ranges [][]rune,
|
||||||
) *charParser {
|
) *charParser {
|
||||||
return &charParser{
|
return &charParser{
|
||||||
name: name,
|
name: name,
|
||||||
commit: ct,
|
|
||||||
not: not,
|
not: not,
|
||||||
chars: chars,
|
chars: chars,
|
||||||
ranges: ranges,
|
ranges: ranges,
|
||||||
@ -29,6 +26,7 @@ func newChar(
|
|||||||
func (p *charParser) nodeName() string { return p.name }
|
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) commitType() CommitType { return Alias }
|
||||||
|
|
||||||
func (p *charParser) init(r *registry) error { return nil }
|
func (p *charParser) init(r *registry) error { return nil }
|
||||||
|
|
||||||
@ -50,12 +48,8 @@ func (p *charParser) parser(r *registry, parsers *idSet) (parser, error) {
|
|||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *charParser) commitType() CommitType {
|
func (p *charParser) builder() builder {
|
||||||
return p.commit
|
return p
|
||||||
}
|
|
||||||
|
|
||||||
func (p *charParser) storeIncluded(*context, int, int) {
|
|
||||||
panic(cannotIncludeParsers(p.name))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *charParser) match(t rune) bool {
|
func (p *charParser) match(t rune) bool {
|
||||||
@ -85,3 +79,18 @@ func (p *charParser) parse(t Trace, c *context) {
|
|||||||
c.store.setMatch(c.offset, includedBy, c.offset+1)
|
c.store.setMatch(c.offset, includedBy, c.offset+1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *charParser) build(c *context) ([]*Node, bool) {
|
||||||
|
t, ok := c.token()
|
||||||
|
if !ok {
|
||||||
|
panic("damaged parser context")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !p.match(t) {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// always alias
|
||||||
|
c.offset++
|
||||||
|
return nil, true
|
||||||
|
}
|
||||||
|
22
choice.go
22
choice.go
@ -16,6 +16,12 @@ type choiceParser struct {
|
|||||||
includedBy []int
|
includedBy []int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type choiceBuilder struct {
|
||||||
|
name string
|
||||||
|
id int
|
||||||
|
commit CommitType
|
||||||
|
}
|
||||||
|
|
||||||
func newChoice(name string, ct CommitType, elements []string) *choiceDefinition {
|
func newChoice(name string, ct CommitType, elements []string) *choiceDefinition {
|
||||||
return &choiceDefinition{
|
return &choiceDefinition{
|
||||||
name: name,
|
name: name,
|
||||||
@ -27,6 +33,7 @@ func newChoice(name string, ct CommitType, elements []string) *choiceDefinition
|
|||||||
func (d *choiceDefinition) nodeName() string { return d.name }
|
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) commitType() CommitType { return d.commit }
|
||||||
|
|
||||||
func (d *choiceDefinition) init(r *registry) error {
|
func (d *choiceDefinition) init(r *registry) error {
|
||||||
parsers := &idSet{}
|
parsers := &idSet{}
|
||||||
@ -44,6 +51,10 @@ func (d *choiceDefinition) setIncludedBy(r *registry, includedBy int, parsers *i
|
|||||||
return setItemsIncludedBy(r, d.elements, includedBy, parsers)
|
return setItemsIncludedBy(r, d.elements, includedBy, parsers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// - it may be possible to initialize the parsers non-recursively
|
||||||
|
// - maybe the whole definition, parser and builder can be united
|
||||||
|
|
||||||
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 {
|
||||||
@ -86,8 +97,8 @@ func (d *choiceDefinition) parser(r *registry, parsers *idSet) (parser, error) {
|
|||||||
return cp, nil
|
return cp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *choiceDefinition) commitType() CommitType {
|
func (d *choiceDefinition) builder() builder {
|
||||||
return d.commit
|
return &choiceBuilder{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *choiceParser) nodeName() string { return p.name }
|
func (p *choiceParser) nodeName() string { return p.name }
|
||||||
@ -155,3 +166,10 @@ func (p *choiceParser) parse(t Trace, c *context) {
|
|||||||
c.fail(from)
|
c.fail(from)
|
||||||
c.include(from, p.id)
|
c.include(from, p.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *choiceBuilder) nodeName() string { return b.name }
|
||||||
|
func (b *choiceBuilder) nodeID() int { return b.id }
|
||||||
|
|
||||||
|
func (b *choiceBuilder) build(*context) ([]*Node, bool) {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
10
context.go
10
context.go
@ -127,10 +127,10 @@ func (c *context) fail(offset int) {
|
|||||||
c.match = false
|
c.match = false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) finalize() error {
|
func (c *context) finalize(root parser) error {
|
||||||
return ErrNotImplemented
|
rootID := root.nodeID()
|
||||||
|
to, match, found := c.store.getMatch(0, rootID)
|
||||||
if c.node.To < c.readOffset {
|
if !found || !match || to < c.readOffset {
|
||||||
return ErrUnexpectedCharacter
|
return ErrUnexpectedCharacter
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,6 +145,8 @@ func (c *context) finalize() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ErrNotImplemented
|
||||||
|
|
||||||
c.node.commit(c.tokens)
|
c.node.commit(c.tokens)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
8
parse.go
8
parse.go
@ -5,12 +5,12 @@ import "fmt"
|
|||||||
type definition interface {
|
type definition interface {
|
||||||
nodeName() string
|
nodeName() string
|
||||||
nodeID() int
|
nodeID() int
|
||||||
|
commitType() CommitType
|
||||||
setID(int)
|
setID(int)
|
||||||
init(*registry) error
|
init(*registry) error
|
||||||
setIncludedBy(*registry, int, *idSet) error
|
setIncludedBy(*registry, int, *idSet) error
|
||||||
parser(*registry, *idSet) (parser, error)
|
parser(*registry, *idSet) (parser, error)
|
||||||
commitType() CommitType
|
builder() builder
|
||||||
// builder() builder
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type parser interface {
|
type parser interface {
|
||||||
@ -22,7 +22,7 @@ type parser interface {
|
|||||||
type builder interface {
|
type builder interface {
|
||||||
nodeName() string
|
nodeName() string
|
||||||
nodeID() int
|
nodeID() int
|
||||||
build(*context) *Node
|
build(*context) ([]*Node, bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parserNotFound(name string) error {
|
func parserNotFound(name string) error {
|
||||||
@ -83,7 +83,7 @@ func parse(t Trace, p parser, c *context) (*Node, error) {
|
|||||||
return nil, ErrInvalidInput
|
return nil, ErrInvalidInput
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.finalize(); err != nil {
|
if err := c.finalize(p); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
19
sequence.go
19
sequence.go
@ -17,6 +17,12 @@ type sequenceParser struct {
|
|||||||
includedBy []int
|
includedBy []int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sequenceBuilder struct {
|
||||||
|
name string
|
||||||
|
id int
|
||||||
|
commit CommitType
|
||||||
|
}
|
||||||
|
|
||||||
func newSequence(name string, ct CommitType, items []SequenceItem) *sequenceDefinition {
|
func newSequence(name string, ct CommitType, items []SequenceItem) *sequenceDefinition {
|
||||||
return &sequenceDefinition{
|
return &sequenceDefinition{
|
||||||
name: name,
|
name: name,
|
||||||
@ -28,6 +34,7 @@ func newSequence(name string, ct CommitType, items []SequenceItem) *sequenceDefi
|
|||||||
func (d *sequenceDefinition) nodeName() string { return d.name }
|
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) commitType() CommitType { return d.commit }
|
||||||
|
|
||||||
func (d *sequenceDefinition) includeItems() bool {
|
func (d *sequenceDefinition) includeItems() bool {
|
||||||
return len(d.items) == 1 && d.items[0].Min == 1 && d.items[0].Max == 1
|
return len(d.items) == 1 && d.items[0].Min == 1 && d.items[0].Max == 1
|
||||||
@ -66,6 +73,7 @@ func (d *sequenceDefinition) setIncludedBy(r *registry, includedBy int, parsers
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *sequenceDefinition) parser(r *registry, parsers *idSet) (parser, error) {
|
func (d *sequenceDefinition) parser(r *registry, parsers *idSet) (parser, error) {
|
||||||
|
// TODO: what is this for? test with sequence containing a sequence through a choice
|
||||||
if parsers.has(d.id) {
|
if parsers.has(d.id) {
|
||||||
panic(cannotIncludeParsers(d.name))
|
panic(cannotIncludeParsers(d.name))
|
||||||
}
|
}
|
||||||
@ -124,8 +132,8 @@ func (d *sequenceDefinition) parser(r *registry, parsers *idSet) (parser, error)
|
|||||||
return sp, nil
|
return sp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *sequenceDefinition) commitType() CommitType {
|
func (d *sequenceDefinition) builder() builder {
|
||||||
return d.commit
|
return &sequenceBuilder{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *sequenceParser) nodeName() string { return p.name }
|
func (p *sequenceParser) nodeName() string { return p.name }
|
||||||
@ -189,3 +197,10 @@ func (p *sequenceParser) parse(t Trace, c *context) {
|
|||||||
c.success(to)
|
c.success(to)
|
||||||
c.include(from, p.id)
|
c.include(from, p.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *sequenceBuilder) nodeName() string { return b.name }
|
||||||
|
func (b *sequenceBuilder) nodeID() int { return b.id }
|
||||||
|
|
||||||
|
func (b *sequenceBuilder) build(*context) ([]*Node, bool) {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
4
store.go
4
store.go
@ -58,6 +58,10 @@ func (s *store) ensureOffset(offset int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *store) setMatch(offset, id, to int) {
|
func (s *store) setMatch(offset, id, to int) {
|
||||||
|
if toe, match, ok := s.getMatch(offset, id); ok && match && toe == to {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
s.ensureOffset(offset)
|
s.ensureOffset(offset)
|
||||||
s.match[offset] = append(s.match[offset], id, to)
|
s.match[offset] = append(s.match[offset], id, to)
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ func childName(name string, childIndex int) string {
|
|||||||
|
|
||||||
func (s *Syntax) Class(name string, ct CommitType, not bool, chars []rune, ranges [][]rune) error {
|
func (s *Syntax) Class(name string, ct CommitType, not bool, chars []rune, ranges [][]rune) error {
|
||||||
cname := childName(name, 0)
|
cname := childName(name, 0)
|
||||||
if err := s.register(newChar(cname, Alias, not, chars, ranges)); err != nil {
|
if err := s.register(newChar(cname, not, chars, ranges)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ func (s *Syntax) CharSequence(name string, ct CommitType, chars []rune) error {
|
|||||||
for i, ci := range chars {
|
for i, ci := range chars {
|
||||||
ref := childName(name, i)
|
ref := childName(name, i)
|
||||||
refs = append(refs, ref)
|
refs = append(refs, ref)
|
||||||
if err := s.register(newChar(ref, Alias, false, []rune{ci}, nil)); err != nil {
|
if err := s.register(newChar(ref, false, []rune{ci}, nil)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user