------------------------------------------------------------------------------
--- 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