Skip to content

Instantly share code, notes, and snippets.

@philipnilsson
Last active August 29, 2015 13:56
Show Gist options
  • Save philipnilsson/9075346 to your computer and use it in GitHub Desktop.
Save philipnilsson/9075346 to your computer and use it in GitHub Desktop.
import Text.Parsec
import Control.Applicative hiding ((<|>))
import qualified Data.Map as M
import Data.Either (partitionEithers)
import Data.List (intercalate)
import System.IO (hPutStrLn, stderr)
data Word = Splice String | Word String
deriving (Ord, Eq, Show)
-- Lexing (Tokenization)
wordToken = many1 alphaNum
splice = Splice <$> between (char '$') (char '$') wordToken
word = Word <$> wordToken
templateText = (splice <|> word) `sepBy` spaces
-- Parsing
evaluateTemplate :: M.Map String String -> [Word] -> Either [String] [String]
evaluateTemplate dict words =
case searched of
([], words) -> Right words
(missing, _) -> Left missing
where searched = partitionEithers $ map (lookupWord dict) words
lookupWord :: M.Map String String -> Word -> Either String String
lookupWord _ (Word w) = Right w
lookupWord dict (Splice w) =
case M.lookup w dict of
Nothing -> Left w
Just wd -> Right wd
-- Input dictionary
dictionary :: M.Map String String
dictionary = M.fromList [ ("foo", "bar"), ("baz", "buzz") ]
-- Driver function
main = do
toTranslate <- getLine
case parse templateText "" toTranslate of
Left err -> hPutStrLn stderr $ "Parse error: " ++ show err
Right res ->
case evaluateTemplate dictionary res of
Left errs -> hPutStrLn stderr $ "Token(s) not found: " ++ show errs
Right r -> putStrLn $ "Parse success: " ++ intercalate " " r
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment