module Text.Layout.OffSides (
Layout(..),
layout,
wrapToken,
) where
import AlexTools
import qualified Data.Text as T
data Layout tok = Layout { beginsLayout :: tok -> Bool
, endsLayout :: tok -> Bool
, sep :: SourceRange -> Lexeme tok
, start :: SourceRange -> Lexeme tok
, end :: SourceRange -> Lexeme tok
}
wrapToken :: tok -> SourceRange -> Lexeme tok
wrapToken lexemeToken lexemeRange = Lexeme { lexemeText = T.empty, .. }
layout :: Layout tok -> [Lexeme tok] -> [Lexeme tok]
layout Layout { .. } = go Nothing []
where
startCol SourceRange { sourceFrom = SourcePos { .. } } = sourceColumn
currentLevel (loc : _) = startCol loc
currentLevel [] = 0
go Just{} stack (tok : toks) =
let loc = lexemeRange tok
in start loc : tok : go Nothing (loc:stack) toks
go (Just loc) stack [] =
start loc : go Nothing (loc : stack) []
go Nothing stack ts@(tok : toks)
| startCol loc < currentLevel stack =
end loc : go Nothing (tail stack) ts
| beginsLayout (lexemeToken tok) =
let sepToks | startCol loc == currentLevel stack = [sep loc]
| otherwise = []
in sepToks ++ tok : go (Just loc) stack toks
| endsLayout (lexemeToken tok) =
end loc : tok : go Nothing (tail stack) toks
| startCol loc == currentLevel stack =
sep loc : tok : go Nothing stack toks
| otherwise =
tok : go Nothing stack toks
where
loc = lexemeRange tok
go _ stack [] =
[ end loc | loc <- stack ]