module CLaSH.Netlist.BlackBox.Parser
(runParse)
where
import Data.Text.Lazy (Text, pack)
import Text.ParserCombinators.UU
import Text.ParserCombinators.UU.BasicInstances hiding (Parser)
import qualified Text.ParserCombinators.UU.Core as PCC (parse)
import Text.ParserCombinators.UU.Utils hiding (pBrackets)
import CLaSH.Netlist.BlackBox.Types
type Parser a = P (Str Char Text LineColPos) a
runParse :: Text -> (BlackBoxTemplate, [Error LineColPos])
runParse = PCC.parse ((,) <$> pBlackBoxD <*> pEnd)
. createStr (LineColPos 0 0 0)
pBlackBoxD :: Parser BlackBoxTemplate
pBlackBoxD = pSome pElement
pElement :: Parser Element
pElement = pTagD
<|> C <$> pText
<|> C <$> (pack <$> pToken "~ ")
pText :: Parser Text
pText = pack <$> pList1 (pRange ('\000','\125'))
pTagD :: Parser Element
pTagD = IF <$> (pTokenWS "~IF" *> pTagE)
<*> (pSpaces *> (pToken "~THEN" *> pBlackBoxD))
<*> (pToken "~ELSE" *> pBlackBoxD <* pToken "~FI")
<|> D <$> pDecl
<|> pTagE
pDecl :: Parser Decl
pDecl = Decl <$> (pTokenWS "~INST" *> pNatural) <*>
((:) <$> pOutput <*> pList pInput) <* pToken "~INST"
pOutput :: Parser (BlackBoxTemplate,BlackBoxTemplate)
pOutput = pTokenWS "~OUTPUT" *> pTokenWS "<=" *> ((,) <$> (pBlackBoxE <* pTokenWS "~") <*> pBlackBoxE) <* pTokenWS "~"
pInput :: Parser (BlackBoxTemplate,BlackBoxTemplate)
pInput = pTokenWS "~INPUT" *> pTokenWS "<=" *> ((,) <$> (pBlackBoxE <* pTokenWS "~") <*> pBlackBoxE) <* pTokenWS "~"
pTagE :: Parser Element
pTagE = O <$ pToken "~RESULT"
<|> I <$> (pToken "~ARG" *> pBrackets pNatural)
<|> L <$> (pToken "~LIT" *> pBrackets pNatural)
<|> (Clk . Just) <$> (pToken "~CLK" *> pBrackets pNatural)
<|> Clk Nothing <$ pToken "~CLKO"
<|> (Rst . Just) <$> (pToken "~RST" *> pBrackets pNatural)
<|> Rst Nothing <$ pToken "~RSTO"
<|> Sym <$> (pToken "~SYM" *> pBrackets pNatural)
<|> Typ Nothing <$ pToken "~TYPO"
<|> (Typ . Just) <$> (pToken "~TYP" *> pBrackets pNatural)
<|> TypM Nothing <$ pToken "~TYPMO"
<|> (TypM . Just) <$> (pToken "~TYPM" *> pBrackets pNatural)
<|> Err Nothing <$ pToken "~ERRORO"
<|> (Err . Just) <$> (pToken "~ERROR" *> pBrackets pNatural)
<|> TypElem <$> (pToken "~TYPEL" *> pBrackets pTagE)
<|> IndexType <$> (pToken "~INDEXTYPE" *> pBrackets pTagE)
<|> CompName <$ pToken "~COMPNAME"
<|> Size <$> (pToken "~SIZE" *> pBrackets pTagE)
<|> Length <$> (pToken "~LENGTH" *> pBrackets pTagE)
<|> FilePath <$> (pToken "~FILE" *> pBrackets pTagE)
<|> Gen <$> (True <$ pToken "~GENERATE")
<|> Gen <$> (False <$ pToken "~ENDGENERATE")
<|> SigD <$> (pToken "~SIGD" *> pBrackets pSigD) <*> (Just <$> (pBrackets pNatural))
<|> (`SigD` Nothing) <$> (pToken "~SIGDO" *> pBrackets pSigD)
pBrackets :: Parser a -> Parser a
pBrackets p = pSym '[' *> p <* pSym ']'
pTokenWS :: String -> Parser String
pTokenWS keyw = pToken keyw <* pSpaces
pBlackBoxE :: Parser BlackBoxTemplate
pBlackBoxE = pSome pElemE
pElemE :: Parser Element
pElemE = pTagE
<|> C <$> pText
pSigD :: Parser [Element]
pSigD = pSome (pTagE <|> pLimitedText)
pLimitedText :: Parser Element
pLimitedText = C <$> (pack <$> pList1 (pSatisfy (`notElem` "[]~") (Insertion (show "notElem \"[]~\"") '_' 5)))