packages feed

babynf-0.1.0.2: lib/Data/BAByNF/ABNF/Rules/NumVal.hs

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

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

import Data.ByteString qualified as ByteString

import Data.BAByNF.Core.Tree (Tree)
import Data.BAByNF.Core.Tree qualified as Tree
import Data.BAByNF.ABNF.Rules.BinVal qualified as BinVal
import Data.BAByNF.ABNF.Rules.DecVal qualified as DecVal
import Data.BAByNF.ABNF.Rules.HexVal qualified as HexVal
import Data.BAByNF.Util.Ascii qualified as Ascii
import Data.BAByNF.Core.Ref qualified as Ref
import Data.BAByNF.ABNF.Model qualified as Model

ref :: Model.Rulename
ref = Model.Rulename (Ascii.stringAsBytesUnsafe "num-val")

rule :: Model.Rule
rule = Model.Rule ref Model.BasicDefinition 
    . Model.Elements
    . Model.Alternation
    . List.singleton
    . Model.Concatenation
    $ 
        [ Model.Repetition Model.NoRepeat
            . Model.CharValElement
            . Model.CaseInsensitiveCharVal
            . Model.CaseInsensitiveString
            $ Model.QuotedString (Ascii.stringAsBytesUnsafe "%")
            
        , Model.Repetition Model.NoRepeat
            . Model.GroupElement
            . Model.Group
            . Model.Alternation
            $ 
                [ Model.Concatenation
                    . List.singleton
                    . Model.Repetition Model.NoRepeat
                    $ Model.RulenameElement BinVal.ref
                , Model.Concatenation
                    . List.singleton
                    . Model.Repetition Model.NoRepeat
                    $ Model.RulenameElement DecVal.ref
                , Model.Concatenation
                    . List.singleton
                    . Model.Repetition Model.NoRepeat
                    $ Model.RulenameElement HexVal.ref
                ]
        ]

fromTree :: Tree Model.Rulename -> Either String Model.NumVal
fromTree tree = case Tree.nodes tree of
    [Tree.StringNode b, Tree.RefNode r subtree] ->
        if b /= ByteString.singleton 37
            then Left "expected % prefix"
            else if Ref.eq r BinVal.ref then BinVal.fromTree subtree <&> Model.BinNumVal
                else if Ref.eq r DecVal.ref then DecVal.fromTree subtree <&> Model.DecNumVal
                else if Ref.eq r HexVal.ref then HexVal.fromTree subtree <&> Model.HexNumVal
                else Left "unexpected rule ref"
    _ -> Left "exactly two nodes expected - \"%\" and bin-val | dec-val | hex-val"