(Arne Babenhauserheide)
2013-03-25: allow escaping : and _. allow escaping : and _.
diff --git a/example.w b/example.w --- a/example.w +++ b/example.w @@ -24,3 +24,10 @@ defun b : :n o . "second defun : with a docstring!" message "I am here" . t + +defun _ : \: +__ +__ . \: + +\_ b + \ No newline at end of file diff --git a/wisp.py b/wisp.py --- a/wisp.py +++ b/wisp.py @@ -28,6 +28,53 @@ but crave the power of lisp. """ +def replaceinwisp(code, string, replacement): + """Replace the given string with the replacement, but only in + indentation sensitive parts of the code. + + Essentially replace everywhere except in brackets or strings. + + :param code: Arbitrary wisp code to process. + :param string: A string to replace. + :param replacement: The replacement string. + + :return: (code, count): The new code and a count of replacements. + """ + count = 0 + instring = False + incomment = False + inbrackets = 0 + strlen = len(string) + for n in range(len(code) - strlen): + i = code[n] + # comments start with a ; - but only in regular wisp code. + if not incomment and not instring and not inbrackets and i == ";": + incomment = not incomment + # a linebreak ends the comment + if incomment: + if i == "\n": + incomment = not incomment + # all processing stops in comments + continue + if i == '"': + instring = not instring + # all processing stops in strings + if instring: + continue + if i == "(": + inbrackets += 1 + elif i == ")": + inbrackets -= 1 + # all processing stops in brackets + if inbrackets: + continue + # here we do the actual replacing + if code[n:n+strlen] == string: + count += 1 + code = code[:n] + replacement + code[n+strlen:] + return code, count + + class Line: def __init__(self, line): """Parse one line in which linebreaks within strings and @@ -41,7 +88,11 @@ class Line: # here line[i-1] is _. Check if line[i+1] is a space. if line[i:i+1] == " ": line = (i)*" " + line[i:] - + # \_ escapes the underscore at the beginning of a line, so you + # can use identifiers which only consist of underscores. + elif line.startswith("\_"): + line = "_" + line[2:] + #: prefix to go around the outer bracket: '(, ,( or `( self.prefix = "" # check if this is a continuation of the parent line @@ -95,8 +146,22 @@ class Line: if self.content[n-1:n+2] == " : " or self.content[n-1:] == " :": bracketstoclose += 1 self.content = self.content[:n] + "(" + self.content[n+1:] + + # after the full line processing, replace " \\: " "\n\\: " and + # " \\:\n" (inside line, start of a line, end of a line) by " + # : ", "\n: " and " :\n" respectively to allow escaping : as + # expression. + self.content, count = replaceinwisp(self.content, " \\: ", " : ") + if self.content.startswith("\\: "): + self.content = ": " + self.content[3:] + elif self.content.endswith(" \\:"): + self.content = self.content[:-3] + " :" + elif self.content == "\\:": # empty function or variable call + self.content = ":" + + # add closing brackets self.content += ")" * bracketstoclose - + #: Is the line effectively empty? self.empty = False onlycomment = (line.split(";")[1:] and # there is content after the comment sign