Skip to content

Commit 74df48f

Browse files
committed
feat: add basic parser primitives
1 parent 26b498b commit 74df48f

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

src/Primitives.hs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
{-# LANGUAGE OverloadedStrings #-}
2+
3+
module Primitives () where
4+
5+
import Control.Applicative
6+
import Data.Char (isDigit)
7+
import qualified Data.Map as M
8+
import qualified Data.Text as T
9+
import Parser
10+
import Text.Read (readMaybe)
11+
12+
data JsonVal
13+
= -- Maybe indicates the fractional part of the number. This will obviously be `Nothing` if it's
14+
-- just a plain integer.
15+
JsonNumber Integer (Maybe Integer)
16+
| JsonBool Bool
17+
| JsonNull
18+
| JsonString T.Text
19+
| JsonArray [JsonVal]
20+
| JsonObj (M.Map T.Text JsonVal)
21+
deriving (Eq, Show)
22+
23+
jsonVal :: Parser JsonVal
24+
jsonVal = jsonNumber <|> jsonNull <|> jsonBool
25+
26+
satisfy :: (Char -> Bool) -> Parser T.Text
27+
satisfy predicate = Parser $ \s ->
28+
let (t, rest) = span predicate $ T.unpack s
29+
in -- If we don't manage to extract any valid tokens, then the received text will be null
30+
-- If so, we'll fail the parsing
31+
case t of
32+
[] -> Nothing
33+
_ -> Just (T.pack t, T.pack rest)
34+
35+
-- TODO: Implement parsing of floating point numbers
36+
jsonNumber :: Parser JsonVal
37+
jsonNumber = f <$> (satisfy isDigit)
38+
where
39+
f s = JsonNumber (read $ T.unpack s) Nothing
40+
41+
charP :: Char -> Parser Char
42+
charP ch = Parser fn
43+
where
44+
fn s =
45+
case T.uncons s of
46+
Just (c, cs) | c == ch -> Just (c, cs)
47+
_ -> Nothing
48+
49+
stringP :: T.Text -> Parser [Char]
50+
stringP s = (sequenceA . map charP) $ T.unpack s
51+
52+
jsonNull :: Parser JsonVal
53+
jsonNull = (\_ -> JsonNull) <$> stringP "null"
54+
55+
jsonBool :: Parser JsonVal
56+
jsonBool = f <$> (stringP "true" <|> stringP "false")
57+
where
58+
f a = case a of
59+
"true" -> JsonBool True
60+
"false" -> JsonBool False
61+
62+
-- A test parser
63+
digit :: Parser Int
64+
digit = Parser $ \s ->
65+
case T.uncons s of
66+
Nothing -> Nothing
67+
Just (c, cs) -> case readMaybe [c] of
68+
Just x -> Just (x, cs)
69+
Nothing -> Nothing

0 commit comments

Comments
 (0)