diff --git a/boot.go b/boot.go index fd31a15..a9e1b42 100644 --- a/boot.go +++ b/boot.go @@ -29,71 +29,6 @@ func stringToCommitType(s string) CommitType { } } -func parseClass(class []rune) (not bool, chars []rune, ranges [][]rune, err error) { - if class[0] == '^' { - not = true - class = class[1:] - } - - for { - if len(class) == 0 { - return - } - - var c0 rune - c0, class = class[0], class[1:] - - /* - this doesn't happen: - switch c0 { - case '[', ']', '^', '-': - err = errInvalidDefinition - return - } - */ - - if c0 == '\\' { - /* - this doesn't happen: - if len(class) == 0 { - err = errInvalidDefinition - return - } - */ - - c0, class = unescapeChar(class[0]), class[1:] - } - - if len(class) < 2 || class[0] != '-' { - chars = append(chars, c0) - continue - } - - var c1 rune - c1, class = class[1], class[2:] - - /* - this doesn't happen: - switch c1 { - case '[', ']', '^', '-': - err = errInvalidDefinition - return - } - - if c1 == '\\' { - if len(class) == 0 { - err = errInvalidDefinition - return - } - - c1, class = unescapeChar(class[0]), class[1:] - } - */ - - ranges = append(ranges, []rune{c0, c1}) - } -} - func defineBootAnything(s *Syntax, d []string) error { ct := stringToCommitType(d[2]) return s.anyChar(d[1], ct) @@ -233,6 +168,7 @@ func createBoot() (*Syntax, error) { func bootSyntax() (*Syntax, error) { /* never fails: + b, err := createBoot() if err != nil { return nil, err diff --git a/char.go b/char.go index ce8a6eb..c5959f5 100644 --- a/char.go +++ b/char.go @@ -73,7 +73,7 @@ func (p *charParser) format(_ *registry, f formatFlags) string { return string(s) } -func matchChars(chars []rune, ranges [][]rune, not bool, char rune) bool { +func matchChar(chars []rune, ranges [][]rune, not bool, char rune) bool { for _, ci := range chars { if ci == char { return !not @@ -90,7 +90,7 @@ func matchChars(chars []rune, ranges [][]rune, not bool, char rune) bool { } func (p *charParser) match(t rune) bool { - return matchChars(p.chars, p.ranges, p.not, t) + return matchChar(p.chars, p.ranges, p.not, t) } func (p *charParser) parse(c *context) { diff --git a/define.go b/define.go index e46cc16..737c3bf 100644 --- a/define.go +++ b/define.go @@ -189,7 +189,7 @@ func defineExpression(s *Syntax, name string, ct CommitType, expression *Node) e return err } -func defineDefinition(s *Syntax, n *Node) error { +func addDefinition(s *Syntax, n *Node) error { return defineExpression( s, n.Nodes[0].Text(), @@ -198,11 +198,11 @@ func defineDefinition(s *Syntax, n *Node) error { ) } -func define(s *Syntax, n *Node) error { - n = dropComments(n) +func define(s *Syntax, syntaxTree *Node) error { + syntaxTree = dropComments(syntaxTree) - for _, ni := range n.Nodes { - if err := defineDefinition(s, ni); err != nil { + for _, n := range syntaxTree.Nodes { + if err := addDefinition(s, n); err != nil { return err } } diff --git a/errors_test.go b/errors_test.go index a98ea97..bde940f 100644 --- a/errors_test.go +++ b/errors_test.go @@ -351,3 +351,11 @@ func TestFailPass(t *testing.T) { }, }}) } + +func TestFailPassRoot(t *testing.T) { + const syntax = `foo:failpass = "foo"` + _, err := openSyntaxString(syntax) + if err == nil { + t.Error("failed to fail") + } +} diff --git a/registry.go b/registry.go index e420dad..4a38f69 100644 --- a/registry.go +++ b/registry.go @@ -2,15 +2,11 @@ package treerack type registry struct { idSeed int - ids map[string]int - names map[int]string definitions map[string]definition } func newRegistry(defs ...definition) *registry { r := ®istry{ - ids: make(map[string]int), - names: make(map[int]string), definitions: make(map[string]definition), } @@ -34,8 +30,6 @@ func (r *registry) setDefinition(d definition) error { r.idSeed++ id := r.idSeed d.setID(id) - r.ids[d.nodeName()] = id - r.names[id] = d.nodeName() r.definitions[d.nodeName()] = d return nil diff --git a/syntax.go b/syntax.go index 9428272..f022058 100644 --- a/syntax.go +++ b/syntax.go @@ -115,6 +115,7 @@ var ( ErrInvalidSyntax = errors.New("invalid syntax") ErrRootAlias = errors.New("root node cannot be an alias") ErrRootWhitespace = errors.New("root node cannot be a whitespace") + ErrRootFailPass = errors.New("root node cannot pass failing definition") ErrNotImplemented = errors.New("not implemented") ErrMultipleRoots = errors.New("multiple roots") ErrInvalidSymbolName = errors.New("invalid symbol name") @@ -130,6 +131,71 @@ func parserNotFound(name string) error { const symbolChars = "^\\\\ \\n\\t\\b\\f\\r\\v/.\\[\\]\\\"{}\\^+*?|():=;" +func parseClass(class []rune) (not bool, chars []rune, ranges [][]rune, err error) { + if class[0] == '^' { + not = true + class = class[1:] + } + + for { + if len(class) == 0 { + return + } + + var c0 rune + c0, class = class[0], class[1:] + + /* + this doesn't happen: + switch c0 { + case '[', ']', '^', '-': + err = errInvalidDefinition + return + } + */ + + if c0 == '\\' { + /* + this doesn't happen: + if len(class) == 0 { + err = errInvalidDefinition + return + } + */ + + c0, class = unescapeChar(class[0]), class[1:] + } + + if len(class) < 2 || class[0] != '-' { + chars = append(chars, c0) + continue + } + + var c1 rune + c1, class = class[1], class[2:] + + /* + this doesn't happen: + switch c1 { + case '[', ']', '^', '-': + err = errInvalidDefinition + return + } + + if c1 == '\\' { + if len(class) == 0 { + err = errInvalidDefinition + return + } + + c1, class = unescapeChar(class[0]), class[1:] + } + */ + + ranges = append(ranges, []rune{c0, c1}) + } +} + func parseSymbolChars(c []rune) []rune { _, chars, _, _ := parseClass(c) return chars @@ -140,7 +206,7 @@ var symbolCharRunes = parseSymbolChars([]rune(symbolChars)) func isValidSymbol(n string) bool { runes := []rune(n) for _, r := range runes { - if !matchChars(symbolCharRunes, nil, true, r) { + if !matchChar(symbolCharRunes, nil, true, r) { return false } } @@ -275,8 +341,6 @@ 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)) } @@ -329,6 +393,10 @@ func (s *Syntax) Init() error { return ErrRootWhitespace } + if s.root.commitType()&FailPass != 0 { + return ErrRootFailPass + } + defs := s.registry.getDefinitions() for i := range defs { defs[i].preinit()