module UU.Scanner.Position where

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


class Position p where 
  line   :: p -> Line
  column :: p -> Column
  file   :: p -> Filename


instance Position Pos where
   line :: Pos -> Column
line   (Pos Column
l Column
_ Filename
_) = Column
l
   column :: Pos -> Column
column (Pos Column
_ Column
c Filename
_) = Column
c
   file :: Pos -> Filename
file   (Pos Column
_ Column
_ Filename
f) = Filename
f

data Pos = Pos !Line !Column Filename 

instance Show Pos where
  show :: Pos -> Filename
show (Pos Column
l Column
c Filename
f) | Column
l Column -> Column -> Bool
forall a. Eq a => a -> a -> Bool
== (-Column
1) = Filename
""
                   | Bool
otherwise = let file :: Filename
file = if Filename -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Filename
f then Filename
"" else ShowS
forall a. Show a => a -> Filename
show Filename
f
                                     lc :: Filename
lc = Filename
"(line " Filename -> ShowS
forall a. [a] -> [a] -> [a]
++ Column -> Filename
forall a. Show a => a -> Filename
show Column
l Filename -> ShowS
forall a. [a] -> [a] -> [a]
++ Filename
", column " Filename -> ShowS
forall a. [a] -> [a] -> [a]
++ Column -> Filename
forall a. Show a => a -> Filename
show Column
c Filename -> ShowS
forall a. [a] -> [a] -> [a]
++Filename
")"
                                 in Filename
file Filename -> ShowS
forall a. [a] -> [a] -> [a]
++ Filename
lc
initPos :: FilePath -> Pos
initPos :: Filename -> Pos
initPos Filename
fn = Column -> Column -> Filename -> Pos
Pos Column
1 Column
1 Filename
fn

noPos :: Pos
noPos :: Pos
noPos = Column -> Column -> Filename -> Pos
Pos (-Column
1) (-Column
1) Filename
""

advl ::  Line -> Pos ->Pos
advl :: Column -> Pos -> Pos
advl Column
i (Pos Column
l Column
c Filename
f) = (Column -> Column -> Filename -> Pos
Pos (Column
lColumn -> Column -> Column
forall a. Num a => a -> a -> a
+Column
i) Column
1 Filename
f)

advc :: Column -> Pos ->  Pos
advc :: Column -> Pos -> Pos
advc Column
i (Pos Column
l Column
c Filename
f) = (Column -> Column -> Filename -> Pos
Pos Column
l (Column
cColumn -> Column -> Column
forall a. Num a => a -> a -> a
+Column
i) Filename
f)

adv :: Pos -> Char -> Pos
adv :: Pos -> Char -> Pos
adv Pos
pos Char
c = case Char
c of
  Char
'\t' -> Column -> Pos -> Pos
advc (Column -> Column
tabWidth (Pos -> Column
forall p. Position p => p -> Column
column Pos
pos)) Pos
pos
  Char
'\n' -> Column -> Pos -> Pos
advl Column
1 Pos
pos
  Char
_    -> Column -> Pos -> Pos
advc Column
1 Pos
pos

updPos :: Char -> Pos -> Pos
updPos :: Char -> Pos -> Pos
updPos Char
x = case Char
x of
 Char
'\n' -> Pos -> Pos
newl
 Char
'\t' -> Pos -> Pos
tab
 Char
_    -> Column -> Pos -> Pos
advc Column
1

tab              :: Pos -> Pos
tab :: Pos -> Pos
tab  (Pos Column
l Column
c Filename
f) =  Column -> Column -> Filename -> Pos
Pos Column
l (Column
cColumn -> Column -> Column
forall a. Num a => a -> a -> a
+Column -> Column
tabWidth Column
c) Filename
f

newl :: Pos ->Pos
newl :: Pos -> Pos
newl =  Column -> Pos -> Pos
advl Column
1

tabWidth :: Column -> Int
tabWidth :: Column -> Column
tabWidth Column
c = Column
8 Column -> Column -> Column
forall a. Num a => a -> a -> a
- ((Column
cColumn -> Column -> Column
forall a. Num a => a -> a -> a
-Column
1) Column -> Column -> Column
forall a. Integral a => a -> a -> a
`mod` Column
8)


updPos' :: Char -> Pos -> (Pos -> a) -> a
updPos' :: forall a. Char -> Pos -> (Pos -> a) -> a
updPos' Char
c Pos
p Pos -> a
cont = Pos
p Pos -> a -> a
`seq` Pos -> a
cont (Char -> Pos -> Pos
updPos Char
c Pos
p)

advc' :: Int -> Pos -> (Pos -> a) -> a
advc' :: forall a. Column -> Pos -> (Pos -> a) -> a
advc' Column
i Pos
p Pos -> a
cont = Pos
p Pos -> a -> a
`seq` Pos -> a
cont (Column -> Pos -> Pos
advc Column
i Pos
p)

tab' :: Pos -> (Pos -> a) -> a
tab' :: forall a. Pos -> (Pos -> a) -> a
tab'  Pos
p Pos -> a
cont = Pos
p Pos -> a -> a
`seq` Pos -> a
cont (Pos -> Pos
tab Pos
p)

newl' :: Pos -> (Pos -> a) -> a
newl' :: forall a. Pos -> (Pos -> a) -> a
newl' Pos
p Pos -> a
cont = Pos
p Pos -> a -> a
`seq` Pos -> a
cont (Pos -> Pos
newl Pos
p)