packages feed

flatparse-0.1.1.1: bench/Bytesmith.hs

{-# language RankNTypes #-}

module Bytesmith (runSexp, runLongws, runNumcsv, strToByteArray) where

import Control.Applicative

import GHC.Exts

import qualified Data.Bytes.Parser       as P
import qualified Data.Bytes.Parser.Ascii as A

import Data.Primitive.ByteArray
import Data.Char

strToByteArray :: String -> ByteArray
strToByteArray = fromList . map (fromIntegral . ord)

byteArrayToStr :: ByteArray -> String
byteArrayToStr = map (chr . fromIntegral) . toList

parseByteArray :: (forall s. Parser s) -> ByteArray -> Bool
parseByteArray p b = case P.parseByteArray p b of
  P.Failure{} -> False
  _           -> True
{-# inline parseByteArray #-}

data U = U
instance Semigroup U where (<>) _ _ = U
instance Monoid U    where mempty   = U

type Parser s = P.Parser U s ()

many_ :: Parser s -> Parser s
many_ p = go where
  go = (p >> go) <|> pure ()
{-# inline many_ #-}

some_ :: Parser s -> Parser s
some_ p = p >> many_ p
{-# inline some_ #-}

ws :: Parser s
ws = many_ do
  P.any U >>= \case
    32 -> pure ()      -- ' '
    10 -> pure ()      -- '\n'
    _  -> P.fail U

open    = A.char U '(' >> ws
close   = A.char U ')' >> ws
ident   = A.skipAlpha1 U >> ws
sexp    = (open >> some_ sexp >> close) <|> ident
src     = sexp >> P.endOfInput U
runSexp = parseByteArray src

longw     = P.cstring U (Ptr "thisisalongkeyword"#)
longws    = some_ (longw >> ws) >> P.endOfInput U
runLongws = parseByteArray longws

numeral   = A.skipDigits1 U >> ws
comma     = A.char U ',' >> ws
numcsv    = numeral >> many_ (comma >> numeral) >> P.endOfInput U
runNumcsv = parseByteArray numcsv