{-# LANGUAGE DataKinds #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE TupleSections #-} module Language.JsonGrammar.Parser (parseValue) where import Language.JsonGrammar.Grammar import Language.JsonGrammar.Util import Control.Applicative ((<$>)) import Control.Monad ((>=>), unless) import Data.Aeson (Object, Array, withObject, (.:), withArray) import Data.Aeson.Types (Parser, typeMismatch) import Data.Monoid ((<>)) import qualified Data.Vector as V -- | Convert a 'Grammar' to a JSON 'Parser'. parseValue :: Grammar 'Val t1 t2 -> t1 -> Parser t2 parseValue = \case Id -> return g1 :. g2 -> parseValue g2 >=> parseValue g1 Empty -> \_ -> fail "empty grammar" g1 :<> g2 -> parseValue g1 <> parseValue g2 Pure f _ -> f Many g -> manyM (parseValue g) Literal val -> \(val' :- t) -> if val == val' then return t else typeMismatch "literal" val' Label _ g -> parseValue g Object g -> \(val :- x) -> withObject "object" (\obj -> parseProperties obj g x) val Array g -> \(val :- x) -> do (arr', y) <- withArray "array" (\arr -> parseElements g (arr, x)) val unless (V.null arr') $ typeMismatch "end of array" (V.head arr') return y Coerce _ g -> parseValue g parseProperties :: Object -> Grammar 'Obj t1 t2 -> t1 -> Parser t2 parseProperties obj = \case Id -> return g1 :. g2 -> parseProperties obj g2 >=> parseProperties obj g1 Empty -> \_ -> fail "empty grammar" g1 :<> g2 -> parseProperties obj g1 <> parseProperties obj g2 Pure f _ -> f Many g -> manyM (parseProperties obj g) Property n g -> \x -> do val <- obj .: n parseValue g (val :- x) parseElements :: Grammar 'Arr t1 t2 -> (Array, t1) -> Parser (Array, t2) parseElements = \case Id -> return g1 :. g2 -> parseElements g2 >=> parseElements g1 Empty -> \_ -> fail "empty grammar" g1 :<> g2 -> parseElements g1 <> parseElements g2 Pure f _ -> \(arr, x) -> (arr, ) <$> f x Many g -> manyM (parseElements g) Element g -> \(arr, x) -> if V.null arr then fail "expected at least one more array element" else do y <- parseValue g (V.last arr :- x) return (V.init arr, y)