module Language.Cimple.IO ( parseFile , parseText ) where import Control.Monad.State.Lazy (State, get, put, runState) import qualified Data.ByteString as BS import qualified Data.Compact as Compact import Data.Map.Strict (Map) import qualified Data.Map.Strict as Map import Data.Text (Text) import qualified Data.Text as Text import qualified Data.Text.Encoding as Text import Language.Cimple.AST (Node (..)) import Language.Cimple.Lexer (Lexeme, runAlex) import Language.Cimple.Parser (parseCimple) type CompactState a = State (Map String Text) a cacheText :: String -> CompactState Text cacheText s = do m <- get case Map.lookup s m of Nothing -> do let text = Text.pack s put $ Map.insert s text m return text Just text -> return text process :: [Node (Lexeme String)] -> IO [Node (Lexeme Text)] process stringAst = do let (textAst, _) = runState (mapM (mapM (mapM cacheText)) stringAst) Map.empty Compact.getCompact <$> Compact.compactWithSharing textAst parseText :: Text -> IO (Either String [Node (Lexeme Text)]) parseText contents = mapM process res where res :: Either String [Node (Lexeme String)] res = runAlex (Text.unpack contents) parseCimple parseFile :: FilePath -> IO (Either String [Node (Lexeme Text)]) parseFile source = do putStrLn $ "Processing " ++ source contents <- Text.decodeUtf8 <$> BS.readFile source parseText contents