packages feed

babynf-0.1.0.2: lib/Data/BAByNF/ABNF/ToParseable.hs

module Data.BAByNF.ABNF.ToParseable
    ( ToParseable
    , toParseable
    ) where

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

import Data.ByteString qualified as ByteString

import Data.Attoparsec.ByteString qualified as Attoparsec.ByteString

import Data.BAByNF.Util.Ascii qualified as Ascii
import Data.BAByNF.Util.Binary qualified as Binary
import Data.BAByNF.Util.Decimal qualified as Decimal
import Data.BAByNF.Util.Hex qualified as Hex
import Data.BAByNF.Core.Parseable (Parseable)
import Data.BAByNF.Core.Parseable qualified as Parseable
import Data.BAByNF.Core.Repeat qualified as Core.Repeat
import Data.BAByNF.Core.Tree (Tree (..))
import Data.BAByNF.Core.Tree qualified as Tree
import Data.BAByNF.ABNF.Model
import Data.BAByNF.ABNF.PrettyPrint

class ToParseable a where
  toParseable :: a -> Parseable Rulename

instance ToParseable Alternation where
  toParseable (Alternation x) = case x of
    [] -> error "empty alt"
    [z'] -> toParseable z'
    _:_ -> Parseable.Alt . List.NonEmpty.fromList . map toParseable $ x

instance ToParseable Concatenation where
  toParseable (Concatenation x) = case x of
    [] -> error "empty seq"
    [z'] -> toParseable z'
    _:_ -> Parseable.Seq . List.NonEmpty.fromList . map toParseable $ x

instance ToParseable Repetition where
  toParseable (Repetition r x) = 
    case r of 
      NoRepeat -> toParseable x 
      _ -> Parseable.Rep (toParseable x) (toRepeat r)
    where toRepeat NoRepeat = Core.Repeat.once
          toRepeat (FixedRepeat i) = Core.Repeat.exactly (fromInteger i)
          toRepeat (RangedRepeat lo hi) =
            let req = case lo of UnBound -> 0; (FixedBound l) -> fromInteger l
                opt = case hi of UnBound -> Nothing; (FixedBound h) -> if req > fromInteger h then error "fail" else Just $ fromInteger h - req
             in Core.Repeat.from req opt

instance ToParseable Element where
  toParseable e = case e of
    (RulenameElement r) -> toParseable r
    (GroupElement g) -> toParseable g
    (OptionElement o) -> toParseable o
    (CharValElement c) -> toParseable c
    (NumValElement n) -> toParseable n
    (ProseValElement p) -> toParseable p

instance ToParseable Rulename where
  toParseable = Parseable.Rule

instance ToParseable Group where
  toParseable (Group a) = toParseable a

instance ToParseable Option where
  toParseable (Option a) = Parseable.Rep (toParseable a) Core.Repeat.maybeOnce

instance ToParseable CharVal where
   toParseable charVal = case charVal of
    CaseInsensitiveCharVal ci -> toParseable ci
    CaseSensitiveCharVal cs -> toParseable cs

instance ToParseable CaseInsensitiveString where
  toParseable (CaseInsensitiveString x@(QuotedString b)) = Parseable.Unit (prettyPrint x) (Ascii.parseCaseInsensitive b <&> (\b' -> (Tree [Tree.StringNode b'])))

instance ToParseable CaseSensitiveString where
  toParseable (CaseSensitiveString x@(QuotedString b)) = Parseable.Unit (prettyPrint x) (Ascii.parseCaseSensitive b <&> (\b' -> (Tree [Tree.StringNode b'])))

instance ToParseable ProseVal where
  toParseable x = Parseable.Unit (prettyPrint x) (fail "prose-val not supported yet")


instance ToParseable NumVal where
  toParseable numVal = case numVal of
    BinNumVal b -> toParseable b
    DecNumVal d -> toParseable d
    HexNumVal x -> toParseable x

instance ToParseable BinVal where
  toParseable x = case x of
    SeqBinVal s -> Parseable.Unit (prettyPrint x)  $ Attoparsec.ByteString.string (ByteString.pack $ map Binary.toNum s) <&> (\b' -> Tree [Tree.StringNode b'])
    RangeBinVal lo hi -> Parseable.Unit (prettyPrint x) $ Attoparsec.ByteString.satisfy (\w -> w >= Binary.toNum lo && w <= Binary.toNum hi) <&> \w -> Tree [Tree.StringNode (ByteString.singleton w)]

instance ToParseable DecVal where
  toParseable x = case x of
    SeqDecVal s -> Parseable.Unit (prettyPrint x) $ Attoparsec.ByteString.string (ByteString.pack $ map Decimal.toNum s) <&> (\b' -> Tree [Tree.StringNode b'])
    RangeDecVal lo hi -> Parseable.Unit (prettyPrint x) $ Attoparsec.ByteString.satisfy (\w -> w >= Decimal.toNum lo && w <= Decimal.toNum hi) <&> \w -> Tree [Tree.StringNode (ByteString.singleton w)]

instance ToParseable HexVal where
  toParseable x = case x of
    SeqHexVal s -> Parseable.Unit (prettyPrint x) $ Attoparsec.ByteString.string (ByteString.pack $ map Hex.toNum s) <&> (\b' -> Tree [Tree.StringNode b'])
    RangeHexVal lo hi -> Parseable.Unit (prettyPrint x) $ Attoparsec.ByteString.satisfy (\w -> w >= Hex.toNum lo && w <= Hex.toNum hi) <&> \w -> Tree [Tree.StringNode (ByteString.singleton w)]