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 l :: Column
l _ _) = Column
l
   column :: Pos -> Column
column (Pos _ c :: Column
c _) = Column
c
   file :: Pos -> Filename
file   (Pos _ _ f :: Filename
f) = Filename
f

data Pos = Pos !Line !Column Filename 

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

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

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

advc :: Column -> Pos ->  Pos
advc :: Column -> Pos -> Pos
advc i :: Column
i (Pos l :: Column
l c :: Column
c f :: 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
pos c :: Char
c = case Char
c of
  '\t' -> Column -> Pos -> Pos
advc (Column -> Column
tabWidth (Pos -> Column
forall p. Position p => p -> Column
column Pos
pos)) Pos
pos
  '\n' -> Column -> Pos -> Pos
advl 1 Pos
pos
  _    -> Column -> Pos -> Pos
advc 1 Pos
pos

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

tab              :: Pos -> Pos
tab :: Pos -> Pos
tab  (Pos l :: Column
l c :: Column
c f :: 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 1

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


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

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

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

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