flatparse-0.5.3.1: bench/Attoparsec.hs
module Attoparsec (runSexp, runLongws, runNumcsv, runTm) where
import Control.Applicative
import Data.Attoparsec.ByteString.Char8
import Common
import qualified Data.ByteString as B
isLatinLetter :: Char -> Bool
isLatinLetter c = ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')
skipWhile1 :: (Char -> Bool) -> Parser ()
skipWhile1 pred = satisfy pred *> skipWhile pred
ws, open, close, ident, sexp :: Parser ()
ws = skipWhile (\c -> c == ' ' || c == '\n')
open = char '(' >> ws
close = char ')' >> ws
ident = skipWhile1 isLatinLetter <* ws
sexp = (open *> skipMany1 sexp <* close) <|> ident
runSexp = parseOnly sexp
longw, longws :: Parser ()
longw = () <$ string "thisisalongkeyword"
longws = skipMany1 (longw *> ws) <* endOfInput
runLongws = parseOnly longws
numeral, comma, numcsv :: Parser ()
numeral = skipWhile1 (\c -> '0' <= c && c <= '9') >> ws
comma = char ',' >> ws
numcsv = numeral >> skipMany1 (comma >> numeral) >> endOfInput
runNumcsv = parseOnly numcsv
--------------------------------------------------------------------------------
ident' :: Parser B.ByteString
ident' = takeWhile1 (\c -> isLatinLetter c || isDigit c) <* ws
equal = char '=' >> ws
semi = char ';' >> ws
dot = char '.' >> ws
addOp = char '+' >> ws
mulOp = char '*' >> ws
parl = char '(' >> ws
parr = char ')' >> ws
chainl :: (b -> a -> b) -> Parser b -> Parser a -> Parser b
chainl f start elem = start >>= go where
go b = do {!a <- elem; go $! f b a} <|> pure b
{-# inline chainl #-}
add :: Parser Tm
add = chainl Add mul (addOp *> mul)
mul :: Parser Tm
mul = chainl Mul spine (mulOp *> spine)
spine :: Parser Tm
spine = chainl App atom atom
atom :: Parser Tm
atom =
(Int <$> (decimal <* ws))
<|> (Var <$> ident')
<|> (parl *> tm <* parr)
tm :: Parser Tm
tm = (do {_ <- string "fun"; ws; x <- ident'; dot; t <- tm; pure (Lam x t)})
<|> (do {_ <- string "let"; ws; x <- ident'; equal; t <- tm; semi; u <- tm; pure (Let x t u)})
<|> add
runTm = parseOnly (ws *> tm <* endOfInput)