| // Copyright 2026 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package specdoc |
| |
| import ( |
| "go/ast" |
| "simd/archsimd/_gen/specgen" |
| "strings" |
| ) |
| |
| // parseCommentGroup splits an AST comment group into classified paragraphs. |
| func parseCommentGroup(cg *ast.CommentGroup) []specgen.Paragraph { |
| if cg == nil || len(cg.List) == 0 { |
| return nil |
| } |
| |
| var paras []specgen.Paragraph |
| var para strings.Builder |
| flush := func() { |
| if para.Len() == 0 { |
| return |
| } |
| text := para.String() |
| para.Reset() |
| |
| kind := specgen.SpecOwned |
| if specgen.HasNotePrefix(text) { |
| kind = specgen.ImplementationNote |
| } |
| paras = append(paras, specgen.Paragraph{Kind: kind, Text: text}) |
| } |
| for _, c := range cg.List { |
| if isDirectiveLine(c.Text) { |
| flush() |
| paras = append(paras, specgen.Paragraph{Kind: specgen.DirectiveComment, Text: c.Text[2:]}) |
| continue |
| } |
| |
| // Drop leading "//" or "// ". If it's "//\t", we keep the "\t" |
| text, ok := strings.CutPrefix(c.Text, "// ") |
| if !ok { |
| text, ok = strings.CutPrefix(text, "//") |
| if !ok { |
| panic("comment does not start with //?") |
| } |
| } |
| if text == "" { |
| // Paragraph break |
| flush() |
| continue |
| } |
| if para.Len() > 0 { |
| para.WriteByte('\n') |
| } |
| para.WriteString(text) |
| } |
| flush() |
| |
| return paras |
| } |
| |
| // isDirectiveLine reports whether comment line is a compiler/tool directive |
| // comment. |
| func isDirectiveLine(line string) bool { |
| line = strings.TrimSpace(line) |
| if _, ok := ast.ParseDirective(0, line); ok { |
| return true |
| } |
| if strings.HasPrefix(line, "//line ") { |
| return true |
| } |
| return false |
| } |