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 {
|
||||
name string
|
||||
id int
|
||||
commit CommitType
|
||||
not bool
|
||||
chars []rune
|
||||
ranges [][]rune
|
||||
@ -12,14 +11,12 @@ type charParser struct {
|
||||
|
||||
func newChar(
|
||||
name string,
|
||||
ct CommitType,
|
||||
not bool,
|
||||
chars []rune,
|
||||
ranges [][]rune,
|
||||
) *charParser {
|
||||
return &charParser{
|
||||
name: name,
|
||||
commit: ct,
|
||||
not: not,
|
||||
chars: chars,
|
||||
ranges: ranges,
|
||||
@ -29,6 +26,7 @@ func newChar(
|
||||
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) commitType() CommitType { return Alias }
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
func (p *charParser) commitType() CommitType {
|
||||
return p.commit
|
||||
}
|
||||
|
||||
func (p *charParser) storeIncluded(*context, int, int) {
|
||||
panic(cannotIncludeParsers(p.name))
|
||||
func (p *charParser) builder() builder {
|
||||
return p
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
type choiceBuilder struct {
|
||||
name string
|
||||
id int
|
||||
commit CommitType
|
||||
}
|
||||
|
||||
func newChoice(name string, ct CommitType, elements []string) *choiceDefinition {
|
||||
return &choiceDefinition{
|
||||
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) 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) init(r *registry) error {
|
||||
parsers := &idSet{}
|
||||
@ -44,6 +51,10 @@ func (d *choiceDefinition) setIncludedBy(r *registry, includedBy int, parsers *i
|
||||
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) {
|
||||
p, ok := r.parser(d.name)
|
||||
if ok {
|
||||
@ -86,8 +97,8 @@ func (d *choiceDefinition) parser(r *registry, parsers *idSet) (parser, error) {
|
||||
return cp, nil
|
||||
}
|
||||
|
||||
func (d *choiceDefinition) commitType() CommitType {
|
||||
return d.commit
|
||||
func (d *choiceDefinition) builder() builder {
|
||||
return &choiceBuilder{}
|
||||
}
|
||||
|
||||
func (p *choiceParser) nodeName() string { return p.name }
|
||||
@ -155,3 +166,10 @@ func (p *choiceParser) parse(t Trace, c *context) {
|
||||
c.fail(from)
|
||||
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
|
||||
}
|
||||
|
||||
func (c *context) finalize() error {
|
||||
return ErrNotImplemented
|
||||
|
||||
if c.node.To < c.readOffset {
|
||||
func (c *context) finalize(root parser) error {
|
||||
rootID := root.nodeID()
|
||||
to, match, found := c.store.getMatch(0, rootID)
|
||||
if !found || !match || to < c.readOffset {
|
||||
return ErrUnexpectedCharacter
|
||||
}
|
||||
|
||||
@ -145,6 +145,8 @@ func (c *context) finalize() error {
|
||||
}
|
||||
}
|
||||
|
||||
return ErrNotImplemented
|
||||
|
||||
c.node.commit(c.tokens)
|
||||
return nil
|
||||
}
|
||||
|
8
parse.go
8
parse.go
@ -5,12 +5,12 @@ import "fmt"
|
||||
type definition interface {
|
||||
nodeName() string
|
||||
nodeID() int
|
||||
commitType() CommitType
|
||||
setID(int)
|
||||
init(*registry) error
|
||||
setIncludedBy(*registry, int, *idSet) error
|
||||
parser(*registry, *idSet) (parser, error)
|
||||
commitType() CommitType
|
||||
// builder() builder
|
||||
builder() builder
|
||||
}
|
||||
|
||||
type parser interface {
|
||||
@ -22,7 +22,7 @@ type parser interface {
|
||||
type builder interface {
|
||||
nodeName() string
|
||||
nodeID() int
|
||||
build(*context) *Node
|
||||
build(*context) ([]*Node, bool)
|
||||
}
|
||||
|
||||
func parserNotFound(name string) error {
|
||||
@ -83,7 +83,7 @@ func parse(t Trace, p parser, c *context) (*Node, error) {
|
||||
return nil, ErrInvalidInput
|
||||
}
|
||||
|
||||
if err := c.finalize(); err != nil {
|
||||
if err := c.finalize(p); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
19
sequence.go
19
sequence.go
@ -17,6 +17,12 @@ type sequenceParser struct {
|
||||
includedBy []int
|
||||
}
|
||||
|
||||
type sequenceBuilder struct {
|
||||
name string
|
||||
id int
|
||||
commit CommitType
|
||||
}
|
||||
|
||||
func newSequence(name string, ct CommitType, items []SequenceItem) *sequenceDefinition {
|
||||
return &sequenceDefinition{
|
||||
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) nodeID() int { return d.id }
|
||||
func (d *sequenceDefinition) setID(id int) { d.id = id }
|
||||
func (d *sequenceDefinition) commitType() CommitType { return d.commit }
|
||||
|
||||
func (d *sequenceDefinition) includeItems() bool {
|
||||
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) {
|
||||
// TODO: what is this for? test with sequence containing a sequence through a choice
|
||||
if parsers.has(d.id) {
|
||||
panic(cannotIncludeParsers(d.name))
|
||||
}
|
||||
@ -124,8 +132,8 @@ func (d *sequenceDefinition) parser(r *registry, parsers *idSet) (parser, error)
|
||||
return sp, nil
|
||||
}
|
||||
|
||||
func (d *sequenceDefinition) commitType() CommitType {
|
||||
return d.commit
|
||||
func (d *sequenceDefinition) builder() builder {
|
||||
return &sequenceBuilder{}
|
||||
}
|
||||
|
||||
func (p *sequenceParser) nodeName() string { return p.name }
|
||||
@ -189,3 +197,10 @@ func (p *sequenceParser) parse(t Trace, c *context) {
|
||||
c.success(to)
|
||||
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) {
|
||||
if toe, match, ok := s.getMatch(offset, id); ok && match && toe == to {
|
||||
return
|
||||
}
|
||||
|
||||
s.ensureOffset(offset)
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
||||
@ -100,7 +100,7 @@ func (s *Syntax) CharSequence(name string, ct CommitType, chars []rune) error {
|
||||
for i, ci := range chars {
|
||||
ref := childName(name, i)
|
||||
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
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user