module Text.Parser.Indentation.Implementation where
type Indentation = Int
data IndentationRel = Eq | Any | Const Indentation | Ge | Gt deriving (Int -> IndentationRel -> ShowS
[IndentationRel] -> ShowS
IndentationRel -> String
(Int -> IndentationRel -> ShowS)
-> (IndentationRel -> String)
-> ([IndentationRel] -> ShowS)
-> Show IndentationRel
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IndentationRel] -> ShowS
$cshowList :: [IndentationRel] -> ShowS
show :: IndentationRel -> String
$cshow :: IndentationRel -> String
showsPrec :: Int -> IndentationRel -> ShowS
$cshowsPrec :: Int -> IndentationRel -> ShowS
Show, IndentationRel -> IndentationRel -> Bool
(IndentationRel -> IndentationRel -> Bool)
-> (IndentationRel -> IndentationRel -> Bool) -> Eq IndentationRel
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: IndentationRel -> IndentationRel -> Bool
$c/= :: IndentationRel -> IndentationRel -> Bool
== :: IndentationRel -> IndentationRel -> Bool
$c== :: IndentationRel -> IndentationRel -> Bool
Eq)
{-# INLINE infIndentation #-}
infIndentation :: Indentation
infIndentation :: Int
infIndentation = Int
forall a. Bounded a => a
maxBound
{-# INLINE mkIndentationState #-}
mkIndentationState :: Indentation -> Indentation -> Bool -> IndentationRel -> IndentationState
mkIndentationState :: Int -> Int -> Bool -> IndentationRel -> IndentationState
mkIndentationState Int
lo Int
hi Bool
mode IndentationRel
rel
| Int
lo Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
infIndentation = String -> IndentationState
forall a. HasCallStack => String -> a
error String
"mkIndentationState: minimum indentation 'infIndentation' is out of bounds"
| Int
lo Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
hi = String -> IndentationState
forall a. HasCallStack => String -> a
error String
"mkIndentationState: minimum indentation is greater than maximum indent"
| Bool
otherwise = Int -> Int -> Bool -> IndentationRel -> IndentationState
IndentationState Int
lo Int
hi Bool
mode IndentationRel
rel
data IndentationState = IndentationState {
IndentationState -> Int
minIndentation :: {-# UNPACK #-} !Indentation,
IndentationState -> Int
maxIndentation :: {-# UNPACK #-} !Indentation,
IndentationState -> Bool
absMode :: !Bool,
IndentationState -> IndentationRel
tokenRel :: !IndentationRel
} deriving (Int -> IndentationState -> ShowS
[IndentationState] -> ShowS
IndentationState -> String
(Int -> IndentationState -> ShowS)
-> (IndentationState -> String)
-> ([IndentationState] -> ShowS)
-> Show IndentationState
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IndentationState] -> ShowS
$cshowList :: [IndentationState] -> ShowS
show :: IndentationState -> String
$cshow :: IndentationState -> String
showsPrec :: Int -> IndentationState -> ShowS
$cshowsPrec :: Int -> IndentationState -> ShowS
Show)
{-# INLINE indentationStateAbsMode #-}
indentationStateAbsMode :: IndentationState -> Bool
indentationStateAbsMode :: IndentationState -> Bool
indentationStateAbsMode IndentationState
x = IndentationState -> Bool
absMode IndentationState
x
{-# INLINE updateIndentation #-}
updateIndentation :: IndentationState -> Indentation -> (IndentationState -> a) -> (String -> a) -> a
updateIndentation :: IndentationState
-> Int -> (IndentationState -> a) -> (String -> a) -> a
updateIndentation (IndentationState Int
lo Int
hi Bool
mode IndentationRel
rel) Int
i IndentationState -> a
ok String -> a
err = Int
-> Int
-> IndentationRel
-> Int
-> (Int -> Int -> a)
-> (String -> a)
-> a
forall a.
Int
-> Int
-> IndentationRel
-> Int
-> (Int -> Int -> a)
-> (String -> a)
-> a
updateIndentation' Int
lo Int
hi (if Bool
mode then IndentationRel
Eq else IndentationRel
rel) Int
i Int -> Int -> a
ok' String -> a
err' where
ok' :: Int -> Int -> a
ok' Int
lo' Int
hi' = IndentationState -> a
ok (Int -> Int -> Bool -> IndentationRel -> IndentationState
IndentationState Int
lo' Int
hi' Bool
False IndentationRel
rel)
err' :: String -> a
err' = String -> a
err
{-# INLINE updateIndentation' #-}
updateIndentation' :: Indentation -> Indentation -> IndentationRel -> Indentation -> (Indentation -> Indentation -> a) -> (String -> a) -> a
updateIndentation' :: Int
-> Int
-> IndentationRel
-> Int
-> (Int -> Int -> a)
-> (String -> a)
-> a
updateIndentation' Int
lo Int
hi IndentationRel
rel Int
i Int -> Int -> a
ok String -> a
err =
case IndentationRel
rel of
IndentationRel
Any -> Int -> Int -> a
ok Int
lo Int
hi
Const Int
c | Int
c Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
i -> Int -> Int -> a
ok Int
lo Int
hi
| Bool
otherwise -> String -> a
err' (String -> a) -> String -> a
forall a b. (a -> b) -> a -> b
$ String
"indentation "String -> ShowS
forall a. [a] -> [a] -> [a]
++Int -> String
forall a. Show a => a -> String
show Int
c
IndentationRel
Eq | Int
lo Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
i Bool -> Bool -> Bool
&& Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
hi -> Int -> Int -> a
ok Int
i Int
i
| Bool
otherwise -> String -> a
err' (String -> a) -> String -> a
forall a b. (a -> b) -> a -> b
$ String
"an indentation between "String -> ShowS
forall a. [a] -> [a] -> [a]
++Int -> String
forall a. Show a => a -> String
show Int
loString -> ShowS
forall a. [a] -> [a] -> [a]
++String
" and "String -> ShowS
forall a. [a] -> [a] -> [a]
++Int -> String
forall a. Show a => a -> String
show Int
hi
IndentationRel
Gt | Int
lo Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
i -> Int -> Int -> a
ok Int
lo (Int -> Int -> Int
forall a. Ord a => a -> a -> a
min (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) Int
hi)
| Bool
otherwise -> String -> a
err' (String -> a) -> String -> a
forall a b. (a -> b) -> a -> b
$ String
"an indentation greater than "String -> ShowS
forall a. [a] -> [a] -> [a]
++Int -> String
forall a. Show a => a -> String
show Int
lo
IndentationRel
Ge | Int
lo Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
i -> Int -> Int -> a
ok Int
lo (Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
i Int
hi)
| Bool
otherwise -> String -> a
err' (String -> a) -> String -> a
forall a b. (a -> b) -> a -> b
$ String
"an indentation greater than or equal to "String -> ShowS
forall a. [a] -> [a] -> [a]
++Int -> String
forall a. Show a => a -> String
show Int
lo
where err' :: String -> a
err' String
place = String -> a
err (String -> a) -> String -> a
forall a b. (a -> b) -> a -> b
$ String
"Found a token at indentation "String -> ShowS
forall a. [a] -> [a] -> [a]
++Int -> String
forall a. Show a => a -> String
show Int
iString -> ShowS
forall a. [a] -> [a] -> [a]
++String
". Expecting a token at "String -> ShowS
forall a. [a] -> [a] -> [a]
++String
placeString -> ShowS
forall a. [a] -> [a] -> [a]
++String
"."
type LocalState a = (IndentationState -> IndentationState)
-> (IndentationState -> IndentationState -> IndentationState)
-> a -> a
{-# INLINE localTokenMode #-}
localTokenMode :: (LocalState a)
-> (IndentationRel -> IndentationRel)
-> a -> a
localTokenMode :: LocalState a -> (IndentationRel -> IndentationRel) -> a -> a
localTokenMode LocalState a
localState IndentationRel -> IndentationRel
f_rel = LocalState a
localState IndentationState -> IndentationState
pre IndentationState -> IndentationState -> IndentationState
post where
pre :: IndentationState -> IndentationState
pre IndentationState
i1 = IndentationState
i1 { tokenRel :: IndentationRel
tokenRel = IndentationRel -> IndentationRel
f_rel (IndentationState -> IndentationRel
tokenRel IndentationState
i1) }
post :: IndentationState -> IndentationState -> IndentationState
post IndentationState
i1 IndentationState
i2 = IndentationState
i2 { tokenRel :: IndentationRel
tokenRel = IndentationState -> IndentationRel
tokenRel IndentationState
i1 }
{-# INLINE absoluteIndentation #-}
absoluteIndentation :: LocalState a -> a -> a
absoluteIndentation :: LocalState a -> a -> a
absoluteIndentation LocalState a
localState = LocalState a
localState IndentationState -> IndentationState
pre IndentationState -> IndentationState -> IndentationState
post where
pre :: IndentationState -> IndentationState
pre IndentationState
i1 = IndentationState
i1 { absMode :: Bool
absMode = Bool
True }
post :: IndentationState -> IndentationState -> IndentationState
post IndentationState
i1 IndentationState
i2 = IndentationState
i2 { absMode :: Bool
absMode = IndentationState -> Bool
absMode IndentationState
i1 Bool -> Bool -> Bool
&& IndentationState -> Bool
absMode IndentationState
i2 }
{-# INLINE ignoreAbsoluteIndentation #-}
ignoreAbsoluteIndentation :: LocalState a -> a -> a
ignoreAbsoluteIndentation :: LocalState a -> a -> a
ignoreAbsoluteIndentation LocalState a
localState = LocalState a
localState IndentationState -> IndentationState
pre IndentationState -> IndentationState -> IndentationState
post where
pre :: IndentationState -> IndentationState
pre IndentationState
i1 = IndentationState
i1 { absMode :: Bool
absMode = Bool
False }
post :: IndentationState -> IndentationState -> IndentationState
post IndentationState
i1 IndentationState
i2 = IndentationState
i2 { absMode :: Bool
absMode = IndentationState -> Bool
absMode IndentationState
i1 }
{-# INLINE localAbsoluteIndentation #-}
localAbsoluteIndentation :: LocalState a -> a -> a
localAbsoluteIndentation :: LocalState a -> a -> a
localAbsoluteIndentation LocalState a
localState = LocalState a
localState IndentationState -> IndentationState
pre IndentationState -> IndentationState -> IndentationState
post where
pre :: IndentationState -> IndentationState
pre IndentationState
i1 = IndentationState
i1 { absMode :: Bool
absMode = Bool
True }
post :: IndentationState -> IndentationState -> IndentationState
post IndentationState
i1 IndentationState
i2 = IndentationState
i2 { absMode :: Bool
absMode = IndentationState -> Bool
absMode IndentationState
i1 }
{-# INLINE localIndentation' #-}
localIndentation' :: LocalState a -> (Indentation -> Indentation) -> (Indentation -> Indentation) -> (Indentation -> Indentation -> Indentation) -> a -> a
localIndentation' :: LocalState a
-> (Int -> Int) -> (Int -> Int) -> (Int -> Int -> Int) -> a -> a
localIndentation' LocalState a
localState Int -> Int
f_lo Int -> Int
f_hi Int -> Int -> Int
f_hi' a
m = LocalState a
localState IndentationState -> IndentationState
pre IndentationState -> IndentationState -> IndentationState
post a
m
where pre :: IndentationState -> IndentationState
pre (IndentationState Int
lo Int
hi Bool
mode IndentationRel
rel) = Int -> Int -> Bool -> IndentationRel -> IndentationState
IndentationState (Int -> Int
f_lo Int
lo) (Int -> Int
f_hi Int
hi) Bool
mode IndentationRel
rel
post :: IndentationState -> IndentationState -> IndentationState
post (IndentationState Int
lo Int
hi Bool
_ IndentationRel
_) IndentationState
i2 = IndentationState
i2 { minIndentation :: Int
minIndentation = Int
lo, maxIndentation :: Int
maxIndentation = Int -> Int -> Int
f_hi' Int
hi (IndentationState -> Int
maxIndentation IndentationState
i2) }
{-# INLINE localIndentation #-}
localIndentation :: LocalState a -> IndentationRel -> a -> a
localIndentation :: LocalState a -> IndentationRel -> a -> a
localIndentation LocalState a
_localState IndentationRel
Eq a
m = a
m
localIndentation LocalState a
localState IndentationRel
Any a
m = LocalState a
-> (Int -> Int) -> (Int -> Int) -> (Int -> Int -> Int) -> a -> a
forall a.
LocalState a
-> (Int -> Int) -> (Int -> Int) -> (Int -> Int -> Int) -> a -> a
localIndentation' LocalState a
localState (Int -> Int -> Int
forall a b. a -> b -> a
const Int
0) (Int -> Int -> Int
forall a b. a -> b -> a
const Int
infIndentation) (Int -> Int -> Int
forall a b. a -> b -> a
const) a
m
localIndentation LocalState a
localState (Const Int
c) a
m
| Int
c Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
infIndentation = String -> a
forall a. HasCallStack => String -> a
error String
"localIndentation: Const indentation 'infIndentation' is out of bounds"
| Bool
otherwise = LocalState a
-> (Int -> Int) -> (Int -> Int) -> (Int -> Int -> Int) -> a -> a
forall a.
LocalState a
-> (Int -> Int) -> (Int -> Int) -> (Int -> Int -> Int) -> a -> a
localIndentation' LocalState a
localState (Int -> Int -> Int
forall a b. a -> b -> a
const Int
c) (Int -> Int -> Int
forall a b. a -> b -> a
const Int
c) (Int -> Int -> Int
forall a b. a -> b -> a
const) a
m
localIndentation LocalState a
localState IndentationRel
Ge a
m = LocalState a
-> (Int -> Int) -> (Int -> Int) -> (Int -> Int -> Int) -> a -> a
forall a.
LocalState a
-> (Int -> Int) -> (Int -> Int) -> (Int -> Int -> Int) -> a -> a
localIndentation' LocalState a
localState (Int -> Int
forall a. a -> a
id) (Int -> Int -> Int
forall a b. a -> b -> a
const Int
infIndentation) ((Int -> Int -> Int) -> Int -> Int -> Int
forall a b c. (a -> b -> c) -> b -> a -> c
flip Int -> Int -> Int
forall a b. a -> b -> a
const) a
m
localIndentation LocalState a
localState IndentationRel
Gt a
m = LocalState a
-> (Int -> Int) -> (Int -> Int) -> (Int -> Int -> Int) -> a -> a
forall a.
LocalState a
-> (Int -> Int) -> (Int -> Int) -> (Int -> Int -> Int) -> a -> a
localIndentation' LocalState a
localState (Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) (Int -> Int -> Int
forall a b. a -> b -> a
const Int
infIndentation) (Int -> Int -> Int
f) ( a
m) where
f :: Int -> Int -> Int
f Int
hi Int
hi' | Int
hi' Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
infIndentation Bool -> Bool -> Bool
|| Int
hi Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
hi' = Int
hi
| Int
hi' Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 = Int
hi' Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
| Bool
otherwise = String -> Int
forall a. HasCallStack => String -> a
error String
"localIndentation: assertion failed: hi' > 0"