module Mello.Text
  ( Brace (..)
  , openBraceChar
  , closeBraceChar
  , readOpenBrace
  , readCloseBrace
  , isSymStart
  , isSymCont
  , isListStart
  , isListEnd
  , isCharStart
  , isStringStart
  , isQuoteStart
  , isUnquoteStart
  , isCommentStart
  , isDocCont
  , isNumStart
  , isAtomStart
  )
where

import Data.Char (isControl, isDigit, isSpace)

data Brace = BraceParen | BraceCurly | BraceSquare
  deriving stock (Brace -> Brace -> Bool
(Brace -> Brace -> Bool) -> (Brace -> Brace -> Bool) -> Eq Brace
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Brace -> Brace -> Bool
== :: Brace -> Brace -> Bool
$c/= :: Brace -> Brace -> Bool
/= :: Brace -> Brace -> Bool
Eq, Eq Brace
Eq Brace =>
(Brace -> Brace -> Ordering)
-> (Brace -> Brace -> Bool)
-> (Brace -> Brace -> Bool)
-> (Brace -> Brace -> Bool)
-> (Brace -> Brace -> Bool)
-> (Brace -> Brace -> Brace)
-> (Brace -> Brace -> Brace)
-> Ord Brace
Brace -> Brace -> Bool
Brace -> Brace -> Ordering
Brace -> Brace -> Brace
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Brace -> Brace -> Ordering
compare :: Brace -> Brace -> Ordering
$c< :: Brace -> Brace -> Bool
< :: Brace -> Brace -> Bool
$c<= :: Brace -> Brace -> Bool
<= :: Brace -> Brace -> Bool
$c> :: Brace -> Brace -> Bool
> :: Brace -> Brace -> Bool
$c>= :: Brace -> Brace -> Bool
>= :: Brace -> Brace -> Bool
$cmax :: Brace -> Brace -> Brace
max :: Brace -> Brace -> Brace
$cmin :: Brace -> Brace -> Brace
min :: Brace -> Brace -> Brace
Ord, Int -> Brace -> ShowS
[Brace] -> ShowS
Brace -> String
(Int -> Brace -> ShowS)
-> (Brace -> String) -> ([Brace] -> ShowS) -> Show Brace
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Brace -> ShowS
showsPrec :: Int -> Brace -> ShowS
$cshow :: Brace -> String
show :: Brace -> String
$cshowList :: [Brace] -> ShowS
showList :: [Brace] -> ShowS
Show, Int -> Brace
Brace -> Int
Brace -> [Brace]
Brace -> Brace
Brace -> Brace -> [Brace]
Brace -> Brace -> Brace -> [Brace]
(Brace -> Brace)
-> (Brace -> Brace)
-> (Int -> Brace)
-> (Brace -> Int)
-> (Brace -> [Brace])
-> (Brace -> Brace -> [Brace])
-> (Brace -> Brace -> [Brace])
-> (Brace -> Brace -> Brace -> [Brace])
-> Enum Brace
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: Brace -> Brace
succ :: Brace -> Brace
$cpred :: Brace -> Brace
pred :: Brace -> Brace
$ctoEnum :: Int -> Brace
toEnum :: Int -> Brace
$cfromEnum :: Brace -> Int
fromEnum :: Brace -> Int
$cenumFrom :: Brace -> [Brace]
enumFrom :: Brace -> [Brace]
$cenumFromThen :: Brace -> Brace -> [Brace]
enumFromThen :: Brace -> Brace -> [Brace]
$cenumFromTo :: Brace -> Brace -> [Brace]
enumFromTo :: Brace -> Brace -> [Brace]
$cenumFromThenTo :: Brace -> Brace -> Brace -> [Brace]
enumFromThenTo :: Brace -> Brace -> Brace -> [Brace]
Enum, Brace
Brace -> Brace -> Bounded Brace
forall a. a -> a -> Bounded a
$cminBound :: Brace
minBound :: Brace
$cmaxBound :: Brace
maxBound :: Brace
Bounded)

openBraceChar :: Brace -> Char
openBraceChar :: Brace -> Char
openBraceChar = \case
  Brace
