ffs, i should have committed wayyy earlier
This commit is contained in:
97
parser/blocks.go
Normal file
97
parser/blocks.go
Normal file
@@ -0,0 +1,97 @@
|
||||
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
|
||||
}
|
Reference in New Issue
Block a user