packages feed

Earley-0.13.0.1: tests/Issue14.hs

module Issue14 where
import Control.Applicative
import Test.Tasty
import Test.Tasty.QuickCheck as QC

import Text.Earley

tests :: TestTree
tests = testGroup "Issue 14"
  [ QC.testProperty "The same rule in alternatives gives many results" $
    \x -> fullParses (parser (issue14 x)) ""
    == (,) (replicate (issue14Length x) ())
           Report { position = 0, expected = [], unconsumed = [] }
  , QC.testProperty "The same rule in alternatives generates many results" $
    \x -> language (generator (issue14 x) "")
    == replicate (issue14Length x) ((), "")
  ]

data Issue14 a
  = Pure a
  | Alt (Issue14 a) (Issue14 a)
  | Ap (Issue14 a) (Issue14 a)
  deriving (Eq, Ord, Show)

instance Arbitrary a => Arbitrary (Issue14 a) where
  arbitrary = sized arbTree
    where arbTree n | n > 0  = oneof [ Pure <$> arbitrary
                                     , Alt <$> arbTree1 <*> arbTree1
                                     , Ap <$> arbTree1 <*> arbTree1
                                     ]
                                     where arbTree1 = arbTree (n `div` 2)
          arbTree _          = Pure <$> arbitrary

  shrink (Pure a)  = Pure <$> shrink a
  shrink (Alt a b) = a : b : [Alt a' b | a' <- shrink a] ++ [Alt a b' | b' <- shrink b]
  shrink (Ap a b)  = a : b : [Ap a' b | a' <- shrink a] ++ [Ap a b' | b' <- shrink b]

issue14Length :: Issue14 () -> Int
issue14Length (Pure ()) = 1
issue14Length (Alt a b) = issue14Length a + issue14Length b
issue14Length (Ap a b)  = issue14Length a * issue14Length b

issue14 :: Issue14 () -> Grammar r (Prod r () Char ())
issue14 tree = do
  emptyRule <- rule $ pure ()
  let x = go emptyRule tree
  return x
  where
    go x (Pure ())   = x
    go x (Alt b1 b2) = go x b1 <|> go x b2
    go x (Ap b1 b2)  = go x b1 <* go x b2