module Alga.Language.SyntaxTree
( SyntaxTree
, Sel (..)
, Statement (..) )
where
import Alga.Language.Element (NRatio)
import Alga.Representation.Base
import Data.Char (isLetter, isAlphaNum)
import Data.List.NonEmpty (NonEmpty (..))
import Data.Ratio ((%))
import Test.QuickCheck
type SyntaxTree = [Sel]
data Sel
= Value NRatio
| Section [Sel]
| Multi [Sel]
| CMulti (NonEmpty ([Sel], [Sel]))
| Reference String
| Range NRatio NRatio
| Product Sel Sel
| Division Sel Sel
| Sum Sel Sel
| Diff Sel Sel
| Loop Sel Sel
| Rotation Sel Sel
| Reverse Sel
deriving (Eq, Show)
instance Arbitrary Sel where
arbitrary = sized arbitrarySel
arbitrarySel :: Int -> Gen Sel
arbitrarySel 0 =
oneof [ Value <$> nonNegative
, Reference <$> identifier
, Range <$> nonNegative <*> nonNegative ]
where nonNegative = (% 1) . getNonNegative <$> arbitrary
arbitrarySel n =
oneof [ Section <$> listSel
, Multi <$> listSel
, CMulti <$> listCnd
, Product <$> leafSel <*> leafSel
, Division <$> leafSel <*> leafSel
, Sum <$> leafSel <*> leafSel
, Diff <$> leafSel <*> leafSel
, Loop <$> leafSel <*> leafSel
, Rotation <$> leafSel <*> leafSel
, Reverse <$> leafSel ]
where cnSel d = arbitrarySel (n `div` d)
vcSel d = listOf (cnSel $ d * 20)
leafSel = cnSel 10
listSel = vcSel 20
listCnd =
let x = (,) <$> vcSel 25 <*> vcSel 25
in (:|) <$> x <*> listOf x
data Statement
= Definition String SyntaxTree
| Exposition SyntaxTree
deriving (Eq, Show)
instance Arbitrary Statement where
arbitrary = oneof
[ Definition <$> identifier <*> arbitrary
, Exposition <$> arbitrary ]
identifier :: Gen String
identifier = (:) <$> ch0 <*> chN
where ch0 = u isLetter
chN = listOf $ u (\x -> isAlphaNum x || x == autoDel)
u f = frequency [ (1, return '_')
, (74, arbitrary `suchThat` f) ]