{- |
Module      :  Text.ParserCombinators.Parsec.Pos
Copyright   :  (c) Daan Leijen 1999-2001
License     :  BSD-style (see the file LICENSE)

Maintainer  :  Christian Maeder <chr.maeder@web.de>
Stability   :  provisional
Portability :  portable

Textual source positions
-}

module Text.ParserCombinators.Parsec.Pos
  ( Column
  , Line
  , SourceName
  , SourcePos
  , incSourceColumn
  , incSourceLine
  , initialPos
  , newPos
  , setSourceColumn
  , setSourceLine
  , setSourceName
  , sourceColumn
  , sourceLine
  , sourceName
  , updatePosChar
  , updatePosString
  ) where

{- ---------------------------------------------------------
Source Positions, a file name, a line and a column.
upper left is (1,1)
--------------------------------------------------------- -}
type SourceName = String
type Line = Int
type Column = Int

{- | The abstract data type @SourcePos@ represents source positions. It
contains the name of the source (i.e. file name), a line number and
a column number. @SourcePos@ is an instance of the 'Show', 'Eq' and
'Ord' class. -}
data SourcePos = SourcePos
  { SourcePos -> SourceName
sourceName :: SourceName -- ^ the name of the source from a position
  , SourcePos -> Line
sourceLine :: !Line      -- ^ the line number from a source position
  , SourcePos -> Line
sourceColumn :: !Column  -- ^ the column number from a source position
  } deriving (SourcePos -> SourcePos -> Bool
(SourcePos -> SourcePos -> Bool)
-> (SourcePos -> SourcePos -> Bool) -> Eq SourcePos
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SourcePos -> SourcePos -> Bool
$c/= :: SourcePos -> SourcePos -> Bool
== :: SourcePos -> SourcePos -> Bool
$c== :: SourcePos -> SourcePos -> Bool
Eq, Eq SourcePos
Eq SourcePos
-> (SourcePos -> SourcePos -> Ordering)
-> (SourcePos -> SourcePos -> Bool)
-> (SourcePos -> SourcePos -> Bool)
-> (SourcePos -> SourcePos -> Bool)
-> (SourcePos -> SourcePos -> Bool)
-> (SourcePos -> SourcePos -> SourcePos)
-> (SourcePos -> SourcePos -> SourcePos)
-> Ord SourcePos
SourcePos -> SourcePos -> Bool
SourcePos -> SourcePos -> Ordering
SourcePos -> SourcePos -> SourcePos
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: SourcePos -> SourcePos -> SourcePos
$cmin :: SourcePos -> SourcePos -> SourcePos
max :: SourcePos -> SourcePos -> SourcePos
$cmax :: SourcePos -> SourcePos -> SourcePos
>= :: SourcePos -> SourcePos -> Bool
$c>= :: SourcePos -> SourcePos -> Bool
> :: SourcePos -> SourcePos -> Bool
$c> :: SourcePos -> SourcePos -> Bool
<= :: SourcePos -> SourcePos -> Bool
$c<= :: SourcePos -> SourcePos -> Bool
< :: SourcePos -> SourcePos -> Bool
$c< :: SourcePos -> SourcePos -> Bool
compare :: SourcePos -> SourcePos -> Ordering
$ccompare :: SourcePos -> SourcePos -> Ordering
$cp1Ord :: Eq SourcePos
Ord)

{- | Create a new 'SourcePos' with the given source name,
line number and column number. -}
newPos :: SourceName -> Line -> Column -> SourcePos
newPos :: SourceName -> Line -> Line -> SourcePos
newPos = SourceName -> Line -> Line -> SourcePos
SourcePos

{- | Create a new 'SourcePos' with the given source name,
and line number and column number set to 1, the upper left. -}
initialPos :: SourceName -> SourcePos
initialPos :: SourceName -> SourcePos
initialPos SourceName
name = SourceName -> Line -> Line -> SourcePos
newPos SourceName
name Line
1 Line
1

-- | Increments the line number of a source position.
incSourceLine :: SourcePos -> Line -> SourcePos
incSourceLine :: SourcePos -> Line -> SourcePos
incSourceLine (SourcePos SourceName
name Line
line Line
column) Line
n
    = SourceName -> Line -> Line -> SourcePos
SourcePos SourceName
name (Line
line Line -> Line -> Line
forall a. Num a => a -> a -> a
+ Line
n) Line
column

-- | Increments the column number of a source position.
incSourceColumn :: SourcePos -> Column -> SourcePos
incSourceColumn :: SourcePos -> Line -> SourcePos
incSourceColumn (SourcePos SourceName
name Line
line Line
column) Line
n
    = SourceName -> Line -> Line -> SourcePos
