Files
marka/parser/blocks.go
2025-08-16 20:38:40 +02:00

98 lines
1.9 KiB
Go

package parser
type BlockType string
const (
BlockData BlockType = "data" // content between lines "{" and "}"
BlockMatching BlockType = "matching" // everything outside data blocks
)
type Block struct {
Type BlockType
Start, End int // byte offsets [Start, End)
src *string
}
func (b Block) GetContent() string {
if b.src == nil || b.Start < 0 || b.End > len(*b.src) || b.Start > b.End {
return ""
}
return (*b.src)[b.Start:b.End]
}
// ExtractBlocks scans once, emitting:
// - data blocks: inner content between a line that's exactly "{" and a line that's exactly "}"
// - matching blocks: gaps between data blocks (excluding the brace lines themselves)
func ExtractBlocks(src string) []Block {
var out []Block
var curlyIndex int
const CLOSING = '}'
const OPENING = '{'
if len(src) > 0 && src[0] == OPENING {
curlyIndex = 1
out = append(out, Block{
Start: 0,
Type: BlockData,
src: &src,
})
} else {
out = append(out, Block{
Start: 0,
Type: BlockMatching,
src: &src,
})
}
for i, r := range src {
var nextCurlyIndex = curlyIndex
switch r {
case OPENING:
nextCurlyIndex++
case CLOSING:
nextCurlyIndex--
}
var nextChar rune = ' '
if i+1 < len(src) {
nextChar = rune(src[i+1])
}
if curlyIndex == 0 && nextCurlyIndex == 1 {
out[len(out)-1].End = i
out = append(out, Block{
Start: i,
Type: BlockData,
src: &src,
})
} else if curlyIndex == 1 && nextCurlyIndex == 0 {
out[len(out)-1].End = i + 1
if nextChar == OPENING {
out = append(out, Block{
Start: i + 1,
Type: BlockData,
src: &src,
})
} else {
out = append(out, Block{
Start: i + 1,
Type: BlockMatching,
src: &src,
})
}
}
curlyIndex = nextCurlyIndex
}
var lastBlock = out[len(out)-1]
if lastBlock.End == 0 {
out = out[:len(out)-1]
}
return out
}