add builder definitions

This commit is contained in:
Arpad Ryszka 2017-07-29 16:25:17 +02:00
parent f6761a7e3d
commit 1e7c0e8c28
7 changed files with 71 additions and 23 deletions

27
char.go
View File

@ -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
}

View File

@ -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
}

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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
}

View File

@ -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)
} }

View File

@ -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
} }
} }