76 lines
1.8 KiB
Go
76 lines
1.8 KiB
Go
package template
|
|
|
|
import "fmt"
|
|
|
|
// CompileTemplate 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 CompileTemplate(templateSource string) ([]Block, error) {
|
|
var out []Block
|
|
var curlyIndex int
|
|
|
|
const OPENING = '{'
|
|
const CLOSING = '}'
|
|
|
|
var start int
|
|
var blockType BlockType
|
|
template := NewSlice(templateSource)
|
|
|
|
if template.Len() > 0 && template.At(0) == OPENING {
|
|
blockType = DataBlock
|
|
} else {
|
|
blockType = MatchingBlock
|
|
}
|
|
|
|
for i, r := range template.Chars() {
|
|
|
|
nextCurlyIndex := curlyIndex
|
|
|
|
switch r {
|
|
case OPENING:
|
|
nextCurlyIndex++
|
|
case CLOSING:
|
|
nextCurlyIndex--
|
|
}
|
|
|
|
if curlyIndex == 0 && nextCurlyIndex == 1 {
|
|
if i > start {
|
|
fmt.Printf("BLockContent 1: %q\n", template.Slice(start, i).String())
|
|
block, err := ParseTemplateBlock(template.Slice(start, i), blockType)
|
|
if err != nil {
|
|
return nil, NewErrorf("cannot parse block @pos -> %w", err).WithPosition(start, i)
|
|
}
|
|
out = append(out, block)
|
|
}
|
|
start = i
|
|
blockType = DataBlock
|
|
} else if curlyIndex == 1 && nextCurlyIndex == 0 {
|
|
fmt.Printf("BLockContent 2: %q\n", template.Slice(start, i).String())
|
|
if i > start {
|
|
block, err := ParseTemplateBlock(template.Slice(start, i), blockType)
|
|
if err != nil {
|
|
return nil, NewErrorf("cannot parse block @pos -> %w", err).WithPosition(start, i)
|
|
}
|
|
out = append(out, block)
|
|
}
|
|
|
|
nextChar := ' '
|
|
if i+1 < template.Len() {
|
|
nextChar = rune(template.At(i + 1))
|
|
}
|
|
|
|
if nextChar == OPENING {
|
|
start = i + 1
|
|
blockType = DataBlock
|
|
} else {
|
|
start = i + 1
|
|
blockType = MatchingBlock
|
|
}
|
|
}
|
|
|
|
curlyIndex = nextCurlyIndex
|
|
}
|
|
|
|
return out, nil
|
|
}
|