perga/lib/Preprocessor.hs

38 lines
1.3 KiB
Haskell
Raw Normal View History

module Preprocessor where
import Control.Monad.Except
import Control.Monad.IO.Class
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import System.FilePath
import System.IO
newtype PreprocessorError = ParseError Text
instance Show PreprocessorError where
show (ParseError t) = "Preprocessor error on line '" ++ show t ++ "'"
type Result = Either PreprocessorError
type ResultIO = ExceptT PreprocessorError IO
concatMapM :: (Applicative f) => (a -> f Text) -> [a] -> f Text
concatMapM _ [] = pure mempty
concatMapM f (x : xs) = ((<>) . (<> "\n") <$> f x) <*> concatMapM f xs
preprocess :: String -> ResultIO Text
preprocess filename = do
handle <- liftIO $ openFile filename ReadMode
text <- liftIO $ T.lines <$> TIO.hGetContents handle
result <- concatMapM (preprocessLine $ takeDirectory filename) text
liftIO $ putStrLn $ "loading: " ++ filename
pure result
parseInclude :: Text -> Result Text
parseInclude line = maybe (Left $ ParseError line) pure $ T.stripPrefix "@include " line
preprocessLine :: FilePath -> Text -> ResultIO Text
preprocessLine base line
| "@include " `T.isPrefixOf` line = liftEither (parseInclude line) >>= preprocess . normalise . (base </>) . T.unpack
| otherwise = pure line