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 } // var lastBlock = out[len(out)-1] // if lastBlock.End == 0 { // out = out[:len(out)-1] // } return out, nil }