#!/usr/bin/env python3 class Line: @property def base(self): if self.sublevels: return self.sublevels[0] return self.indent @property def levels(self): return self.sublevels + [self.indent] def __init__(self, line): self.continues = line.lstrip().startswith(". ") if self.continues: self.content = line.lstrip()[2:].lstrip() else: self.content = line.lstrip() # the indentation of the code self.indent = len(line) - len(line.lstrip()) # due to : vertical space optimization, the line can have multiple sublevels # TODO make this work. self.sublevels = [] while self.content.startswith(": ") and self.content[2:].lstrip(): self.sublevels.append(self.indent) self.indent += len(self.content) - len(self.content[2:].lstrip()) self.content = self.content[2:].lstrip() if self.content.strip() == ":": self.content = "" def wisp2lisp(code): """Turn wisp code to lisp code.""" # first get rid of linebreaks in strings instring = False nostringbreaks = [] for char in code: if char == '"': instring = not instring if instring and char == "\n": nostringbreaks.append("\\n") else: nostringbreaks.append(char) code = "".join(nostringbreaks) # now read the indentation lines = [] for line in code.splitlines(): lines.append(Line(line)) # finally emit matching lisp code # write into the lisp lines with a delay of 1 line lisplines = [] levels = [] prev = lines[0] if not prev.continues: prev.content = "(" + prev.content for line in lines[1:]: # continuing lines do not get a leading bracket. if not line.continues: line.content = "(" + line.content # rising indent: sibling function or variable if line.base > prev.indent: levels.extend(line.levels) lisplines.append(prev.indent * " " + prev.content) # same indent: neighbour function of variable: close the previour lines bracket elif line.base == prev.indent: lisplines.append(prev.indent * " " + prev.content + ")") for l in line.levels: if l > levels[-1]: levels.append(l) # lower indent: parent funtion or variable. Find the number of brackets to close elif prev.indent > line.base: bracketstoclose = len([level for level in levels if level >= line.indent]) levels = levels[:-bracketstoclose + 1] for l in line.levels: if not levels or l > levels[-1]: levels.append(l) if prev.continues: bracketstoclose -= 1 lisplines.append(prev.indent * " " + prev.content + ")" * bracketstoclose) prev = line lisplines.append(prev.indent * " " + prev.content + ")" * (len(levels))) return "\n".join(lisplines) if __name__ == "__main__": print() with open("example.w") as f: wisp = f.read() print(wisp2lisp(wisp))