Skip to content

Instantly share code, notes, and snippets.

@TerrorJack
Last active August 29, 2015 14:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TerrorJack/95a964c649c325c8bf87 to your computer and use it in GitHub Desktop.
Save TerrorJack/95a964c649c325c8bf87 to your computer and use it in GitHub Desktop.
A minimal PEG parsing library.
import Control.Applicative
import Control.Monad.State
import Data.Char
import Data.Function
type Parser = StateT String Maybe
parse :: Parser a -> String -> Maybe (a,String)
parse = runStateT
anyChar :: Parser Char
anyChar = get >>= \s -> case s of { c:cs -> put cs *> return c; [] -> lift Nothing }
filterChar :: (Char -> Bool) -> Parser Char
filterChar f = mfilter f anyChar
char :: Char -> Parser Char
char c = filterChar (==c)
natural :: Parser Integer
natural = read <$> some (filterChar isDigit)
chainl :: Parser b -> Parser (b -> a -> b) -> Parser a -> Parser b
chainl l f r = foldl (&) <$> l <*> many (flip <$> f <*> r)
addspace :: Parser a -> Parser a
addspace p = spaces *> p <* spaces where spaces = many $ filterChar isSpace
minus :: Parser (Integer -> Integer -> Integer)
minus = addspace $ (-) <$ char '-'
minusexp :: Parser Integer
minusexp = chainl natural minus natural
main :: IO ()
main = print $ parse minusexp "16 - 5 - 2"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment