module Grm.Layout (layout) where
import Grm.Lex
import Grm.Prims
layout :: [Token Point] -> [Token Point]
layout ts = loop [] ts
where
loop [] [] = []
loop (_:cs) [] = stopSyms eofLoc ++ loop cs []
loop cs (x:y:xs) | isStopSym x && isStopWord y = x : y : loop cs xs
loop (_:cs) (x:xs) | isStopWord x =
stopSyms (startLoc x) ++ [x] ++ loop (filter ((>=) $ col x) cs) xs
loop (c:cs) xs0@(x:_) | col x < c = stopSyms (startLoc x) ++ loop cs xs0
loop (c:cs) (x:xs) | col x == c && (isWord ["where"] x) = stopSyms (startLoc x) ++ cont cs x xs
loop cs0@(c:_) (x:xs) | col x == c = termSym (startLoc x) : cont cs0 x xs
loop cs0 (x:xs) = cont cs0 x xs
cont cs0 x0 [] | isStartWord x0 = x0 : startSym (stopLoc x0) : loop (col x0 : cs0) []
cont cs0 x0 (x:xs) | isStartWord x0 && not (isStartSym x) =
x0 : startSym (startLoc x) : cont (col x : cs0) x xs
cont cs0 x xs0 = x : loop cs0 xs0
eofLoc = stopLoc $ last ts
isStartWord :: Token Point -> Bool
isStartWord = isWord [ "where", "do", "of", "imports", "exports", "branch" ]
isStopWord :: Token Point -> Bool
isStopWord = isWord [ "until" ]
isStartSym :: Token Point -> Bool
isStartSym = isWord ["{"]
isStopSym :: Token Point -> Bool
isStopSym = isWord ["}"]
isWord :: [String] -> Token Point -> Bool
isWord ss (TSymbol _ s) = s `elem` ss
isWord _ _ = False
col :: Token Point -> Int
col = locColumn . startLoc
mkSym :: String -> Loc -> Token Point
mkSym s l = TSymbol (Point l l) s
startSym :: Loc -> Token Point
startSym = mkSym "{"
stopSyms :: Loc -> [Token Point]
stopSyms loc = [ termSym loc, mkSym "}" loc ]
termSym :: Loc -> Token Point
termSym = mkSym ";"