-
Notifications
You must be signed in to change notification settings - Fork 76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide context parsing in the mkMessage
function
#283
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
{-# LANGUAGE TypeFamilies #-} | ||
{-# LANGUAGE MultiParamTypeClasses #-} | ||
{-# LANGUAGE FlexibleInstances #-} | ||
{-# LANGUAGE FlexibleContexts #-} | ||
{-# LANGUAGE TypeSynonymInstances #-} | ||
{-# LANGUAGE ExistentialQuantification #-} | ||
|
||
|
@@ -62,7 +63,6 @@ module Text.Shakespeare.I18N | |
) where | ||
|
||
import Language.Haskell.TH.Syntax hiding (makeRelativeToProject) | ||
import Control.Applicative ((<$>)) | ||
import Control.Monad (filterM, forM) | ||
import Data.Text (Text, pack, unpack) | ||
import System.Directory | ||
|
@@ -72,12 +72,12 @@ import Data.List (isSuffixOf, sortBy, foldl') | |
import qualified Data.Map as Map | ||
import qualified Data.ByteString as S | ||
import Data.Text.Encoding (decodeUtf8) | ||
import Data.Char (isSpace, toLower, toUpper) | ||
import Data.Char (isSpace, toLower, toUpper, isLower) | ||
import Data.Ord (comparing) | ||
import Text.Shakespeare.Base (Deref (..), Ident (..), parseHash, derefToExp) | ||
import Text.ParserCombinators.Parsec (parse, many, eof, many1, noneOf, (<|>)) | ||
import Text.ParserCombinators.Parsec (parse, many, eof, many1, noneOf, (<|>), | ||
string, spaces, char, option, alphaNum, sepBy1, try) | ||
import Control.Arrow ((***)) | ||
import Data.Monoid (mempty, mappend) | ||
import qualified Data.Text as T | ||
import Data.String (IsString (fromString)) | ||
|
||
|
@@ -165,22 +165,79 @@ mkMessageCommon genType prefix postfix master dt rawFolder lang = do | |
Nothing -> error $ "Did not find main language file: " ++ unpack lang | ||
Just def -> toSDefs def | ||
mapM_ (checkDef sdef) $ map snd contents' | ||
let mname = mkName $ dt ++ postfix | ||
c1 <- fmap concat $ mapM (toClauses prefix dt) contents' | ||
c2 <- mapM (sToClause prefix dt) sdef | ||
let mname = mkName $ dt2 ++ postfix | ||
c1 <- fmap concat $ mapM (toClauses prefix dt2 ) contents' | ||
c2 <- mapM (sToClause prefix dt2) sdef | ||
c3 <- defClause | ||
return $ | ||
( if genType | ||
then ((DataD [] mname [] Nothing (map (toCon dt) sdef) []) :) | ||
then ((DataD [] mname [] Nothing (map (toCon dt2) sdef) []) :) | ||
else id) | ||
[ instanceD | ||
[] | ||
(ConT ''RenderMessage `AppT` (ConT $ mkName master) `AppT` ConT mname) | ||
cxt -- Here the parsed context should be added, otherwise [] | ||
(ConT ''RenderMessage `AppT` (if ' ' `elem` master' | ||
then let (ts, us) = break (== ' ') . | ||
filter (\x -> x /= '(' && x /= ')') $ master' in | ||
let us1 = filter (/= ' ') us in ParensT (ConT (mkName ts) | ||
`AppT` VarT (mkName us1)) else ConT $ | ||
mkName master') `AppT` ConT mname) | ||
[ FunD (mkName "renderMessage") $ c1 ++ c2 ++ [c3] | ||
] | ||
] | ||
|
||
toClauses :: String -> String -> (Lang, [Def]) -> Q [Clause] | ||
where (dt1, cxt0) = case (parse parseName "" dt) of | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's improve the formatting of all the new parsing code here. |
||
Left err -> error $ show err | ||
Right x -> x | ||
dt2 = concat . take 1 $ dt1 | ||
master' | cxt0 == [] = master | ||
| otherwise = (\xss -> if length xss > 1 | ||
then '(':unwords xss ++ ")" | ||
else concat . take 1 $ xss) . fst $ | ||
(case parse parseName "" master of | ||
Left err -> error $ show err | ||
Right x -> x) | ||
cxt = fmap (\(c:rest) -> foldl' (\acc v -> acc `AppT` nameToType v) | ||
(ConT $ mkName c) rest) cxt0 | ||
|
||
nameToType :: String -> Type -- Is taken from the | ||
-- https://hackage.haskell.org/package/yesod-core-1.6.26.0/docs/src/Yesod.Routes.Parse.html#nameToType | ||
nameToType t = if isTvar t | ||
then VarT $ mkName t | ||
else ConT $ mkName t | ||
|
||
isTvar :: String -> Bool -- Is taken from the | ||
-- https://hackage.haskell.org/package/yesod-core-1.6.26.0/docs/src/Yesod.Routes.Parse.html#isTvar | ||
isTvar (h:_) = isLower h | ||
isTvar _ = False | ||
|
||
parseName = do | ||
cxt' <- option [] parseContext | ||
args <- many parseWord | ||
spaces | ||
eof | ||
return (args, cxt') | ||
|
||
parseWord = do | ||
spaces | ||
many1 alphaNum | ||
|
||
parseContext = try $ do | ||
cxts <- parseParen parseContexts | ||
spaces | ||
_ <- string "=>" | ||
return cxts | ||
|
||
parseParen p = do | ||
spaces | ||
_ <- try ( char '(' ) | ||
r <- p | ||
spaces | ||
_ <- try ( char ')' ) | ||
return r | ||
|
||
parseContexts = | ||
sepBy1 (many1 parseWord) (spaces >> char ',' >> return ()) | ||
|
||
toClauses :: String -> String -> (Lang, [Def]) -> Q [Clause] | ||
toClauses prefix dt (lang, defs) = | ||
mapM go defs | ||
where | ||
|
@@ -261,7 +318,7 @@ toCon dt (SDef c vs _) = | |
where | ||
go (n, t) = (varName dt n, notStrict, ConT $ mkName t) | ||
|
||
varName :: String -> String -> Name | ||
varName :: String -> String -> Name | ||
varName a y = | ||
mkName $ concat [lower a, "Message", upper y] | ||
where | ||
|
@@ -358,8 +415,7 @@ loadLangFile :: FilePath -> IO [Def] | |
loadLangFile file = do | ||
bs <- S.readFile file | ||
let s = unpack $ decodeUtf8 bs | ||
defs <- fmap catMaybes $ mapM (parseDef . T.unpack . T.strip . T.pack) $ lines s | ||
return defs | ||
fmap catMaybes $ mapM (parseDef . T.unpack . T.strip . T.pack) $ lines s | ||
|
||
parseDef :: String -> IO (Maybe Def) | ||
parseDef "" = return Nothing | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,31 +33,6 @@ spec = do | |
(DerefBranch (DerefIdent (Ident "+")) (DerefIdent (Ident "a"))) | ||
(DerefIdent (Ident "b")))) | ||
|
||
it "parseDeref parse single type applications" $ do | ||
runParser parseDeref () "" "x @y" `shouldBe` | ||
Right | ||
(DerefBranch | ||
(DerefIdent (Ident "x")) | ||
(DerefType "y")) | ||
it "parseDeref parse unit type applications" $ do | ||
runParser parseDeref () "" "x @()" `shouldBe` | ||
Right | ||
(DerefBranch | ||
(DerefIdent (Ident "x")) | ||
(DerefType "()")) | ||
it "parseDeref parse compound type applications" $ do | ||
runParser parseDeref () "" "x @(Maybe String)" `shouldBe` | ||
Right | ||
(DerefBranch | ||
(DerefIdent (Ident "x")) | ||
(DerefType "Maybe String")) | ||
it "parseDeref parse single @ as operator" $ do | ||
runParser parseDeref () "" "x @ y" `shouldBe` | ||
Right | ||
(DerefBranch | ||
(DerefBranch (DerefIdent (Ident "@")) (DerefIdent (Ident "x"))) | ||
(DerefIdent (Ident "y"))) | ||
Comment on lines
-36
to
-59
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why were these tests removed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is strange. I have not edited the file. Should I add these lines into the BaseSpec.hs? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like a minor git accident then 🙂 You can just revert this change. |
||
|
||
it "parseDeref parse expressions with record dot" $ do | ||
runParser parseDeref () "" "x.y" `shouldBe` | ||
Right (DerefGetField (DerefIdent (Ident "x")) "y") | ||
|
@@ -131,3 +106,4 @@ spec = do | |
|
||
eShowErrors :: Either ParseError c -> c | ||
eShowErrors = either (error . show) id | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a good reason why this changelog entry was removed? This looks like a mistake.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On Hackage the version 2.1.1 is the last one and is already deprecated.
https://hackage.haskell.org/package/shakespeare-2.1.1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, but it shouldn't be removed even if it's deprecated. The deprecated version should continue to exist in the version history.