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

import Data.Functor ((<&>))

import Data.BAByNF.Core.Tree (Tree)
import Data.BAByNF.Core.Tree qualified as Tree

import Data.Maybe (fromMaybe)
import Data.List qualified as List

import Control.Applicative ((<|>))

import Data.BAByNF.Util.Ascii qualified as Ascii
import Data.BAByNF.ABNF.Rules.CaseInsensitiveString qualified as CaseInsensitiveString
import Data.BAByNF.ABNF.Rules.CaseSensitiveString qualified as CaseSensitiveString
import Data.BAByNF.ABNF.Model qualified as Model

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

rule :: Model.Rule
rule :: Rule
rule = Rulename -> DefinedAs -> Elements -> Rule
Model.Rule Rulename
ref DefinedAs
Model.BasicDefinition
    (Elements -> Rule)
-> ([Concatenation] -> Elements) -> [Concatenation] -> Rule
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Alternation -> Elements
Model.Elements
    (Alternation -> Elements)
-> ([Concatenation] -> Alternation) -> [Concatenation] -> Elements
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Concatenation] -> Alternation
Model.Alternation
    ([Concatenation] -> Rule) -> [Concatenation] -> Rule
forall a b. (a -> b) -> a -> b
$
        [ [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 -> Concatenation) -> Element -> Concatenation
forall a b. (a -> b) -> a -> b
$ Rulename -> Element
Model.RulenameElement Rulename
CaseInsensitiveString.ref
        , [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 -> Concatenation) -> Element -> Concatenation
forall a b. (a -> b) -> a -> b
$ Rulename -> Element
Model.RulenameElement Rulename
CaseSensitiveString.ref
        ]

fromTree :: Tree Model.Rulename -> Either String Model.CharVal
fromTree :: Tree Rulename -> Either String CharVal
fromTree Tree Rulename
tree =
    Either String CharVal
-> Maybe (Either String CharVal) -> Either String CharVal
forall a. a -> Maybe a -> a
fromMaybe (String -> Either String CharVal
forall a b. a -> Either a b
Left String
"no string") (Maybe (Either String CharVal) -> Either String CharVal)
-> Maybe (Either String CharVal) -> Either String CharVal
forall a b. (a -> b) -> a -> b
$ Tree Rulename -> Maybe (Either String CharVal)
tryGetInsensitive Tree Rulename
tree Maybe (Either String CharVal)
-> Maybe (Either String CharVal) -> Maybe (Either String CharVal)
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Tree Rulename -> Maybe (Either String CharVal)
tryGetSensitive Tree Rulename
tree
    where tryGetInsensitive :: Tree Rulename -> Maybe (Either String CharVal)
tryGetInsensitive Tree Rulename
t = do
            Tree Rulename
subtree <- Rulename -> Tree Rulename -> Maybe (Tree Rulename)
forall a. a -> Tree a -> Maybe (Tree a)
Tree.getChildWithRef Rulename
CaseInsensitiveString.ref Tree Rulename
t
            Either String CharVal -> Maybe (Either String CharVal)
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String CharVal -> Maybe (Either String CharVal))
-> Either String CharVal -> Maybe (Either String CharVal)
forall a b. (a -> b) -> a -> b
$ Tree Rulename -> Either String CaseInsensitiveString
CaseInsensitiveString.fromTree Tree Rulename
subtree Either String CaseInsensitiveString
-> (CaseInsensitiveString -> CharVal) -> Either String CharVal
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> CaseInsensitiveString -> CharVal
Model.CaseInsensitiveCharVal
          tryGetSensitive :: Tree Rulename -> Maybe (Either String CharVal)
tryGetSensitive Tree Rulename
t = do
            Tree Rulename
subtree <- Rulename -> Tree Rulename -> Maybe (Tree Rulename)
forall a. a -> Tree a -> Maybe (Tree a)
Tree.getChildWithRef Rulename
CaseSensitiveString.ref Tree Rulename
t
            Either String CharVal -> Maybe (Either String CharVal)
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String CharVal -> Maybe (Either String CharVal))
-> Either String CharVal -> Maybe (Either String CharVal)
forall a b. (a -> b) -> a -> b
$ Tree Rulename -> Either String CaseSensitiveString
CaseSensitiveString.fromTree Tree Rulename
subtree Either String CaseSensitiveString
-> (CaseSensitiveString -> CharVal) -> Either String CharVal
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> CaseSensitiveString -> CharVal
Model.CaseSensitiveCharVal