in cqlprotodoc/spec/spec.go [71:165]
func Parse(data string) (Document, error) {
lines := strings.Split(data, "\n")
var license strings.Builder
var doc Document
l := 0
// license
for l < len(lines) {
m := commentRegexp.FindStringSubmatch(lines[l])
if len(m) != 2 {
break
}
license.WriteString(m[1])
license.WriteString("\n")
l++
}
doc.License = parseBody(strings.Trim(license.String(), "\n "))
// empty lines
for l < len(lines) && emptyRegexp.MatchString(lines[l]) {
l++
}
// title
if l >= len(lines) {
return Document{}, fmt.Errorf("missing title")
}
m := titleRegexp.FindStringSubmatch(lines[l])
if len(m) != 2 {
return Document{}, fmt.Errorf("line %d: title expected on line", l)
}
doc.Title = m[1]
l++
// empty lines
for l < len(lines) && emptyRegexp.MatchString(lines[l]) {
l++
}
// table of contents header
if lines[l] != "Table of Contents" {
return Document{}, fmt.Errorf("line %d: expected table of contents", l)
}
l++
// empty lines
for l < len(lines) && emptyRegexp.MatchString(lines[l]) {
l++
}
// toc entries
for l < len(lines) {
if emptyRegexp.MatchString(lines[l]) {
// end of toc
break
}
mh := headingRegexp.FindStringSubmatch(lines[l])
if len(mh) != 4 {
return Document{}, fmt.Errorf("line %d: expected toc entry", l)
}
doc.TOC = append(doc.TOC, TOCEntry{
Number: mh[mhNumber],
Title: mh[mhTitle],
})
l++
}
// empty lines
for l < len(lines) && emptyRegexp.MatchString(lines[l]) {
l++
}
// content
tocIdx := 0
var section Section
var body []string
for l < len(lines) {
var sectionStart bool
var newSection Section
sectionStart, tocIdx, newSection = checkSectionStart(doc.TOC, tocIdx, lines[l])
if sectionStart {
section.Body = parseBody(strings.Join(body, "\n"))
doc.Sections = append(doc.Sections, section)
section = newSection
body = nil
l++
// Eat empty lines
for l < len(lines) && emptyRegexp.MatchString(lines[l]) {
l++
}
continue
}
body = append(body, lines[l])
l++
}
if len(body) > 0 || !section.Empty() {
section.Body = parseBody(strings.Join(body, "\n"))
doc.Sections = append(doc.Sections, section)
}
return doc, nil
}