Skip to content

Commit

Permalink
pull Parser module out
Browse files Browse the repository at this point in the history
  • Loading branch information
kpse committed Oct 17, 2020
1 parent 41f0122 commit cc27d58
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 42 deletions.
49 changes: 7 additions & 42 deletions Main.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
module Main where

import Control.Applicative ( Alternative((<|>), empty, many) )
import Control.Applicative ( (<|>), many)
import Data.Char (isSpace, isDigit)
import Parser ( Parser(..), notEmpty, spanP, charP )
-- import ParserE ( Parser(..), notEmpty, spanP, charP )

data JsonValue = JsonNull
| JsonBool Bool
Expand All @@ -11,10 +13,6 @@ data JsonValue = JsonNull
| JsonObject [(String, JsonValue)]
deriving (Show, Eq)

newtype Parser a = Parser {
runParser :: String -> Maybe (String, a)
}

jsonNull :: Parser JsonValue
jsonNull = const JsonNull <$> stringP "null"

Expand All @@ -34,12 +32,7 @@ jsonNumber = f <$> notEmpty (spanP included)
f = JsonNumber . read
included a = isDigit a || (== '.') a

notEmpty :: Parser String -> Parser String
notEmpty (Parser p) = Parser $ \i -> do
(i2, rest) <- p i
case rest of
[] -> Nothing
_ -> Just (i2, rest)



jsonArray :: Parser JsonValue
Expand Down Expand Up @@ -79,39 +72,11 @@ jsonObject :: Parser JsonValue
jsonObject = JsonObject <$> (startBrace *> pairBy <* endBrace)


spanP :: (Char -> Bool) -> Parser String
spanP f = Parser $ \input -> let (m, rest) = span f input in Just (rest, m)

charP :: Char -> Parser Char
charP x = Parser f
where
f (y:ys)
| y == x = Just (ys, x)
| otherwise = Nothing
f [] = Nothing

stringP :: String -> Parser String
stringP = traverse charP


instance Functor Parser where
fmap f (Parser p) = Parser g
where
g input = do
(input', x) <- p input
Just (input', f x)

instance Applicative Parser where
pure x = Parser $ \input -> Just (input, x)
(Parser p1) <*> (Parser p2) = Parser $ \input -> do
(i2, f) <- p1 input
(i3, a) <- p2 i2
Just (i3, f a)


instance Alternative Parser where
empty = Parser $ const Nothing
(Parser a1) <|> (Parser a2) = Parser $ \i -> a1 i <|> a2 i

jsonValue :: Parser JsonValue
jsonValue = jsonNull <|> jsonBool <|> jsonNumber <|> jsonString <|> jsonArray <|> jsonObject
Expand All @@ -132,8 +97,8 @@ main = do
print $ runParser jsonArray "[]"
print $ runParser jsonValue "[2, true, false, [], \"123\"]"
print $ runParser jsonValue "[{\"key\": 42}, true, false, [], \"123\"]"
print $ runParser jsonObject "{\"key\":\"a\",\"k\":42}"
print $ runParser pairKey "\"key\""
print $ runParser jsonValue "{\"key\":\"a\",\"k\":42}"
print $ runParser pairKey "\"key\":"
print $ runParser (charP '{' *> ws *> commaSep <* ws <* charP '}') "{,}"
print $ runParser (charP '{' *> ws *> pairKey <* ws <* charP '}') "{\"somekey\"}"
print $ runParser (charP '{' *> ws *> pairKey <* ws <* charP '}') "{\"somekey\":}"

46 changes: 46 additions & 0 deletions Parser.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
module Parser (Parser(..), notEmpty, spanP, charP) where

import Control.Applicative ( Alternative((<|>), empty) )

newtype Parser a = Parser {
runParser :: String -> Maybe (String, a)
}


instance Functor Parser where
fmap f (Parser p) = Parser g
where
g input = do
(input', x) <- p input
Just (input', f x)

instance Applicative Parser where
pure x = Parser $ \input -> Just (input, x)
(Parser p1) <*> (Parser p2) = Parser $ \input -> do
(i2, f) <- p1 input
(i3, a) <- p2 i2
Just (i3, f a)


instance Alternative Parser where
empty = Parser $ const Nothing
(Parser a1) <|> (Parser a2) = Parser $ \i -> a1 i <|> a2 i


notEmpty :: Parser String -> Parser String
notEmpty (Parser p) = Parser $ \i -> do
(i2, rest) <- p i
case rest of
[] -> Nothing
_ -> Just (i2, rest)

spanP :: (Char -> Bool) -> Parser String
spanP f = Parser $ \input -> let (m, rest) = span f input in Just (rest, m)

charP :: Char -> Parser Char
charP x = Parser f
where
f (y:ys)
| y == x = Just (ys, x)
| otherwise = Nothing
f [] = Nothing

0 comments on commit cc27d58

Please sign in to comment.