import os, re, sys class Blob: def append(self, *_): pass def finish(self, *_): pass class Formula(Blob): def __init__(self): self.lines = [] def append(self, line): self.lines.append(line) def finish(self, *_): for i, line in enumerate(self.lines): assert(len(line[:3].strip()) == 0) line = re.sub(r"\s+", " ", line[3:]) line = re.sub(r"\(\s+", "(", line) line = re.sub(r"\s+\)", ")", line) self.lines[i] = line def format(self, output): output.write("/// ```text\n") for line in self.lines: output.write("/// {}\n".format(line)) output.write("/// ```\n") class Space(Blob): def format(self, output): output.write("///\n") class Text(Blob): def __init__(self): self.lines = [] def append(self, line): self.lines.append(line) def finish(self, index, total, f): lines = self.lines if index == 0: first = re.sub(r"(?i)\s*{}\s+".format(f.name), "", lines[0]) lines[0] = first line = " ".join(lines) line = re.sub(r"\s+", " ", line) line = re.sub(r"\(\s+", "(", line) line = re.sub(r"\s+\)", ")", line) if index == total - 1 and line[-1] != ".": line = "{}.".format(line) lines = line.split(". ") lowercase = ["alpha", "or", "where"] for i, line in enumerate(lines): if all([not line.startswith(word) for word in lowercase]): lines[i] = "{}{}".format(line[0].upper(), line[1:]) line = ". ".join(lines) substitutes = { "Compute": "Computes", "equal to 1": "equal to one", } for key, value in substitutes.items(): line = re.sub(r"\b{}\b".format(key), value, line) chunks = line.split(" ") lines = [] count = 0 while len(chunks) > 0: current = " ".join(chunks[:count]) if count == len(chunks) or 4 + len(current) + len(chunks[count]) >= 80: lines.append(current) chunks = chunks[count:] count = 0 else: count += 1 self.lines = lines def format(self, output): for line in self.lines: output.write("/// {}\n".format(line)) def clean(lines): lines = [re.sub(r"^\*> ?", "", line.rstrip()) for line in lines] while len(lines) > 0 and lines[0].strip() == "": lines = lines[1:] while len(lines) > 0 and lines[-1].strip() == "": lines = lines[:-1] margin = 42 for line in lines: if len(line.strip()) > 0: margin = min(margin, len(line) - len(line.strip())) for i, line in enumerate(lines): if len(line.strip()) > 0: lines[i] = lines[i][margin:] return lines def extract(filename): SEARCHING = 0 IN_PURPOSE = 1 IN_DESCRIPTION = 2 lines = [] state = SEARCHING with open(filename) as file: for line in file: if state == SEARCHING: if "par Purpose" in line: state = IN_PURPOSE elif state == IN_PURPOSE: if "\\verbatim" in line: state = IN_DESCRIPTION elif state == IN_DESCRIPTION: if "\\endverbatim" in line: break lines.append(line.replace("\n", "")) return lines def partition(lines): paragraphs = [] current = None for line in lines: if line.startswith(" "): klass = Formula elif len(line) == 0: klass = Space else: klass = Text if not isinstance(current, klass): if current is not None: paragraphs.append(current) current = klass() current.append(line) if current is not None: paragraphs.append(current) return paragraphs def print_documentation(f, reference): filename = os.path.join(reference, "BLAS", "SRC", "{}.f".format(f.name)) if not os.path.exists(filename): return paragraphs = partition(clean(extract(filename))) for i, paragraph in enumerate(paragraphs): paragraph.finish(i, len(paragraphs), f) paragraph.format(sys.stdout)