File: Layout.hs

package info (click to toggle)
haskell-lexer 1.1.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 252 kB
  • sloc: haskell: 150; makefile: 6
file content (61 lines) | stat: -rw-r--r-- 2,050 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
module Language.Haskell.Lexer.Layout (layoutPre,PosToken) where

import Language.Haskell.Lexer.Tokens
import Language.Haskell.Lexer.Position

type PosToken = (Token,(Pos,String))

-- | This is an implementation of Haskell layout, as specified in
-- section 9.3 of the revised Haskell 98 report.
-- This preprocessor inserts the extra \<n\> and {n} tokens.
layoutPre :: [PosToken] -> [PosToken]
layoutPre = indent . open

open :: [PosToken] -> [PosToken]
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 :: [PosToken] -> [PosToken]
open1 (t1@(Reservedid,(_,"module")):ts) = t1:open2 ts
open1 (t1@(Special,(_,"{")):ts)         = t1:open2 ts
open1 ts@((_,(p,_)):_)                  = (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 :: [PosToken] -> [PosToken]
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 &lt;n&gt;, where n is the indentation of the token.
-}
indent :: [PosToken] -> [PosToken]
indent (t1@(Open _,(p,_)):ts) = t1:indent2 (line p) ts
indent (t1@(_,(p,_)):ts)    = (Indent (column p),(p,"")):t1:indent2 (line p) ts
indent [] = []

indent2 :: Int -> [PosToken] -> [PosToken]
indent2 r (t1@(_,(p,_)):ts) | line p==r = t1:indent2 r ts
indent2 _ ts = indent ts