megaparsec/Text/Megaparsec/Pos.hs
2015-08-13 00:02:49 +06:00

128 lines
3.7 KiB
Haskell
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- |
-- Module : Text.Megaparsec.Pos
-- Copyright : © 2015 Megaparsec contributors
-- © 2007 Paolo Martini
-- © 19992001 Daan Leijen
-- License : BSD3
--
-- Maintainer : Mark Karpov <markkarpov@opmbx.org>
-- Stability : experimental
-- Portability : portable
--
-- Textual source positions.
module Text.Megaparsec.Pos
( SourceName
, Line
, Column
, SourcePos
, sourceLine
, sourceColumn
, sourceName
, incSourceLine
, incSourceColumn
, setSourceLine
, setSourceColumn
, setSourceName
, newPos
, initialPos
, updatePosChar
, updatePosString )
where
import Data.Data (Data)
import Data.List (foldl')
import Data.Typeable (Typeable)
-- | @SourceName@ is a file name, in our case it's @String@.
type SourceName = String
-- | @Line@ represents line number, 1 is the minimum.
type Line = Int
-- | @Column@ is column number, 1 is the the minimum.
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
{ -- | Extract the name of the source from a source position.
sourceName :: SourceName
-- | Extract the line number from a source position.
, sourceLine :: !Line
-- | Extract the column number from a source position.
, sourceColumn :: !Column }
deriving (Eq, Ord, Data, Typeable)
instance Show SourcePos where
show (SourcePos n l c)
| null n = showLC
| otherwise = "\"" ++ n ++ "\" " ++ showLC
where showLC = "line " ++ show l ++ ", column " ++ show c
-- | Create a new 'SourcePos' with the given source name,
-- line number and column number.
newPos :: SourceName -> Line -> Column -> SourcePos
newPos = 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 name = newPos name 1 1
-- | Increment the line number of a source position.
incSourceLine :: SourcePos -> Line -> SourcePos
incSourceLine (SourcePos n l c) d = SourcePos n (l + d) c
-- | Increments the column number of a source position.
incSourceColumn :: SourcePos -> Column -> SourcePos
incSourceColumn (SourcePos n l c) d = SourcePos n l (c + d)
-- | Set the name of the source.
setSourceName :: SourcePos -> SourceName -> SourcePos
setSourceName (SourcePos _ l c) n = SourcePos n l c
-- | Set the line number of a source position.
setSourceLine :: SourcePos -> Line -> SourcePos
setSourceLine (SourcePos n _ c) l = SourcePos n l c
-- | Set the column number of a source position.
setSourceColumn :: SourcePos -> Column -> SourcePos
setSourceColumn (SourcePos n l _) = SourcePos n l
-- | Update a source position given a character. If the character is a
-- newline (\'\\n\') the line number is incremented by 1. If the character
-- is carriage return (\'\\r\') the line number is unaltered, but column
-- number is reset to 1. If the character is a tab (\'\\t\') the column
-- number is incremented to the nearest 8'th column, i.e. @column + 8 -
-- ((column - 1) \`rem\` 8)@. In all other cases, the column is incremented
-- by 1.
updatePosChar :: SourcePos -> Char -> SourcePos
updatePosChar (SourcePos n l c) ch =
case ch of
'\n' -> SourcePos n (l + 1) 1
'\r' -> SourcePos n l 1
'\t' -> SourcePos n l (c + 8 - ((c - 1) `rem` 8))
_ -> SourcePos n l (c + 1)
-- | The expression @updatePosString pos s@ updates the source position
-- @pos@ by calling 'updatePosChar' on every character in @s@, i.e. @foldl
-- updatePosChar pos string@.
updatePosString :: SourcePos -> String -> SourcePos
updatePosString = foldl' updatePosChar