22
33module Expr where
44
5- import Data.Scientific (Scientific )
6- import Data.String (IsString (.. ))
7- import Data.Text (Text )
8- import qualified Data.Text as T
9- import Text.Parsec (many , many1 , optionMaybe , parse , sepBy ,
10- (<|>) , between )
11- import Text.Parsec.Char (char , digit , letter , noneOf , spaces )
12- import Text.Parsec.Error (ParseError )
13- import Text.Parsec.Text (Parser )
5+ import Data.Aeson (Value (.. ), decode' , encode )
6+ import Data.Scientific (Scientific )
7+ import Data.String (IsString (.. ))
8+ import Data.Text (Text )
9+ import qualified Data.Text as T
10+ import qualified Data.Text.Lazy as TL
11+ import qualified Data.Text.Lazy.Encoding as TL
12+ import Text.Parsec (between , many , many1 , optionMaybe ,
13+ parse , sepBy , (<|>) )
14+ import Text.Parsec.Char (char , digit , letter , noneOf , spaces )
15+ import Text.Parsec.Error (ParseError )
16+ import Text.Parsec.Text (Parser )
1417
1518-- $setup
1619-- >>> :set -XOverloadedStrings
1720
1821data Expr = IntLiteral ! Integer
1922 | DoubleLiteral ! Scientific
2023 | StringLiteral ! Text
24+ | JsonLiteral ! Value
2125 | FunctionCall ! Function
2226 deriving (Show , Eq )
2327
@@ -40,7 +44,33 @@ expr = literal <|> functionCall
4044
4145
4246literal :: Parser Expr
43- literal = number <|> stringLiteral
47+ literal = number <|> stringLiteral <|> jsonLiteral
48+
49+
50+ showExpr :: Expr -> Text
51+ showExpr (StringLiteral s) = " \" " <> s <> " \" "
52+ showExpr (IntLiteral n) = T. pack . show $ n
53+ showExpr (DoubleLiteral n) = T. pack . show $ n
54+ showExpr (JsonLiteral s) = TL. toStrict . TL. decodeUtf8 $ encode s
55+ showExpr (FunctionCall _) = error " Can only convert literals to text representation"
56+
57+
58+ jsonLiteral :: Parser Expr
59+ jsonLiteral = do
60+ assignments <- between (char ' {' ) (char ' }' ) (assignment `sepBy` comma)
61+ let
62+ objStr = " {" <> T. intercalate " , " assignments <> " }"
63+ case decode' (TL. encodeUtf8 . TL. fromStrict $ objStr) of
64+ Nothing -> error $ " Invalid JSON string: " <> T. unpack objStr
65+ Just v -> pure $ JsonLiteral v
66+ where
67+ assignment = do
68+ key <- stringLiteral
69+ _ <- colon
70+ value <- literal
71+ pure $ showExpr key <> " : " <> showExpr value
72+ colon = char ' :' >> spaces
73+ comma = char ' ,' >> spaces
4474
4575
4676number :: Parser Expr
@@ -59,8 +89,8 @@ number = do
5989stringLiteral :: Parser Expr
6090stringLiteral = StringLiteral . T. pack <$> string
6191 where
62- singleQuote = char ' \' '
63- string = between singleQuote singleQuote (many (noneOf " \' " ))
92+ quote = char ' \' ' <|> char ' " '
93+ string = between quote quote (many (noneOf " \'\" " ))
6494
6595
6696functionCall :: Parser Expr
@@ -106,5 +136,11 @@ ident = do
106136--
107137-- >>> parseExpr "''"
108138-- Right (StringLiteral "")
139+ --
140+ -- >>> parseExpr "{}"
141+ -- Right (JsonLiteral (Object (fromList [])))
142+ --
143+ -- >>> parseExpr "{\"x\": 10, \"y\": {}}"
144+ -- Right (JsonLiteral (Object (fromList [("x",Number 10.0),("y",Object (fromList []))])))
109145parseExpr :: Text -> Either ParseError Expr
110146parseExpr = parse expr " (unknown)"
0 commit comments