Files
marka/parser/blocks.go
2025-08-17 01:21:15 +02:00

75 lines
1.6 KiB
Go

package parser
import (
"fmt"
"git.max-richter.dev/max/marka/parser/blocks"
)
// 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(template string) ([]blocks.TemplateBlock, error) {
var out []blocks.TemplateBlock
var curlyIndex int
const CLOSING = '}'
const OPENING = '{'
var start int
var blockType blocks.BlockType
if len(template) > 0 && template[0] == OPENING {
curlyIndex = 1
blockType = blocks.DataBlock
} else {
blockType = blocks.MatchingBlock
}
for i, r := range template {
var nextCurlyIndex = curlyIndex
switch r {
case OPENING:
nextCurlyIndex++
case CLOSING:
nextCurlyIndex--
}
var nextChar rune = ' '
if i+1 < len(template) {
nextChar = rune(template[i+1])
}
if curlyIndex == 0 && nextCurlyIndex == 1 {
block, err := blocks.ParseTemplateBlock(template[start:i], blockType)
if err != nil {
return nil, fmt.Errorf("Failed to parse block: %w", err)
}
out = append(out, block)
start = i
blockType = blocks.DataBlock
} else if curlyIndex == 1 && nextCurlyIndex == 0 {
block, err := blocks.ParseTemplateBlock(template[start:i+1], blockType)
if err != nil {
return nil, fmt.Errorf("Failed to parse block: %w", err)
}
out = append(out, block)
if nextChar == OPENING {
start = i + 1
blockType = blocks.DataBlock
} else {
start = i + 1
blockType = blocks.MatchingBlock
}
}
curlyIndex = nextCurlyIndex
}
return out, nil
}