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