SourcePos SourceName
name Line
line (Line
column Line -> Line -> Line
forall a. Num a => a -> a -> a
+ Line
n)

-- | Set the name of the source.
setSourceName :: SourcePos -> SourceName -> SourcePos
setSourceName :: SourcePos -> SourceName -> SourcePos
setSourceName (SourcePos SourceName
_name Line
line Line
column) SourceName
n = SourceName -> Line -> Line -> SourcePos
SourcePos SourceName
n Line
line Line
column

-- | Set the line number of a source position.
setSourceLine :: SourcePos -> Line -> SourcePos
setSourceLine :: SourcePos -> Line -> SourcePos
setSourceLine (SourcePos SourceName
name Line
_line Line
column) Line
n = SourceName -> Line -> Line -> SourcePos
SourcePos SourceName
name Line
n Line
column

-- | Set the column number of a source position.
setSourceColumn :: SourcePos -> Column -> SourcePos
setSourceColumn :: SourcePos -> Line -> SourcePos
setSourceColumn (SourcePos SourceName
name Line
line Line
_column) = SourceName -> Line -> Line -> SourcePos
SourcePos SourceName
name Line
line

{- | The expression @updatePosString pos s@ updates the source position
@pos@ by calling 'updatePosChar' on every character in @s@, ie.
@foldl updatePosChar pos string@. -}
updatePosString :: SourcePos -> String -> SourcePos
updatePosString :: SourcePos -> SourceName -> SourcePos
updatePosString SourcePos
pos SourceName
string = SourcePos -> SourcePos
forcePos ((SourcePos -> Char -> SourcePos)
-> SourcePos -> SourceName -> SourcePos
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl SourcePos -> Char -> SourcePos
updatePosChar SourcePos
pos SourceName
string)

updatePosChar :: SourcePos -> Char -> SourcePos
updatePosChar :: SourcePos -> Char -> SourcePos
updatePosChar (SourcePos SourceName
name Line
line Line
column) Char
c = SourcePos -> SourcePos
forcePos (SourcePos -> SourcePos) -> SourcePos -> SourcePos
forall a b. (a -> b) -> a -> b
$ case Char
c of
  Char
'\n' -> SourceName -> Line -> Line -> SourcePos
SourcePos SourceName
name (Line
line Line -> Line -> Line
forall a. Num a => a -> a -> a
+ Line
1) Line
1
  Char
'\t' -> SourceName -> Line -> Line -> SourcePos
SourcePos SourceName
name Line
line (Line
column Line -> Line -> Line
forall a. Num a => a -> a -> a
+ Line
8 Line -> Line -> Line
forall a. Num a => a -> a -> a
- ((Line
column Line -> Line -> Line
forall a. Num a => a -> a -> a
- Line
1) Line -> Line -> Line
forall a. Integral a => a -> a -> a
`mod` Line
8))
  Char
_ -> SourceName -> Line -> Line -> SourcePos
SourcePos SourceName
name Line
line (Line
column Line -> Line -> Line
forall a. Num a => a -> a -> a
+ Line
1)

forcePos :: SourcePos -> SourcePos
forcePos :: SourcePos -> SourcePos
forcePos pos :: SourcePos
pos@(SourcePos SourceName
_name Line
line Line
column) = Line -> SourcePos -> SourcePos
seq Line
line (Line -> SourcePos -> SourcePos
seq Line
column SourcePos
pos)

{- ---------------------------------------------------------
Show positions
--------------------------------------------------------- -}
instance Show SourcePos where
  show :: SourcePos -> SourceName
show (SourcePos SourceName
name Line
line Line
column)
    | SourceName -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null SourceName
name = SourceName
showLineColumn
    | Bool
otherwise = SourceName
"\"" SourceName -> ShowS
forall a. [a] -> [a] -> [a]
++ SourceName
name SourceName -> ShowS
forall a. [a] -> [a] -> [a]
++ SourceName
"\" " SourceName -> ShowS
forall a. [a] -> [a] -> [a]
++ SourceName
showLineColumn
    where
      showLineColumn :: SourceName
showLineColumn = SourceName
"(line " SourceName -> ShowS
forall a. [a] -> [a] -> [a]
++ Line -> SourceName
forall a. Show a => a -> SourceName
show Line
line SourceName -> ShowS
forall a. [a] -> [a] -> [a]
++
                          SourceName
", column " SourceName -> ShowS
forall a. [a] -> [a] -> [a]
++ Line -> SourceName
forall a. Show a => a -> SourceName
show Line
column SourceName -> ShowS
forall a. [a] -> [a] -> [a]
++
                          SourceName
")"