treerack/whitespace.go

188 lines
3.8 KiB
Go
Raw Normal View History

2017-10-28 22:54:15 +02:00
package treerack
2017-10-28 23:41:23 +02:00
import (
"fmt"
2017-10-29 01:14:31 +02:00
"strconv"
2017-10-28 23:41:23 +02:00
"strings"
)
2017-10-28 22:54:15 +02:00
const whitespaceName = ":ws"
func brokenRegistryError(err error) error {
return fmt.Errorf("broken registry: %v", err)
}
2017-11-01 02:43:46 +01:00
func splitWhitespaceDefs(defs []definition) ([]definition, []definition) {
2017-10-28 22:54:15 +02:00
var whitespaceDefs, nonWhitespaceDefs []definition
2017-11-01 02:43:46 +01:00
for _, def := range defs {
2017-10-28 22:54:15 +02:00
if def.commitType()&Whitespace != 0 {
def.setCommitType(def.commitType() | Alias)
whitespaceDefs = append(whitespaceDefs, def)
continue
}
nonWhitespaceDefs = append(nonWhitespaceDefs, def)
}
return whitespaceDefs, nonWhitespaceDefs
}
func splitRoot(defs []definition) (definition, []definition) {
var (
root definition
rest []definition
)
for _, def := range defs {
if def.commitType()&Root != 0 {
root = def
continue
}
rest = append(rest, def)
}
return root, rest
}
func mergeWhitespaceDefs(ws []definition) definition {
var names []string
for _, def := range ws {
names = append(names, def.nodeName())
}
return newChoice(whitespaceName, Alias, names)
}
2017-10-28 23:41:23 +02:00
func patchName(s ...string) string {
return strings.Join(s, ":")
}
2017-10-28 22:54:15 +02:00
func applyWhitespaceToSeq(s *sequenceDefinition) []definition {
var (
defs []definition
items []SequenceItem
)
2017-10-29 00:49:03 +02:00
whitespace := SequenceItem{Name: whitespaceName, Min: 0, Max: -1}
2017-10-28 22:54:15 +02:00
for i, item := range s.items {
if item.Max >= 0 && item.Max <= 1 {
2017-10-29 00:49:03 +02:00
if i > 0 {
items = append(items, whitespace)
}
2017-10-28 22:54:15 +02:00
items = append(items, item)
continue
}
singleItem := SequenceItem{Name: item.Name, Min: 1, Max: 1}
2017-10-29 01:14:31 +02:00
restName := patchName(item.Name, s.nodeName(), "wsrest", strconv.Itoa(i))
2017-10-29 00:49:03 +02:00
restDef := newSequence(restName, Alias, []SequenceItem{whitespace, singleItem})
2017-10-28 22:54:15 +02:00
defs = append(defs, restDef)
restItems := SequenceItem{Name: restName, Min: 0, Max: -1}
if item.Min > 0 {
restItems.Min = item.Min - 1
}
if item.Max > 0 {
restItems.Min = item.Max - 1
}
if item.Min > 0 {
2017-10-29 00:49:03 +02:00
if i > 0 {
items = append(items, whitespace)
}
2017-10-28 22:54:15 +02:00
items = append(items, singleItem, restItems)
continue
}
2017-10-29 01:14:31 +02:00
optName := patchName(item.Name, s.nodeName(), "wsopt", strconv.Itoa(i))
2017-10-29 00:49:03 +02:00
optDef := newSequence(optName, Alias, []SequenceItem{whitespace, singleItem, restItems})
2017-10-28 22:54:15 +02:00
defs = append(defs, optDef)
items = append(items, SequenceItem{Name: optName, Min: 0, Max: 1})
}
s = newSequence(s.nodeName(), s.commitType(), items)
defs = append(defs, s)
return defs
}
2017-11-01 02:43:46 +01:00
func applyWhitespaceToDefs(defs []definition) []definition {
2017-10-28 22:54:15 +02:00
var defsWS []definition
for _, def := range defs {
if def.commitType()&NoWhitespace != 0 {
defsWS = append(defsWS, def)
continue
}
seq, ok := def.(*sequenceDefinition)
if !ok {
defsWS = append(defsWS, def)
continue
}
defsWS = append(defsWS, applyWhitespaceToSeq(seq)...)
}
return defsWS
}
2017-11-01 02:43:46 +01:00
func applyWhitespaceToRoot(root definition) (definition, definition) {
2017-10-28 22:54:15 +02:00
original, name := root, root.nodeName()
2017-10-28 23:41:23 +02:00
wsName := patchName(name, "wsroot")
2017-10-28 22:54:15 +02:00
original.setNodeName(wsName)
original.setCommitType(original.commitType() &^ Root)
original.setCommitType(original.commitType() | Alias)
root = newSequence(name, Root, []SequenceItem{{
Name: whitespaceName,
Min: 0,
Max: -1,
}, {
Name: wsName,
Min: 1,
Max: 1,
}, {
Name: whitespaceName,
Min: 0,
Max: -1,
}})
return original, root
}
2017-11-01 02:43:46 +01:00
func hasWhitespace(defs []definition) bool {
for i := range defs {
if defs[i].commitType()&Whitespace != 0 {
return true
2017-10-28 22:54:15 +02:00
}
}
2017-11-01 02:43:46 +01:00
return false
}
2017-10-28 22:54:15 +02:00
2017-11-01 02:43:46 +01:00
func applyWhitespace(defs []definition) ([]definition, definition) {
whitespaceDefs, defs := splitWhitespaceDefs(defs)
2017-10-28 22:54:15 +02:00
whitespace := mergeWhitespaceDefs(whitespaceDefs)
2017-11-01 02:43:46 +01:00
defs = applyWhitespaceToDefs(defs)
2017-10-28 22:54:15 +02:00
root, defs := splitRoot(defs)
2017-11-01 02:43:46 +01:00
originalRoot, root := applyWhitespaceToRoot(root)
defs = append(
append(
defs,
whitespaceDefs...,
),
whitespace,
originalRoot,
root,
)
return defs, root
2017-10-28 22:54:15 +02:00
}