module Language.Prolog.NanoProlog.Parser (
pFun
, pRule
, pTerm
, pCons
, pTerms
, startParse
) where
import Data.ListLike.Base (ListLike)
import Language.Prolog.NanoProlog.NanoProlog
import Text.ParserCombinators.UU
import Text.ParserCombinators.UU.BasicInstances
import Text.ParserCombinators.UU.Utils
startParse :: (ListLike s b, Show b) =>
P (Str b s LineColPos) a -> s -> (a, [Error LineColPos])
startParse p inp = parse ((,) <$> p <*> pEnd)
$ createStr (LineColPos 0 0 0) inp
pSepDot :: Parser String -> Parser [String]
pSepDot p = (:) <$> p <*> pList ((:) <$> pDot <*> p)
pTerm, pFactor, pCons, pVar, pFun :: Parser Term
pTerm = pChainr ((\ f a -> Fun "->" [f, a]) <$ pToken "->") pCons
pCons = pChainr ((\ h t -> Fun "cons" [h, t]) <$ pToken ":" ) pFactor
pFactor = pVar
<|> pFun
<|> pParens pTerm
pVar = Var <$> lexeme ((++) <$> pList1 pUpper <*> (concat <$> pSepDot (pList1 pDigit) `opt` []))
pFun = Fun <$> pLowerCase <*> (pParens pTerms `opt` [])
<|> Fun "[]" <$> pBrackets ((:[]) <$> pTerm)
where pLowerCase :: Parser String
pLowerCase = lexeme ((:) <$> pLower <*> pList (pLetter <|> pDigit))
pRule :: Parser Rule
pRule = (:<-:) <$> pFun <*> (pSymbol ":-" *> pTerms `opt` []) <* pDot
pTerms :: Parser [Term]
pTerms = pList1Sep pComma pTerm