packages feed

ddc-source-tetra-0.4.3.1: DDC/Source/Tetra/Lexer.hs

-- | Lexer for Source Tetra tokens.
module DDC.Source.Tetra.Lexer
        ( Name (..)
        , lexModuleString)
where
import DDC.Source.Tetra.Prim
import DDC.Core.Lexer
import DDC.Data.Pretty
import Control.DeepSeq
import Data.Char
import Data.Text                (Text)
import qualified Data.Text      as Text


---------------------------------------------------------------------------------------------------
-- | Union of all names that we detect during lexing.
data Name
        -- | A user defined variable.
        = NameVar        !Text

        -- | A user defined constructor.
        | NameCon        !Text

        -- | Primitive type names.
        | NamePrimType   !PrimType

        -- | Primitive literal values.
        | NamePrimValLit !PrimLit

        -- | Primitive operator values.
        | NamePrimValOp  !PrimVal
        deriving (Eq, Ord, Show)


---------------------------------------------------------------------------------------------------
instance Pretty Name where
 ppr nn
  = case nn of
        NameVar  v              -> text (Text.unpack v)
        NameCon  c              -> text (Text.unpack c)
        NamePrimType p          -> ppr p
        NamePrimValLit p        -> ppr p
        NamePrimValOp  p        -> ppr p


instance NFData Name where
 rnf nn
  = case nn of
        NameVar s               -> rnf s
        NameCon s               -> rnf s
        NamePrimType p          -> rnf p
        NamePrimValLit p        -> rnf p
        NamePrimValOp  p        -> rnf p


-- | Read the name of a variable, constructor or literal.
readName :: String -> Maybe Name
readName str
        -- Primitive names.
        | Just n        <- readPrimType str
        = Just $ NamePrimType   n

        | Just n        <- readPrimLit str
        = Just $ NamePrimValLit n

        | Just n        <- readPrimVal str
        = Just $ NamePrimValOp  n

        -- Constructors.
        | c : _         <- str
        , isUpper c
        = Just $ NameCon (Text.pack str)

        -- Variables.
        | c : _         <- str
        , isVarStart c      
        = Just $ NameVar (Text.pack str)

        | otherwise
        = Nothing


---------------------------------------------------------------------------------------------------
-- | Lex a string to tokens, using primitive names.
--
--   The first argument gives the starting source line number.
--
--   We're currently re-using the lexer for the core language, which has
--   *mostly* the same lexical structure as Source Tetra.
--   There are a few tokens accepted by one language but not the other,
--   but it'll do for now.
--
lexModuleString :: String -> Int -> String -> [Located (Token Name)]
lexModuleString sourceName lineStart str
 = map rn $ lexModuleWithOffside sourceName lineStart str
 where 
        rn (Located sp strTok)
         = case renameToken readName strTok of
                Just t' -> Located sp t'
                Nothing -> Located sp (KErrorJunk "lexical error")