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

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.Repeat qualified as Repeat
import Data.BAByNF.ABNF.Rules.Element qualified as Element
import Data.BAByNF.ABNF.Model qualified as Model

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

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 
            (Element -> Repetition)
-> (Element -> Element) -> Element -> Repetition
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Option -> Element
Model.OptionElement
            (Option -> Element) -> (Element -> Option) -> Element -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Alternation -> Option
Model.Option
            (Alternation -> Option)
-> (Element -> Alternation) -> Element -> Option
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Concatenation] -> Alternation
Model.Alternation
            ([Concatenation] -> Alternation)
-> (Element -> [Concatenation]) -> Element -> Alternation
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Concatenation -> [Concatenation]
forall a. a -> [a]
List.singleton
            (Concatenation -> [Concatenation])
-> (Element -> Concatenation) -> Element -> [Concatenation]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Repetition] -> Concatenation
Model.Concatenation
            ([Repetition] -> Concatenation)
-> (Element -> [Repetition]) -> Element -> Concatenation
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Repetition -> [Repetition]
forall a. a -> [a]
List.singleton
            (Repetition -> [Repetition])
-> (Element -> Repetition) -> Element -> [Repetition]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Repeat -> Element -> Repetition
Model.Repetition Repeat
Model.NoRepeat
            (Element -> Repetition) -> Element -> Repetition
forall a b. (a -> b) -> a -> b
$ Rulename -> Element
Model.RulenameElement Rulename
Repeat.ref
        , Repeat -> Element -> Repetition
Model.Repetition Repeat
Model.NoRepeat
            (Element -> Repetition) -> Element -> Repetition
forall a b. (a -> b) -> a -> b
$ Rulename -> Element
Model.RulenameElement Rulename
Element.ref
        ]

fromTree :: Tree Model.Rulename -> Either String Model.Repetition
fromTree :: Tree Rulename -> Either String Repetition
fromTree Tree Rulename
tree =
    let rd :: Either String Repeat
rd = Either String Repeat
-> (Tree Rulename -> Either String Repeat)
-> Maybe (Tree Rulename)
-> Either String Repeat
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Repeat -> Either String Repeat
forall a b. b -> Either a b
Right Repeat
Model.NoRepeat) Tree Rulename -> Either String Repeat
Repeat.fromTree  (Rulename -> Tree Rulename -> Maybe (Tree Rulename)
forall a. a -> Tree a -> Maybe (Tree a)
Tree.getChildWithRef Rulename
Repeat.ref Tree Rulename
tree)
        e :: Either String Element
e = Rulename -> Tree Rulename -> Either String (Tree Rulename)
forall a. Ref a => a -> Tree a -> Either String (Tree a)
Tree.tryGetChildWithRef Rulename
Element.ref Tree Rulename
tree Either String (Tree Rulename)
-> (Tree Rulename -> Either String Element)
-> Either String Element
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 Element
Element.fromTree
     in Either String Repeat
rd Either String Repeat
-> (Repeat -> Either String Repetition) -> Either String Repetition
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
>>= \Repeat
rd' ->
         Either String Element
e Either String Element
-> (Element -> Either String Repetition)
-> Either String Repetition
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
>>= \Element
e' -> Repetition -> Either String Repetition
forall a. a -> Either String a
forall (m :: * -> *) a. Monad m => a -> m a
return (Repetition -> Either String Repetition)
-> Repetition -> Either String Repetition
forall a b. (a -> b) -> a -> b
$ Repeat -> Element -> Repetition
Model.Repetition Repeat
rd' Element
e'