Skip to content

Commit

Permalink
Rewritten formatting (#144)
Browse files Browse the repository at this point in the history
* Began working on the rewritten formatter.

* Implemented first prototype. Most special forms aren't done yet, nor is the cost heuristic.

* Implemented all special forms.

* Updated the cost function.

* Cleaned up code a bit.

* Fixed bug.

* Improved comment handling
  • Loading branch information
rahularya50 authored Apr 8, 2019
1 parent 9b7f0a9 commit 1de35a0
Show file tree
Hide file tree
Showing 4 changed files with 612 additions and 319 deletions.
58 changes: 28 additions & 30 deletions editor/format_parser.py
Original file line number Diff line number Diff line change
@@ -1,54 +1,60 @@
from typing import Union, List

from lexer import TokenBuffer, SPECIALS
from lexer import TokenBuffer, SPECIALS, Comment
from scheme_exceptions import ParseError


class FormatList:
def __init__(self,
contents: List['Formatted'],
last: 'Formatted',
comments: List[str],
close_paren,
allow_inline,
prefix: str=""):
self.contents = contents
self.last = last
self.comments = comments
self.contains_comment = any(x.contains_comment or x.comments for x in contents)
self.allow_inline = allow_inline and len(comments) <= 1
self.open_paren = "(" if close_paren == ")" else "["
self.close_paren = close_paren
self.prefix = prefix

def __repr__(self):
return str(self.__dict__)
class PrefixManager:
def __init__(self, lst):
self.lst = lst

def __enter__(self):
self.prefix = self.lst.prefix
self.lst.prefix = ""
return self.prefix

def __exit__(self, *_):
self.lst.prefix = self.prefix

def hold_prefix(self):
return self.PrefixManager(self)


class FormatAtom:
def __init__(self, value: str, comments: List[str]=None, allow_inline=True):
def __init__(self, value: str):
self.value = value
self.comments = comments if comments else []
self.contains_comment = False
self.allow_inline = allow_inline and (not comments or len(comments) <= 1)
self.prefix = ""

def __repr__(self):
return str(self.__dict__)

class FormatComment:
def __init__(self, value: str, allow_inline: bool):
self.value = value
self.prefix = ""
self.allow_inline = allow_inline


Formatted = Union[FormatList, FormatAtom]
Formatted = Union[FormatList, FormatAtom, FormatComment]


def get_expression(buffer: TokenBuffer) -> Formatted:
token = buffer.pop_next_token()
comments = []
if token == "#" and not buffer.done and buffer.get_next_token() == "[":
if isinstance(token, Comment):
return FormatComment(token.value, not token.first_in_line)
elif token == "#" and not buffer.done and buffer.get_next_token() == "[":
buffer.pop_next_token()
out = FormatAtom("#[" + buffer.pop_next_token().value + "]")
buffer.pop_next_token()
elif token in SPECIALS:
comments = token.comments
if token in ("(", "["):
out = get_rest_of_list(buffer, ")" if token == "(" else "]")
elif token in ("'", "`"):
Expand All @@ -75,20 +81,12 @@ def get_expression(buffer: TokenBuffer) -> Formatted:
token.value = "#f"
out = FormatAtom(token.value)

out.comments = comments + buffer.tokens[buffer.i - 1].comments
out.allow_inline = token.comments_inline and buffer.tokens[buffer.i - 1].comments_inline
return out


def get_rest_of_list(buffer: TokenBuffer, end_paren: str):
out = []
last = None
while buffer.get_next_token() != end_paren and buffer.get_next_token() != ".":
while buffer.get_next_token() != end_paren:
out.append(get_expression(buffer))
if buffer.get_next_token() == ".":
buffer.pop_next_token()
last = get_expression(buffer)
if buffer.get_next_token() != end_paren:
raise ParseError("Only one expression may follow a dot in a dotted list.")
buffer.pop_next_token()
return FormatList(out, last, [], end_paren, True)
return FormatList(out, end_paren)
Loading

0 comments on commit 1de35a0

Please sign in to comment.