module HsLayoutPre(layoutPre,PosToken) where import HsTokens import HsLexerPos
This is an implementation of Haskell layout, as specified in section 9.3 of the revised Haskell 98 report.
This module contains the layout preprocessor that inserts the extra <n> and {n} tokens.
type PosToken = (Token,(Pos,String)) layoutPre :: [PosToken] -> [PosToken] layoutPre = indent . open open = open1
If the first lexeme of a module is not { or module, then it is preceded by {n} where n is the indentation of the lexeme.
open1 (t1@(Reservedid,(_,"module")):ts) = t1:open2 ts open1 (t1@(Special,(_,"{")):ts) = t1:open2 ts open1 ts@((t,(p,s)):_) = (Open (column p),(p,"")):open2 ts open1 [] = []
If a let, where, do, or of keyword is not followed by the lexeme {, the token {n} is inserted after the keyword, where n is the indentation of the next lexeme if there is one, or 0 if the end of file has been reached.
open2 (t1:ts1) | isLtoken t1 = case ts1 of t2@(_,(p,_)):ts2 -> if notLBrace t2 then t1:(Open (column p),(p,"")):open2 ts1 else t1:t2:open2 ts2 [] -> t1:(Open 0,(fst (snd t1),"")):[] where isLtoken (Reservedid,(_,s)) = s `elem` ["let","where","do","of"] isLtoken _ = False notLBrace (Special,(_,"{")) = False notLBrace _ = True open2 (t:ts) = t:open2 ts open2 [] = []
(This is from the original Haskell 98 report.) The first token on each line (not including tokens already annotated) is preceeded by <n>, where n is the indentation of the token.
indent (t1@(Open _,(p,_)):ts) = t1:indent2 (line p) ts
indent (t1@(t,(p,s)):ts) = (Indent (column p),(p,"")):t1:indent2 (line p) ts
indent [] = []
indent2 r (t1@(_,(p,_)):ts) | line p==r = t1:indent2 r ts
indent2 r ts = indent ts