module Types (module Text.Parsec.Applicative, module Types) where
import Test.QuickCheck
import Text.Parsec.Applicative
import Text.Parsec.Applicative.Internal
instance HasSourcePos () where
sourcePos = const noPos
type Tokens = [(Sigma, Extra)]
data Sigma = A | B | C deriving (Eq, Ord, Enum, Bounded, Show)
instance Arbitrary Sigma where
arbitrary = arbitraryBoundedEnum
data Extra = E | F | G deriving (Eq, Ord, Enum, Bounded, Show)
instance Monoid Extra where
mempty = E
mappend E x = x
mappend x E = x
mappend F F = G
mappend F G = E
mappend G F = E
mappend G G = F
instance HasSourcePos Extra where
sourcePos = const $ SourcePos Nothing (-1) (-1)
instance Arbitrary Extra where
arbitrary = arbitraryBoundedEnum
type P = Parser String Sigma Extra Extra
newtype RecP = RecP { getP :: P }
instance Arbitrary P where
arbitrary = arbitraryParser False
instance Arbitrary RecP where
arbitrary = RecP <$> arbitraryParser True
arbitraryParser :: Bool -> Gen P
arbitraryParser rec = sized $ arb rec
arb :: Bool -> Int -> Gen P
arb _ 0 = oneof
[ (PEnd *>) . PConst <$> arbitrary
, PConst <$> arbitrary
, PApp (pure snd) . PToken <$> arbitrary
, return $ PFail $ Just "arbitrary"
]
arb rec n = oneof
[ bin PSkip
-- TODO generate real functions
, PApp <$> ((*> pure id) <$> arb') <*> arb'
, PTry <$> arb'
, PApp (pure mconcat) . PRepeat <$> arb' `suchThat` (not . acceptEmpty . Ex)
, bin PChoice
-- TODO generate recursive parsers
, PLabel "label" <$> arb'
]
where
arb' = arb rec $ n `div` 2
bin op = op <$> arb' <*> arb'