BraceParen -> Char
'('
  Brace
BraceCurly -> Char
'{'
  Brace
BraceSquare -> Char
'['

closeBraceChar :: Brace -> Char
closeBraceChar :: Brace -> Char
closeBraceChar = \case
  Brace
BraceParen -> Char
')'
  Brace
BraceCurly -> Char
'}'
  Brace
BraceSquare -> Char
']'

readOpenBrace :: Char -> Maybe Brace
readOpenBrace :: Char -> Maybe Brace
readOpenBrace = \case
  Char
'(' -> Brace -> Maybe Brace
forall a. a -> Maybe a
Just Brace
BraceParen
  Char
'{' -> Brace -> Maybe Brace
forall a. a -> Maybe a
Just Brace
BraceCurly
  Char
'[' -> Brace -> Maybe Brace
forall a. a -> Maybe a
Just Brace
BraceSquare
  Char
_ -> Maybe Brace
forall a. Maybe a
Nothing

readCloseBrace :: Char -> Maybe Brace
readCloseBrace :: Char -> Maybe Brace
readCloseBrace = \case
  Char
')' -> Brace -> Maybe Brace
forall a. a -> Maybe a
Just Brace
BraceParen
  Char
'}' -> Brace -> Maybe Brace
forall a. a -> Maybe a
Just Brace
BraceCurly
  Char
']' -> Brace -> Maybe Brace
forall a. a -> Maybe a
Just Brace
BraceSquare
  Char
_ -> Maybe Brace
forall a. Maybe a
Nothing

isSymStart
  , isSymCont
  , isListStart
  , isListEnd
  , isCharStart
  , isStringStart
  , isQuoteStart
  , isUnquoteStart
  , isCommentStart
  , isDocCont
  , isNumStart
  , isAtomStart
    :: Char -> Bool
isSymStart :: Char -> Bool
isSymStart Char
c = Bool -> Bool
not (Char -> Bool
isDigit Char
c) Bool -> Bool -> Bool
&& Char -> Bool
isSymCont Char
c
isSymCont :: Char -> Bool
isSymCont Char
c =
  Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$
    Char -> Bool
isControl Char
c
      Bool -> Bool -> Bool
|| Char -> Bool
isSpace Char
c
      Bool -> Bool -> Bool
|| Char -> Bool
isCommentStart Char
c
      Bool -> Bool -> Bool
|| Char -> Bool
isListStart Char
c
      Bool -> Bool -> Bool
|| Char -> Bool
isListEnd Char
c
      Bool -> Bool -> Bool
|| Char -> Bool
isStringStart Char
c
      Bool -> Bool -> Bool
|| Char -> Bool
isCharStart Char
c
      Bool -> Bool -> Bool
|| Char -> Bool
isQuoteStart Char
c
      Bool -> Bool -> Bool
|| Char -> Bool
isUnquoteStart Char
c
      Bool -> Bool -> Bool
|| Char -> Bool
isDigit Char
c
isListStart :: Char -> Bool
isListStart Char
c = Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'(' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'{' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'['
isListEnd :: Char -> Bool
isListEnd Char
c = Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
')' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'}' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
']'
isCharStart :: Char -> Bool
isCharStart Char
c = Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\''
isStringStart :: Char -> Bool
isStringStart Char
c = Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\"'
isQuoteStart :: Char -> Bool
isQuoteStart Char
c = Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'`'
isUnquoteStart :: Char -> Bool
isUnquoteStart Char
c = Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
','
isCommentStart :: Char -> Bool
isCommentStart Char
c = Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
';'
isDocCont :: Char -> Bool
isDocCont Char
c = Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'|'
isNumStart :: Char -> Bool
isNumStart Char
c = Char -> Bool
isDigit Char
c Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'-'
isAtomStart :: Char -> Bool
isAtomStart Char
c =
  Char -> Bool
isSymStart Char
c
    Bool -> Bool -> Bool
|| Char -> Bool
isNumStart Char
c
    Bool -> Bool -> Bool
|| Char -> Bool
isStringStart Char
c
    Bool -> Bool -> Bool
|| Char -> Bool
isCharStart Char
c