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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
------------------------------------------------------------------------------
--- Handling parse positions
---
--- @author Jasper Sikorra - jsi@informatik.uni-kiel.de
--- @version January 2014
------------------------------------------------------------------------------
module ParsePos where

-- Tab width
tw :: Int
tw = 8

-- Unkown filename
unknown_fname :: String
unknown_fname = "Unknown file"

type Filename = String
type Absolute = Int
type Line     = Int
type Column   = Int

-- A reduced representation of the position
type SimplePos = (Int,Int)

--- The Pos data type contains the name of the file, the absolute,
--- where every character is counted as 1 (newlines, tabs too) 
--- (starting with 0), the line (starting with 1) and the column (starting
--- with 1) of the character's position.
data Pos = Pos Filename Absolute Line Column

--- Construct a new position
setPos :: Filename -> Absolute -> Line -> Column -> Pos
setPos fname abs line col = Pos fname abs line col

--- Construct the initial position
initPos :: Filename -> Pos
initPos fname = Pos fname 0 1 1

getFilename :: Pos -> Filename
getFilename (Pos f _ _ _) = f

setFilename :: Pos -> Filename -> Pos
setFilename (Pos _ a x y) fname = Pos fname a x y

getAbs :: Pos -> Absolute
getAbs (Pos _ a _ _) = a

setAbs :: Pos -> Absolute -> Pos
setAbs (Pos f _ x y) abs = Pos f abs x y

moveAbs :: Pos -> Absolute -> Pos
moveAbs (Pos f a x y) n = Pos f (a+n) x y

getLn :: Pos -> Line
getLn (Pos _ _ x _) = x

setLn :: Pos -> Line -> Pos
setLn (Pos f a _ y) lin = Pos f a lin y

moveLn :: Pos -> Line -> Pos
moveLn (Pos f a x y) n = Pos f a (x+n) y

getCol :: Pos -> Column
getCol (Pos _ _ _ y) = y

setCol :: Pos -> Column -> Pos
setCol (Pos f a x _) col = Pos f a x col

moveCol :: Pos -> Column -> Pos
moveCol (Pos f a x y) n = Pos f a x (y+n)

--- The difference in lines between two positions
lnDifference :: Pos -> Pos -> Line
lnDifference p1 p2 = getLn p2 - getLn p1

--- The difference in columns between two positions
colDifference :: Pos -> Pos -> Column
colDifference p1 p2 = getCol p2 - getCol p1

--- The absolute difference between two positions
absDifference :: Pos -> Pos -> Absolute
absDifference p1 p2 = getAbs p2 - getAbs p1

--- The line and column difference between two positions
fullDifference :: Pos -> Pos -> (Line,Column)
fullDifference p1 p2 = (lnDifference p1 p2,colDifference p1 p2)

--- Move the position one character
movePosByChar :: Pos -> Char -> Pos
movePosByChar (Pos f a x y) c | c == '\n' = Pos f (a+1) (x+1) 1
                              | c == '\t' = Pos f (a+1) x (y+tw-mod (y-1) tw)
                              | otherwise = Pos f (a+1) x     (y+1)

--- Move the position multiple characters
movePosByString :: Pos -> String -> Pos
movePosByString p ""     = p
movePosByString p (c:cs) = movePosByString (movePosByChar p c) cs

--- Convert to SimplePos
toSimplePos :: Pos -> SimplePos
toSimplePos p = (getLn p,getCol p)

--- Convert from SimplePos
fromSimplePos :: SimplePos -> Pos
fromSimplePos p = fromSimplePosWithFname p unknown_fname

--- Convert from SimplePos with Filename
fromSimplePosWithFname :: SimplePos -> Filename -> Pos
fromSimplePosWithFname (x,y) fn = setPos fn (x+y) x y