ampersand-3.1.0: src/Database/Design/Ampersand/Input/ADL1/LexerMessage.hs
{- Based on module LexerMessage from Helium (GPL license) -}
module Database.Design.Ampersand.Input.ADL1.LexerMessage
( LexerError(..)
, LexerErrorInfo(..)
, LexerWarning(..)
, LexerWarningInfo(..)
, keepOneTabWarning
, showLexerErrorInfo
, showLexerWarningInfo
) where
import Database.Design.Ampersand.Input.ADL1.FilePos(FilePos)
import qualified Database.Design.Ampersand.Input.ADL1.LexerTexts as Texts
-- | Defines a lexer error
data LexerError = LexerError FilePos LexerErrorInfo -- ^ The lexer file position and error information
deriving(Show)
-- | Defines the different lexer error types
data LexerErrorInfo
-- | The comment was not terminated
= UnterminatedComment
-- | The purpose statement was not terminated
| UnterminatedPurpose
-- | The atom was not terminated
| UnterminatedAtom
-- | The character was unexpected
| UnexpectedChar Char
-- | The string was not terminated
| NonTerminatedString String
-- | In UnexpectedClose, first char is the closing bracket we see,
-- second char is the closing bracket we would like to see first
-- e.g. [(1,3] => UnexpectedClose ']' ... ')'
| TooManyClose Char
-- | An unexpected closing bracket was found
| UnexpectedClose Char FilePos Char
-- | Brackets were not closed at the end of the file
| StillOpenAtEOF [(FilePos, Char)]
-- | DateTime not conforming to ISO 8601 format
| ProblematicISO8601DateTime
deriving(Show)
-- | Converts the error information into a list of error messages
showLexerErrorInfo :: LexerErrorInfo -- ^ The error information
-> [String] -- ^ The error messages
showLexerErrorInfo info =
case info of
UnterminatedComment -> [ Texts.lexerUnterminatedComment ]
UnterminatedPurpose -> [ Texts.lexerUnterminatedPurpose ]
UnterminatedAtom -> [ Texts.lexerUnterminatedAtom ]
UnexpectedChar c -> [ Texts.lexerUnexpectedChar c ]
NonTerminatedString _ -> [ Texts.lexerNonTerminatedString, correctStrings ]
TooManyClose c -> [ Texts.lexerTooManyClose c ]
UnexpectedClose c1 _ c2 -> Texts.lexerUnexpectedClose c1 c2
StillOpenAtEOF [b] -> [ Texts.lexerStillOpenAtEOF [ show (snd b) ] ]
StillOpenAtEOF bs -> [ Texts.lexerStillOpenAtEOF (reverse (map (show.snd) bs)) ]
-- 'reverse' because positions will be sorted and brackets are
-- reported in reversed order
ProblematicISO8601DateTime -> [ Texts.lexerProblematicISO8601DateTime ]
correctStrings :: String
correctStrings = Texts.lexerCorrectStrings
-- | Defines a lexer warning
data LexerWarning =
LexerWarning FilePos LexerWarningInfo -- ^ The lexer file position and warning information
-- | Defines the different lexer warning types
data LexerWarningInfo
= TabCharacter -- ^ Tab character was encountered
| NestedComment FilePos -- ^ Nested comment was encountered
| UtfChar -- ^ The UTF BOM character was found
| CommentOperator -- ^ Syntax coloring cannot handle names containing --
-- | Converts the warning information into a list of warning messages
showLexerWarningInfo :: LexerWarningInfo -- ^ The warning information
-> [String] -- ^ The warning messages
showLexerWarningInfo info =
case info of
TabCharacter -> Texts.lexerTabCharacter
NestedComment _ -> Texts.lexerNestedComment
UtfChar -> Texts.lexerUtfChar
CommentOperator -> Texts.lexerCommentOperator
-- | Generates a TabCharacter warning
keepOneTabWarning :: [LexerWarning] -- ^ The old warnings
-> [LexerWarning] -- ^ The new warnings
keepOneTabWarning = keepOneTab True
where
keepOneTab isFirst (warning@(LexerWarning _ TabCharacter):rest)
| isFirst = warning : keepOneTab False rest
| otherwise = keepOneTab isFirst rest
keepOneTab isFirst (warning:rest) =
warning : keepOneTab isFirst rest
keepOneTab _ [] = []