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)
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)
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)