module Data.BAByNF.ABNF.Rules.Elements
    ( ref
    , rule
    , fromTree
    ) where

import Data.Functor ((<&>))
import Data.List qualified as List

import Data.BAByNF.Util.Ascii qualified as Ascii
import Data.BAByNF.Core.Tree (Tree)
import Data.BAByNF.Core.Tree qualified as Tree
import Data.BAByNF.ABNF.Rules.Alternation qualified as Alternation
import Data.BAByNF.ABNF.Rules.CWsp qualified as CWsp
import Data.BAByNF.ABNF.Model qualified as Model

ref :: Model.Rulename
ref :: Rulename
ref = ByteString -> Rulename
Model.Rulename (String -> ByteString
Ascii.stringAsBytesUnsafe String
"elements")

rule :: Model.Rule
rule :: Rule
rule = Rulename -> DefinedAs -> Elements -> Rule
Model.Rule Rulename
ref DefinedAs
Model.BasicDefinition 
    (Elements -> Rule)
-> ([Repetition] -> Elements) -> [Repetition] -> Rule
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Alternation -> Elements
Model.Elements
    (Alternation -> Elements)
-> ([Repetition] -> Alternation) -> [Repetition] -> Elements
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Concatenation] -> Alternation
Model.Alternation
    ([Concatenation] -> Alternation)
-> ([Repetition] -> [Concatenation]) -> [Repetition] -> Alternation
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Concatenation -> [Concatenation]
forall a. a -> [a]
List.singleton
    (Concatenation -> [Concatenation])
-> ([Repetition] -> Concatenation)
-> [Repetition]
-> [Concatenation]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Repetition] -> Concatenation
Model.Concatenation
    ([Repetition] -> Rule) -> [Repetition] -> Rule
forall a b. (a -> b) -> a -> b
$ 
        [ Repeat -> Element -> Repetition
Model.Repetition Repeat
Model.NoRepeat (Rulename -> Element
Model.RulenameElement Rulename
Alternation.ref)
        , Repeat -> Element -> Repetition
Model.Repetition (Bound -> Bound -> Repeat
Model.RangedRepeat Bound
Model.UnBound Bound
Model.UnBound) (Rulename -> Element
Model.RulenameElement Rulename
CWsp.ref)
        ]

fromTree :: Tree Model.Rulename -> Either String Model.Elements
fromTree :: Tree Rulename -> Either String Elements
fromTree Tree Rulename
tree = Rulename -> Tree Rulename -> Either String (Tree Rulename)
forall a. Ref a => a -> Tree a -> Either String (Tree a)
Tree.tryGetChildWithRef Rulename
Alternation.ref Tree Rulename
tree Either String (Tree Rulename)
-> (Tree Rulename -> Either String Alternation)
-> Either String Alternation
forall a b.
Either String a -> (a -> Either String b) -> Either String b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Tree Rulename -> Either String Alternation
Alternation.fromTree Either String Alternation
-> (Alternation -> Elements) -> Either String Elements
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> Alternation -> Elements
Model.Elements