module HsLayoutPre(layoutPre,Pos,PosToken) where import HsTokens {-+ 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 Pos = (Int,Int) -- (row,column) 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@(r,c),s)):_) = (Open c,(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@(r,c),_)):ts2 -> if notLBrace t2 then t1:(Open c,(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 _,((r,c),_)):ts) = t1:indent2 r ts indent (t1@(t,(p@(r,c),s)):ts) = (Indent c,(p,"")):t1:indent2 r ts indent [] = [] indent2 r (t1@(_,((r',_),_)):ts) | r'==(r::Int) = t1:indent2 r ts indent2 r ts = indent ts