treeificator/parser.go
mStar 4368f7713e
Fix parser invalid results, add tests, readme
- Fix parser not producing the correct results
- Add tests for everything
- Add readme with example

Ready for v1
2025-05-02 15:18:14 +02:00

89 lines
2.3 KiB
Go

package treeificator
import (
"strings"
"git.mstar.dev/mstar/goutils/other"
)
func Marshal(raw string, informers ...Informer) Node {
prefixToInformer := map[string]Informer{}
maxPrefixLen := 0
for _, informer := range informers {
prefixToInformer[informer.GetPrefix()] = informer
if l := len(informer.GetPrefix()); l > maxPrefixLen {
maxPrefixLen = l
}
}
defaultInformer := &DefaultInformer{}
delete(prefixToInformer, defaultInformer.GetPrefix())
elems, consumed := marshal(raw, prefixToInformer, nil)
_ = consumed
return Node{
NodeType: defaultInformer,
Elements: elems,
}
}
// Return the elements in the given string, using the given informers, in order of appearance.
func marshal(
raw string,
informers map[string]Informer,
activeInformer Informer,
) ([]NodeElement, uint64) {
elements := []NodeElement{}
buffer := make([]rune, 0)
var consumed uint64 = 0
var insideDiff uint64 = 0 // Nr of runes consumed by recursive calls
outer:
for i, char := range []rune(raw) {
i++
// Skip runes that have been consumed by recursive calls
if uint64(i) < consumed {
continue
}
buffer = append(buffer, char)
consumed = uint64(i)
for k, v := range informers {
if !strings.HasSuffix(string(buffer), k) {
continue
}
if len(buffer) > 0 {
// Cut informer prefix from buffer, append buffer as text element
elements = append(
elements,
NodeElement{Text: other.IntoPointer(strings.TrimSuffix(string(buffer), k))},
)
}
buffer = make([]rune, 0)
subElems, subConsumed := marshal(string([]rune(raw)[consumed:]), informers, v)
elements = append(elements, NodeElement{
Node: &Node{
NodeType: v,
Elements: subElems,
},
})
insideDiff += subConsumed
consumed += subConsumed
continue outer
}
if activeInformer != nil && strings.HasSuffix(string(buffer), activeInformer.GetSuffix()) {
if len(buffer) > 0 {
b := strings.TrimSuffix(string(buffer), activeInformer.GetSuffix())
elements = append(
elements,
NodeElement{
Text: other.IntoPointer(
b,
),
},
)
}
return elements, uint64(consumed) + 1
}
}
if len(buffer) > 0 {
elements = append(elements, NodeElement{Text: other.IntoPointer(string(buffer))})
}
return elements, uint64(consumed)
}