-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMain.hs
115 lines (99 loc) · 3.08 KB
/
Main.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
module Main where
import Control.Applicative
import Data.Char qualified as Char
import Parser
import System.Directory
main = do
allFiles <- getDirectoryContents "./jsons"
let files = drop 2 allFiles
texts <- mapM (readFile . ("./jsons/" ++)) files
let res = zip files (map valid texts)
ff <- readFile "test.json"
mapM_ print ff
print (runParser parseVal ff)
-- mapM_ print res
data Pair = Pair Key Value
deriving (Show)
newtype Key = Key String
deriving (Show)
data Value
= S String
| N String
| L String
| A [Value]
| O [Pair]
deriving (Show)
valid :: String -> Bool
valid xs = case runParser parseVal xs of
Just (_, "") -> True
_ -> False
parseObj :: Parser [Pair]
parseObj =
( (\_ _ -> [])
<$> (spaces *> char '{' <* spaces)
<*> (spaces *> char '}' <* spaces)
)
<|> ( (\_ x y _ -> x ++ [y])
<$> (spaces *> char '{' <* spaces)
<*> atleast0 (const <$> parsePair <*> char ',' <* spaces)
<*> parsePair
<*> (spaces *> char '}' <* spaces)
)
parsePair :: Parser Pair
parsePair =
(\x _ y -> Pair x y)
<$> (parseKey <* spaces)
<*> char ':'
<*> (spaces *> parseVal)
parseKey :: Parser Key
parseKey = Key <$> parseString
parseVal :: Parser Value
parseVal =
O <$> parseObj
<|> A <$> parseArray
<|> N <$> parseNumber
<|> S <$> parseString
<|> L <$> parseLiteral
parseString :: Parser String
parseString =
(\_ y _ -> y)
<$> (spaces *> char '"')
<*> ( (atleast0 (satisfy isLegal))
>>= ( \x ->
if last x == '\\'
--then (\y -> x ++ "hello") <$> (char 'r' <|> char 't')
then error "x"
else pure x
)
)
<*> (char '"' <* spaces)
where
isLegal c = c == ' ' || not (c == '"' || c == '\\' || Char.isSpace c || Char.isControl c)
parseNumber :: Parser String
parseNumber = spaces *> p5 <* spaces
where
p1 = (\x y z -> x ++ y ++ z) <$> safeChar '-' <*> digits <*> safeChar '.'
p2 = p1 >>= (\x -> if last x == '.' then (x ++) <$> digits else pure x)
p3 = (++) <$> p2 <*> safeChar 'e'
p4 = p3 >>= (\x -> if last x == 'e' then (x ++) <$> safeChar '-' else pure x)
p5 = p4 >>= (\x -> if last x == 'e' || last x == '-' then (x ++) <$> digits else pure x)
parseLiteral :: Parser String
parseLiteral =
(join4 <$> (spaces *> char 't') <*> char 'r' <*> char 'u' <*> (char 'e' <* spaces))
<|> (join5 <$> (spaces *> char 'f') <*> char 'a' <*> char 'l' <*> char 's' <*> (char 'e' <* spaces))
<|> (join4 <$> (spaces *> char 'n') <*> char 'u' <*> char 'l' <*> (char 'l' <* spaces))
where
join4 a b c d = [a] ++ [b] ++ [c] ++ [d]
join5 a b c d e = [a] ++ [b] ++ [c] ++ [d] ++ [e]
parseArray :: Parser [Value]
parseArray =
( (\_ _ -> [])
<$> (spaces *> char '[' <* spaces)
<*> (spaces *> char ']' <* spaces)
)
<|> ( (\_ x y _ -> x ++ [y])
<$> (spaces *> char '[' <* spaces)
<*> atleast0 (const <$> parseVal <*> char ',' <* spaces)
<*> parseVal
<*> (spaces *> char ']' <* spaces)
)