2008-01-13 20:53:15 +03:00
|
|
|
|
-- |
|
2015-08-01 19:24:45 +03:00
|
|
|
|
-- Module : Text.Megaparsec.Pos
|
|
|
|
|
-- Copyright : © 2015 Megaparsec contributors
|
2015-07-30 19:20:37 +03:00
|
|
|
|
-- © 2007 Paolo Martini
|
|
|
|
|
-- © 1999–2001 Daan Leijen
|
2015-07-28 16:32:19 +03:00
|
|
|
|
-- License : BSD3
|
|
|
|
|
--
|
|
|
|
|
-- Maintainer : Mark Karpov <markkarpov@opmbx.org>
|
2015-07-29 11:38:32 +03:00
|
|
|
|
-- Stability : experimental
|
2008-01-13 20:53:15 +03:00
|
|
|
|
-- Portability : portable
|
2015-07-28 16:32:19 +03:00
|
|
|
|
--
|
2008-01-13 20:53:15 +03:00
|
|
|
|
-- Textual source positions.
|
|
|
|
|
|
2015-08-01 19:24:45 +03:00
|
|
|
|
module Text.Megaparsec.Pos
|
2015-07-28 16:32:19 +03:00
|
|
|
|
( SourceName
|
|
|
|
|
, Line
|
|
|
|
|
, Column
|
2008-01-13 20:53:15 +03:00
|
|
|
|
, SourcePos
|
2015-07-28 16:32:19 +03:00
|
|
|
|
, sourceLine
|
|
|
|
|
, sourceColumn
|
|
|
|
|
, sourceName
|
|
|
|
|
, incSourceLine
|
|
|
|
|
, incSourceColumn
|
|
|
|
|
, setSourceLine
|
|
|
|
|
, setSourceColumn
|
|
|
|
|
, setSourceName
|
|
|
|
|
, newPos
|
|
|
|
|
, initialPos
|
|
|
|
|
, updatePosChar
|
|
|
|
|
, updatePosString )
|
|
|
|
|
where
|
2008-01-13 20:53:15 +03:00
|
|
|
|
|
2010-09-08 09:37:47 +04:00
|
|
|
|
import Data.Data (Data)
|
2015-07-29 11:38:32 +03:00
|
|
|
|
import Data.List (foldl')
|
2010-09-08 09:37:47 +04:00
|
|
|
|
import Data.Typeable (Typeable)
|
2008-12-26 11:29:54 +03:00
|
|
|
|
|
2015-07-30 21:36:54 +03:00
|
|
|
|
-- | @SourceName@ is a file name, in our case it's @String@.
|
2008-01-13 20:53:15 +03:00
|
|
|
|
|
|
|
|
|
type SourceName = String
|
2015-07-30 21:36:54 +03:00
|
|
|
|
|
|
|
|
|
-- | @Line@ represents line number, 1 is the minimum.
|
|
|
|
|
|
|
|
|
|
type Line = Int
|
|
|
|
|
|
|
|
|
|
-- | @Column@ is column number, 1 is the the minimum.
|
|
|
|
|
|
|
|
|
|
type Column = Int
|
2008-01-13 20:53:15 +03:00
|
|
|
|
|
2008-01-22 07:16:19 +03:00
|
|
|
|
-- | The abstract data type @SourcePos@ represents source positions. It
|
2015-07-28 16:32:19 +03:00
|
|
|
|
-- 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.
|
2008-01-22 07:16:19 +03:00
|
|
|
|
|
2015-07-29 11:38:32 +03:00
|
|
|
|
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
|
2015-08-03 17:45:09 +03:00
|
|
|
|
where showLC = "line " ++ show l ++ ", column " ++ show c
|
2008-01-13 20:53:15 +03:00
|
|
|
|
|
2008-01-22 07:16:19 +03:00
|
|
|
|
-- | Create a new 'SourcePos' with the given source name,
|
|
|
|
|
-- line number and column number.
|
|
|
|
|
|
2008-01-13 20:53:15 +03:00
|
|
|
|
newPos :: SourceName -> Line -> Column -> SourcePos
|
2015-07-28 16:32:19 +03:00
|
|
|
|
newPos = SourcePos
|
2008-01-13 20:53:15 +03:00
|
|
|
|
|
2008-01-22 07:16:19 +03:00
|
|
|
|
-- | Create a new 'SourcePos' with the given source name,
|
|
|
|
|
-- and line number and column number set to 1, the upper left.
|
|
|
|
|
|
2008-01-13 20:53:15 +03:00
|
|
|
|
initialPos :: SourceName -> SourcePos
|
2015-07-29 11:38:32 +03:00
|
|
|
|
initialPos name = newPos name 1 1
|
2008-01-22 07:16:19 +03:00
|
|
|
|
|
2015-07-29 11:38:32 +03:00
|
|
|
|
-- | Increment the line number of a source position.
|
2008-01-22 07:16:19 +03:00
|
|
|
|
|
2008-01-13 20:53:15 +03:00
|
|
|
|
incSourceLine :: SourcePos -> Line -> SourcePos
|
2015-07-29 11:38:32 +03:00
|
|
|
|
incSourceLine (SourcePos n l c) d = SourcePos n (l + d) c
|
2008-01-13 20:53:15 +03:00
|
|
|
|
|
2015-07-28 16:32:19 +03:00
|
|
|
|
-- | Increments the column number of a source position.
|
2008-01-22 07:16:19 +03:00
|
|
|
|
|
2008-01-13 20:53:15 +03:00
|
|
|
|
incSourceColumn :: SourcePos -> Column -> SourcePos
|
2015-07-29 11:38:32 +03:00
|
|
|
|
incSourceColumn (SourcePos n l c) d = SourcePos n l (c + d)
|
2008-01-13 20:53:15 +03:00
|
|
|
|
|
2008-01-22 07:16:19 +03:00
|
|
|
|
-- | Set the name of the source.
|
|
|
|
|
|
2008-01-13 20:53:15 +03:00
|
|
|
|
setSourceName :: SourcePos -> SourceName -> SourcePos
|
2015-07-29 11:38:32 +03:00
|
|
|
|
setSourceName (SourcePos _ l c) n = SourcePos n l c
|
2008-01-13 20:53:15 +03:00
|
|
|
|
|
2015-07-28 16:32:19 +03:00
|
|
|
|
-- | Set the line number of a source position.
|
2008-01-22 07:16:19 +03:00
|
|
|
|
|
2008-01-13 20:53:15 +03:00
|
|
|
|
setSourceLine :: SourcePos -> Line -> SourcePos
|
2015-07-29 11:38:32 +03:00
|
|
|
|
setSourceLine (SourcePos n _ c) l = SourcePos n l c
|
2008-01-13 20:53:15 +03:00
|
|
|
|
|
2015-07-28 16:32:19 +03:00
|
|
|
|
-- | Set the column number of a source position.
|
2008-01-22 07:16:19 +03:00
|
|
|
|
|
2008-01-13 20:53:15 +03:00
|
|
|
|
setSourceColumn :: SourcePos -> Column -> SourcePos
|
2015-07-29 11:38:32 +03:00
|
|
|
|
setSourceColumn (SourcePos n l _) = SourcePos n l
|
2008-01-13 20:53:15 +03:00
|
|
|
|
|
2008-01-22 07:16:19 +03:00
|
|
|
|
-- | Update a source position given a character. If the character is a
|
2015-08-03 10:20:15 +03:00
|
|
|
|
-- 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.
|
2015-07-29 11:38:32 +03:00
|
|
|
|
|
|
|
|
|
updatePosChar :: SourcePos -> Char -> SourcePos
|
|
|
|
|
updatePosChar (SourcePos n l c) ch =
|
|
|
|
|
case ch of
|
|
|
|
|
'\n' -> SourcePos n (l + 1) 1
|
2015-08-03 10:20:15 +03:00
|
|
|
|
'\r' -> SourcePos n l 1
|
|
|
|
|
'\t' -> SourcePos n l (c + 8 - ((c - 1) `rem` 8))
|
2015-07-29 11:38:32 +03:00
|
|
|
|
_ -> SourcePos n l (c + 1)
|
2015-08-03 10:20:15 +03:00
|
|
|
|
|
|
|
|
|
-- | 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
|