{-# LANGUAGE OverloadedStrings #-}
module Hasmin.Parser.Utils
( ident
, skipComments
, lexeme
, functionParser
, digits
, comma
, colon
, slash
, opt
, nmchar
, hexadecimal
, word8
, parserFromPairs
, atMost
) where
import Control.Applicative (liftA2, (<|>), many)
import Control.Monad (void, mzero)
import Data.Attoparsec.Text (char,
option, Parser, satisfy, skipSpace, string)
import Data.Text (Text)
import Data.Maybe (fromMaybe)
import qualified Data.Text as T
import Data.Word (Word8)
import qualified Data.Attoparsec.Text as A
import qualified Data.Char as C
import qualified Data.Map.Strict as Map
import Hasmin.Parser.Primitives
skipComments :: Parser ()
skipComments = void $ many (skipSpace *> comment) <* skipSpace
comment :: Parser Text
comment = mappend <$> string "/*" <*> (string "*/" <|> untilAsterisk)
where untilAsterisk = mappend <$> A.takeWhile (/= '*') <*> checkAsterisk
checkAsterisk = mappend <$> string "*" <*> (string "/" <|> untilAsterisk)
comma :: Parser Char
comma = lexeme $ char ','
colon :: Parser Char
colon = lexeme $ char ':'
slash :: Parser Char
slash = lexeme $ char '/'
lexeme :: Parser a -> Parser a
lexeme p = skipComments *> p <* skipComments
opt :: Monoid m => Parser m -> Parser m
opt = option mempty
functionParser :: Parser a -> Parser a
functionParser p = lexeme p <* char ')'
hexadecimal :: Parser Char
hexadecimal = satisfy C.isHexDigit
word8 :: Parser Word8
word8 = read <$> digits
parserFromPairs :: [(Text, Parser a)] -> Parser a
parserFromPairs ls = do
i <- ident
let t = T.toLower i
fromMaybe mzero (Map.lookup t m)
where m = Map.fromList ls
atMost :: Int -> Parser a -> Parser [a]
atMost 0 _ = pure []
atMost n p = A.option [] $ liftA2 (:) p (atMost (n-1) p)