#!/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))