ampersand-3.1.0: src/Database/Design/Ampersand/Input/ADL1/LexerToken.hs
module Database.Design.Ampersand.Input.ADL1.LexerToken
( Token(..)
, Lexeme(..)
, lexemeText
, initPos
, FilePos(..)
) where
import Database.Design.Ampersand.Input.ADL1.FilePos (FilePos(..), initPos)
import Text.Parsec()
import Data.Time.Calendar
import Data.Time.Clock
import Data.Time.LocalTime() -- for instance Show UTCTime
-- | The Ampersand token
data Token = Tok { tokLex :: Lexeme -- ^ The lexeme
, tokPos :: FilePos -- ^ The position where the lexeme was found
}
instance Show Token where
show (Tok lx p) = show lx ++ " " ++ show p
-- | The Ampersand Lexemes
data Lexeme = LexSymbol Char -- ^ A symbol
| LexOperator String -- ^ An operator
| LexKeyword String -- ^ A keyword
| LexString String -- ^ A quoted string
| LexExpl String -- ^ An explanation
| LexSingleton String -- ^ An atomvalue in an Expression
| LexDecimal Int -- ^ A decimal number
| LexFloat Double -- ^ A decimal floating point thing
| LexOctal Int -- ^ An octal number
| LexHex Int -- ^ A hexadecimal number
| LexConId String -- ^ An upper case identifier
| LexVarId String -- ^ A lower case identifier
| LexDateTime UTCTime -- ^ A date-time
| LexDate Day -- ^ A date
deriving (Eq, Ord)
instance Show Lexeme where
show x = case x of
LexSymbol val -> "symbol " ++ "'" ++ [val] ++ "'"
LexOperator val -> "operator " ++ "'" ++ val ++ "'"
LexKeyword val -> "keyword " ++ show val
LexString val -> "string " ++ "\"" ++ val ++ "\""
LexExpl val -> "explanation " ++ "{+" ++ val ++ "+}"
LexSingleton val -> "singleton " ++ "'" ++ val ++ "'"
LexDecimal _ -> "integer " ++ lexemeText x
LexFloat _ -> "float " ++ lexemeText x
LexOctal _ -> "octal " ++ lexemeText x
LexHex _ -> "hexadecimal " ++ lexemeText x
LexVarId val -> "lower case identifier " ++ val
LexConId val -> "upper case identifier " ++ val
LexDateTime _ -> "iso 8601 date time " ++ lexemeText x
LexDate _ -> "iso 8601 date " ++ lexemeText x
-- A Stream instance is responsible for maintaining the "position within the stream" in the stream state (Token).
-- This is trivial unless you are using the monad in a non-trivial way.
-- instance (Monad m) => Stream [Token] m Char where
-- uncons :: (Monad m) => [Token] -> m (Maybe (Char, [Token]))
-- uncons [] = return $ Nothing
-- uncons (t:ts) = return $ Just (t,ts)
-- | Retrieves the text from a lexeme
lexemeText :: Lexeme -- ^ The lexeme
-> String -- ^ The text contained in the lexeme
lexemeText l = case l of
LexSymbol val -> [val]
LexOperator val -> val
LexKeyword val -> val
LexString val -> val
LexExpl val -> val
LexSingleton val -> val
LexDecimal val -> show val
LexFloat val -> show val
LexOctal val -> "0o" ++ toBase 8 val
LexHex val -> "0x" ++ toBase 16 val
LexConId val -> val
LexVarId val -> val
LexDateTime val -> show val
LexDate val -> show val
toBase :: Integral a => Show a => a -> a -> String
toBase b x = conv x ""
where conv 0 str = str
conv n str = conv (n `div` b) (show (n `mod` b) ++ str)