-- | Parsers for unit/module identifiers
module GHC.Unit.Parser
   ( parseUnit
   , parseUnitId
   , parseHoleyModule
   , parseModSubst
   )
where

import GHC.Prelude

import GHC.Unit.Types
import GHC.Data.FastString

import qualified Text.ParserCombinators.ReadP as Parse
import Text.ParserCombinators.ReadP (ReadP, (<++))
import Data.Char (isAlphaNum)

import Language.Haskell.Syntax.Module.Name (ModuleName, parseModuleName)

parseUnit :: ReadP Unit
parseUnit :: ReadP Unit
parseUnit = ReadP Unit
parseVirtUnitId ReadP Unit -> ReadP Unit -> ReadP Unit
forall a. ReadP a -> ReadP a -> ReadP a
<++ ReadP Unit
parseDefUnitId
  where
    parseVirtUnitId :: ReadP Unit
parseVirtUnitId = do
        uid   <- ReadP UnitId
parseUnitId
        insts <- parseModSubst
        return (mkVirtUnit uid insts)
    parseDefUnitId :: ReadP Unit
parseDefUnitId = do
        s <- ReadP UnitId
parseUnitId
        return (RealUnit (Definite s))

parseUnitId :: ReadP UnitId
parseUnitId :: ReadP UnitId
parseUnitId = do
   s <- (Char -> Bool) -> ReadP String
Parse.munch1 (\Char
c -> Char -> Bool
isAlphaNum Char
c Bool -> Bool -> Bool
|| Char
c Char -> String -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
"-_.+")
   return (UnitId (mkFastString s))

parseHoleyModule :: ReadP Module
parseHoleyModule :: ReadP Module
parseHoleyModule = ReadP Module
forall {uid}. ReadP (GenModule (GenUnit uid))
parseModuleVar ReadP Module -> ReadP Module -> ReadP Module
forall a. ReadP a -> ReadP a -> ReadP a
<++ ReadP Module
parseModule
    where
      parseModuleVar :: ReadP (GenModule (GenUnit uid))
parseModuleVar = do
        _ <- Char -> ReadP Char
Parse.char Char
'<'
        modname <- parseModuleName
        _ <- Parse.char '>'
        return (Module HoleUnit modname)
      parseModule :: ReadP Module
parseModule = do
        uid <- ReadP Unit
parseUnit
        _ <- Parse.char ':'
        modname <- parseModuleName
        return (Module uid modname)

parseModSubst :: ReadP [(ModuleName, Module)]
parseModSubst :: ReadP [(ModuleName, Module)]
parseModSubst = ReadP Char
-> ReadP Char
-> ReadP [(ModuleName, Module)]
-> ReadP [(ModuleName, Module)]
forall open close a.
ReadP open -> ReadP close -> ReadP a -> ReadP a
Parse.between (Char -> ReadP Char
Parse.char Char
'[') (Char -> ReadP Char
Parse.char Char
']')
      (ReadP [(ModuleName, Module)] -> ReadP [(ModuleName, Module)])
-> (ReadP (ModuleName, Module) -> ReadP [(ModuleName, Module)])
-> ReadP (ModuleName, Module)
-> ReadP [(ModuleName, Module)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ReadP (ModuleName, Module)
 -> ReadP Char -> ReadP [(ModuleName, Module)])
-> ReadP Char
-> ReadP (ModuleName, Module)
-> ReadP [(ModuleName, Module)]
forall a b c. (a -> b -> c) -> b -> a -> c
flip ReadP (ModuleName, Module)
-> ReadP Char -> ReadP [(ModuleName, Module)]
forall a sep. ReadP a -> ReadP sep -> ReadP [a]
Parse.sepBy (Char -> ReadP Char
Parse.char Char
',')
      (ReadP (ModuleName, Module) -> ReadP [(ModuleName, Module)])
-> ReadP (ModuleName, Module) -> ReadP [(ModuleName, Module)]
forall a b. (a -> b) -> a -> b
$ do k <- ReadP ModuleName
parseModuleName
           _ <- Parse.char '='
           v <- parseHoleyModule
           return (k, v)