vulkan-utils-0.5.0: src/Vulkan/Utils/ShaderQQ/Backend/Shaderc.hs
module Vulkan.Utils.ShaderQQ.Backend.Shaderc
( ShadercError
, ShadercWarning
, processShadercMessages
) where
import Control.Monad ( void )
import qualified Data.ByteString.Lazy.Char8 as BSL
import Data.Foldable ( asum )
import Text.ParserCombinators.ReadP
type ShadercError = String
type ShadercWarning = String
processShadercMessages :: BSL.ByteString -> ([ShadercWarning], [ShadercError])
processShadercMessages = foldMap parseMsg . lines . BSL.unpack
-- >>> parseMsg "blah"
-- ([],[])
--
-- >>> parseMsg "blah"
-- ([],["blah"])
--
-- >>> parseMsg "foo:2: error: unknown var"
-- ([],["foo:2: unknown var"])
--
-- >>> parseMsg "foo:2: warning: unknown var"
-- (["foo:2: unknown var"],[])
--
-- >>> parseMsg "bar:2: error: 'a' : unknown variable"
-- ([],["bar:2: 'a' : unknown variable"])
--
-- >>> parseMsg "f:o: error: f:o:2: 'a' : unknown variable"
-- ([],["f:o:2: 'a' : unknown variable"])
--
-- >>> parseMsg "f:o: error: f:o:2: 'return' : type does not match, or is not convertible to, the function's return type"
-- ([],["f:o:2: 'return' : type does not match, or is not convertible to, the function's return type"])
--
-- >>> parseMsg "foo: foo(1): error at column 3, HLSL parsing failed."
-- ([],["foo:1: error at column 3, HLSL parsing failed."])
parseMsg :: String -> ([ShadercWarning], [ShadercError])
parseMsg = runParser $ foldl1
(<++)
[ do
f <- filename
line <- between colon colon number
skipSpaces
t <- msgType
msg <- manyTill get eof
pure $ formatMsg t f line msg
, do
f <- filename
colon *> skipSpaces
t <- msgType
_ <- string f
line <- between (char ':') (char ':') number
skipSpaces
msg <- manyTill get eof
pure $ formatMsg t f line msg
, do
f <- filename
colon *> skipSpaces
_ <- string f
line <- between (char '(') (char ')') number
colon *> skipSpaces
let t x = ([], [x])
msg <- manyTill get eof
pure $ formatMsg t f line msg
, do
_ <- number
skipSpaces
_ <- string "errors generated"
eof
pure ([], [])
, do
-- Unknown format
msg <- manyTill get eof
eof
pure ([], [msg])
]
where
formatMsg t f line msg = t (f <> ":" <> show line <> ": " <> msg)
filename = many1 get
number = readS_to_P (reads @Integer)
colon = void $ char ':'
msgType =
asum
[ (\x -> ([], [x])) <$ string "error"
, (\x -> ([x], [])) <$ string "warning"
]
<* colon
<* skipSpaces
runParser :: Monoid p => ReadP p -> String -> p
runParser p s = case readP_to_S p s of
[(r, "")] -> r
_ -> mempty