{-# OPTIONS_GHC -Wunused-imports #-}
module Agda.Syntax.Parser.Layout
( withLayout
, offsideRule
, newLayoutBlock
, emptyLayout
, confirmLayout
) where
import Control.Monad ( when )
import Control.Monad.State ( gets, modify )
import Agda.Syntax.Parser.Lexer
import Agda.Syntax.Parser.Alex
import Agda.Syntax.Parser.Monad
import Agda.Syntax.Parser.Tokens
import Agda.Syntax.Parser.LexActions
import Agda.Syntax.Position
import Agda.Utils.Functor ((<&>))
offsideRule :: LexAction Token
offsideRule :: LexAction Token
offsideRule = (PreviousInput -> PreviousInput -> Int -> Parser Token)
-> LexAction Token
forall r.
(PreviousInput -> PreviousInput -> Int -> Parser r) -> LexAction r
LexAction ((PreviousInput -> PreviousInput -> Int -> Parser Token)
-> LexAction Token)
-> (PreviousInput -> PreviousInput -> Int -> Parser Token)
-> LexAction Token
forall a b. (a -> b) -> a -> b
$ \ PreviousInput
inp PreviousInput
_ Int
_ -> do
let p :: PositionWithoutFile
p = PreviousInput -> PositionWithoutFile
lexPos PreviousInput
inp
i :: Interval' (Maybe RangeFile)
i = Maybe RangeFile
-> PositionWithoutFile
-> PositionWithoutFile
-> Interval' (Maybe RangeFile)
forall a.
a -> PositionWithoutFile -> PositionWithoutFile -> Interval' a
posToInterval (PreviousInput -> Maybe RangeFile
lexSrcFile PreviousInput
inp) PositionWithoutFile
p PositionWithoutFile
p
PositionWithoutFile -> Parser Ordering
forall a. Position' a -> Parser Ordering
getOffside PositionWithoutFile
p Parser Ordering -> (Ordering -> Parser Token) -> Parser Token
forall a b. Parser a -> (a -> Parser b) -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Ordering
LT -> do Parser ()
popBlock
Token -> Parser Token
forall a. a -> Parser a
forall (m :: * -> *) a. Monad m => a -> m a
return (Symbol -> Interval' (Maybe RangeFile) -> Token
TokSymbol Symbol
SymCloseVirtualBrace Interval' (Maybe RangeFile)
i)
Ordering
EQ -> do Parser ()
popLexState
Token -> Parser Token
forall a. a -> Parser a
forall (m :: * -> *) a. Monad m => a -> m a
return (Symbol -> Interval' (Maybe RangeFile) -> Token
TokSymbol Symbol
SymVirtualSemi Interval' (Maybe RangeFile)
i)
Ordering
GT -> do Parser ()
popLexState
Parser Token
lexToken
emptyLayout :: LexAction Token
emptyLayout :: LexAction Token
emptyLayout = (PreviousInput -> PreviousInput -> Int -> Parser Token)
-> LexAction Token
forall r.
(PreviousInput -> PreviousInput -> Int -> Parser r) -> LexAction r
LexAction ((PreviousInput -> PreviousInput -> Int -> Parser Token)
-> LexAction Token)
-> (PreviousInput -> PreviousInput -> Int -> Parser Token)
-> LexAction Token
forall a b. (a -> b) -> a -> b
$ \ PreviousInput
inp PreviousInput
_ Int
_ -> do
let p :: PositionWithoutFile
p = PreviousInput -> PositionWithoutFile
lexPos PreviousInput
inp
i :: Interval' (Maybe RangeFile)
i = Maybe RangeFile
-> PositionWithoutFile
-> PositionWithoutFile
-> Interval' (Maybe RangeFile)
forall a.
a -> PositionWithoutFile -> PositionWithoutFile -> Interval' a
posToInterval (PreviousInput -> Maybe RangeFile
lexSrcFile PreviousInput
inp) PositionWithoutFile
p PositionWithoutFile
p
Parser ()
popLexState
Int -> Parser ()
pushLexState Int
bol
Token -> Parser Token
forall a. a -> Parser a
forall (m :: * -> *) a. Monad m => a -> m a
return (Symbol -> Interval' (Maybe RangeFile) -> Token
TokSymbol Symbol
SymCloseVirtualBrace Interval' (Maybe RangeFile)
i)
newLayoutBlock :: LexAction Token
newLayoutBlock :: LexAction Token
newLayoutBlock = (PreviousInput -> PreviousInput -> Int -> Parser Token)
-> LexAction Token
forall r.
(PreviousInput -> PreviousInput -> Int -> Parser r) -> LexAction r
LexAction ((PreviousInput -> PreviousInput -> Int -> Parser Token)
-> LexAction Token)
-> (PreviousInput -> PreviousInput -> Int -> Parser Token)
-> LexAction Token
forall a b. (a -> b) -> a -> b
$ \ PreviousInput
inp PreviousInput
_ Int
_ -> do
let p :: PositionWithoutFile
p = PreviousInput -> PositionWithoutFile
lexPos PreviousInput
inp
i :: Interval' (Maybe RangeFile)
i = Maybe RangeFile
-> PositionWithoutFile
-> PositionWithoutFile
-> Interval' (Maybe RangeFile)
forall a.
a -> PositionWithoutFile -> PositionWithoutFile -> Interval' a
posToInterval (PreviousInput -> Maybe RangeFile
lexSrcFile PreviousInput
inp) PositionWithoutFile
p PositionWithoutFile
p
offset :: Word32
offset = PositionWithoutFile -> Word32
forall a. Position' a -> Word32
posCol PositionWithoutFile
p
status <- Parser LayoutStatus
popPendingLayout
kw <- gets parseLayKw
prevOffs <- confirmedLayoutColumn <$> getContext
if prevOffs >= offset
then pushLexState empty_layout
else do
when (status == Confirmed) $
modifyContext $ confirmTentativeBlocks $ Just offset
pushBlock $ Layout kw status offset
return $ TokSymbol SymOpenVirtualBrace i
where
popPendingLayout :: Parser LayoutStatus
popPendingLayout :: Parser LayoutStatus
popPendingLayout = do
status <- (ParseState -> LayoutStatus) -> Parser LayoutStatus
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets ParseState -> LayoutStatus
parseLayStatus
resetLayoutStatus
return status
confirmedLayoutColumn :: LayoutContext -> Column
confirmedLayoutColumn :: LayoutContext -> Word32
confirmedLayoutColumn = \case
Layout Keyword
_ LayoutStatus
Confirmed Word32
c : LayoutContext
_ -> Word32
c
Layout Keyword
_ LayoutStatus
Tentative Word32
_ : LayoutContext
cxt -> LayoutContext -> Word32
confirmedLayoutColumn LayoutContext
cxt
[] -> Word32
0
getOffside :: Position' a -> Parser Ordering
getOffside :: forall a. Position' a -> Parser Ordering
getOffside Position' a
loc =
Parser LayoutContext
forall (m :: * -> *). MonadState ParseState m => m LayoutContext
getContext Parser LayoutContext
-> (LayoutContext -> Ordering) -> Parser Ordering
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \case
Layout Keyword
_ LayoutStatus
_ Word32
n : LayoutContext
_ -> Word32 -> Word32 -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Position' a -> Word32
forall a. Position' a -> Word32
posCol Position' a
loc) Word32
n
LayoutContext
_ -> Ordering
GT
confirmLayout :: Parser ()
confirmLayout :: Parser ()
confirmLayout = Parser [Int]
getLexState Parser [Int] -> ([Int] -> Parser ()) -> Parser ()
forall a b. Parser a -> (a -> Parser b) -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ case
Int
s : [Int]
_ | Int
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
layout -> Parser ()
confirmedLayoutComing
[Int]
_ -> Parser ()
confirmLayoutAtNewLine
where
confirmedLayoutComing :: Parser ()
confirmedLayoutComing :: Parser ()
confirmedLayoutComing = (ParseState -> ParseState) -> Parser ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((ParseState -> ParseState) -> Parser ())
-> (ParseState -> ParseState) -> Parser ()
forall a b. (a -> b) -> a -> b
$ \ ParseState
s -> ParseState
s { parseLayStatus = Confirmed }
confirmLayoutAtNewLine :: Parser ()
confirmLayoutAtNewLine :: Parser ()
confirmLayoutAtNewLine = (LayoutContext -> LayoutContext) -> Parser ()
modifyContext ((LayoutContext -> LayoutContext) -> Parser ())
-> (LayoutContext -> LayoutContext) -> Parser ()
forall a b. (a -> b) -> a -> b
$ Maybe Word32 -> LayoutContext -> LayoutContext
confirmTentativeBlocks Maybe Word32
forall a. Maybe a
Nothing
confirmTentativeBlocks :: Maybe Column -> LayoutContext -> LayoutContext
confirmTentativeBlocks :: Maybe Word32 -> LayoutContext -> LayoutContext
confirmTentativeBlocks Maybe Word32
mcol = \case
Layout Keyword
kw LayoutStatus
Tentative Word32
col : LayoutContext
cxt | Bool -> (Word32 -> Bool) -> Maybe Word32 -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
True (Word32
col Word32 -> Word32 -> Bool
forall a. Ord a => a -> a -> Bool
<) Maybe Word32
mcol
-> Keyword -> LayoutStatus -> Word32 -> LayoutBlock
Layout Keyword
kw LayoutStatus
Confirmed Word32
col LayoutBlock -> LayoutContext -> LayoutContext
forall a. a -> [a] -> [a]
: Maybe Word32 -> LayoutContext -> LayoutContext
confirmTentativeBlocks (Word32 -> Maybe Word32
forall a. a -> Maybe a
Just Word32
col) LayoutContext
cxt
LayoutContext
cxt -> LayoutContext
cxt