Skip to content

Instantly share code, notes, and snippets.

@scott-fleischman
Created August 26, 2014 07:22
Show Gist options
  • Save scott-fleischman/28f7bc1ac51d47130ed5 to your computer and use it in GitHub Desktop.
Save scott-fleischman/28f7bc1ac51d47130ed5 to your computer and use it in GitHub Desktop.
module AParser (Parser, runParser, satisfy, char, posInt) where
import Control.Applicative
import Data.Char
newtype Parser a = Parser { runParser :: String -> Maybe (a, String) }
satisfy :: (Char -> Bool) -> Parser Char
satisfy p = Parser f
where
f [] = Nothing
f (x:xs)
| p x = Just (x, xs)
| otherwise = Nothing
char :: Char -> Parser Char
char c = satisfy (== c)
posInt :: Parser Integer
posInt = Parser f
where
f xs
| null ns = Nothing
| otherwise = Just (read ns, rest)
where (ns, rest) = span isDigit xs
inParser f = Parser . f . runParser
first :: (a -> b) -> (a,c) -> (b,c)
first f (x,y) = (f x, y)
instance Functor Parser where
fmap = inParser . fmap . fmap . first
instance Applicative Parser where
pure a = Parser (\s -> Just (a, s))
(Parser fp) <*> xp = Parser $ \s ->
case fp s of
Nothing -> Nothing
Just (f,s') -> runParser (f <$> xp) s'
instance Alternative Parser where
empty = Parser (const Nothing)
Parser p1 <|> Parser p2 = Parser $ liftA2 (<|>) p1 p2
-- http://www.seas.upenn.edu/~cis194/hw/11-applicative2.pdf
{- CIS 194 HW 11
due Monday, 8 April
-}
module SExpr where
import AParser
import Control.Applicative
import Data.Char
------------------------------------------------------------
-- 1. Parsing repetitions
------------------------------------------------------------
zeroOrMore :: Parser a -> Parser [a]
zeroOrMore p = oneOrMore p <|> pure []
oneOrMore :: Parser a -> Parser [a]
oneOrMore p = (:) <$> p <*> zeroOrMore p <|> empty
------------------------------------------------------------
-- 2. Utilities
------------------------------------------------------------
spaces :: Parser String
spaces = zeroOrMore (satisfy isSpace)
ident :: Parser String
ident = (:) <$> (satisfy isAlpha) <*> zeroOrMore (satisfy isAlphaNum)
------------------------------------------------------------
-- 3. Parsing S-expressions
------------------------------------------------------------
-- An "identifier" is represented as just a String; however, only
-- those Strings consisting of a letter followed by any number of
-- letters and digits are valid identifiers.
type Ident = String
-- An "atom" is either an integer value or an identifier.
data Atom = N Integer | I Ident
deriving Show
-- An S-expression is either an atom, or a list of S-expressions.
data SExpr = A Atom
| Comb [SExpr]
deriving Show
parseAtom :: Parser Atom
parseAtom = N <$> posInt <|>
I <$> ident
trim :: Parser a -> Parser a
trim p = spaces *> p <* spaces
parseSExpr :: Parser SExpr
parseSExpr = trim $
A <$> parseAtom <|>
char '(' *> (Comb <$> (oneOrMore parseSExpr)) <* char ')'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment