// isMultilineValue return true if value is multiline string func isMultilineValue(value string) bool { if strutil.Head(value, 1) == "\"" && strutil.Tail(value, 1) != "\"" { return true } return false }
// Parse method parse given file and return document struct and slice with errors func Parse(file string) (*Document, []error) { if !fsutil.CheckPerms("FR", file) { return nil, []error{fmt.Errorf("File %s is not readable or not exist", file)} } fd, err := os.Open(file) if err != nil { return nil, []error{err} } defer fd.Close() reader := bufio.NewReader(fd) scanner := bufio.NewScanner(reader) var buffer []string var doc = &Document{Title: filepath.Base(file)} var lineNum = 0 for scanner.Scan() { line := scanner.Text() line = strings.TrimLeft(line, " ") lineNum++ if lineNum == 1 { continue } if line == "" { if buffer != nil && !doc.IsValid() { doc.About = getCleanData(buffer) } buffer = nil continue } if strings.Trim(line, "#") == "" { if buffer != nil { buffer = append(buffer, "") } continue } if line[0] == '#' { buffer = append(buffer, line[2:]) continue } t, name, value := parseEntity(line) if t == ENT_TYPE_UNKNOWN || len(buffer) == 0 { buffer = nil continue } switch t { case ENT_TYPE_METHOD: m := parseMethodComment(name, buffer) if m == nil { buffer = nil continue } m.Line = lineNum // Methods MUST have description if len(m.Desc) != 0 { doc.Methods = append(doc.Methods, m) } buffer = nil case ENT_TYPE_VARIABLE, ENT_TYPE_CONSTANT: v := parseVariableComment(name, value, buffer) if v == nil { buffer = nil continue } // Append multiline parts to value if isMultilineValue(value) { MULTIPART: for scanner.Scan() { valuePart := scanner.Text() v.Value += valuePart if strutil.Tail(valuePart, 1) == "\"" { break MULTIPART } } } v.Line = lineNum // Variables MUST have description if len(v.Desc) != 0 { if t == ENT_TYPE_VARIABLE { doc.Variables = append(doc.Variables, v) } else { doc.Constants = append(doc.Constants, v) } } buffer = nil } } return doc, []error{} }