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