{-# OPTIONS_GHC -Wwarn #-}
module Ide.Plugin.Eval.Parse.Token (
Token(..),
TokenS,
tokensFrom,
unsafeContent,
isStatement,
isTextLine,
isPropLine,
isCodeLine,
isBlockOpen,
isBlockClose
) where
import Control.Monad.Combinators (many, optional, skipManyTill,
(<|>))
import Data.Functor (($>))
import Data.List (foldl')
import Ide.Plugin.Eval.Parse.Parser (Parser, alphaNumChar, char,
letterChar, runParser, satisfy,
space, string, tillEnd)
import Ide.Plugin.Eval.Types (Format (..), Language (..), Loc,
Located (Located))
import Maybes (fromJust, fromMaybe)
type TParser = Parser Char (State, [TokenS])
data State = InCode | | deriving (State -> State -> Bool
(State -> State -> Bool) -> (State -> State -> Bool) -> Eq State
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: State -> State -> Bool
$c/= :: State -> State -> Bool
== :: State -> State -> Bool
$c== :: State -> State -> Bool
Eq, Int -> State -> ShowS
[State] -> ShowS
State -> String
(Int -> State -> ShowS)
-> (State -> String) -> ([State] -> ShowS) -> Show State
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [State] -> ShowS
$cshowList :: [State] -> ShowS
show :: State -> String
$cshow :: State -> String
showsPrec :: Int -> State -> ShowS
$cshowsPrec :: Int -> State -> ShowS
Show)
commentState :: Bool -> State
Bool
True = State
InMultiComment
commentState Bool
False = State
InSingleComment
type TokenS = Token String
data Token s
=
Statement s
|
PropLine s
|
TextLine s
|
CodeLine
|
BlockOpen {Token s -> Maybe s
blockName :: Maybe s, Token s -> Language
blockLanguage :: Language, Token s -> Format
blockFormat :: Format}
|
BlockClose
deriving (Token s -> Token s -> Bool
(Token s -> Token s -> Bool)
-> (Token s -> Token s -> Bool) -> Eq (Token s)
forall s. Eq s => Token s -> Token s -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Token s -> Token s -> Bool
$c/= :: forall s. Eq s => Token s -> Token s -> Bool
== :: Token s -> Token s -> Bool
$c== :: forall s. Eq s => Token s -> Token s -> Bool
Eq, Int -> Token s -> ShowS
[Token s] -> ShowS
Token s -> String
(Int -> Token s -> ShowS)
-> (Token s -> String) -> ([Token s] -> ShowS) -> Show (Token s)
forall s. Show s => Int -> Token s -> ShowS
forall s. Show s => [Token s] -> ShowS
forall s. Show s => Token s -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Token s] -> ShowS
$cshowList :: forall s. Show s => [Token s] -> ShowS
show :: Token s -> String
$cshow :: forall s. Show s => Token s -> String
showsPrec :: Int -> Token s -> ShowS
$cshowsPrec :: forall s. Show s => Int -> Token s -> ShowS
Show)
isStatement :: Token s -> Bool
isStatement :: Token s -> Bool
isStatement (Statement s
_) = Bool
True
isStatement Token s
_ = Bool
False
isTextLine :: Token s -> Bool
isTextLine :: Token s -> Bool
isTextLine (TextLine s
_) = Bool
True
isTextLine Token s
_ = Bool
False
isPropLine :: Token s -> Bool
isPropLine :: Token s -> Bool
isPropLine (PropLine s
_) = Bool
True
isPropLine Token s
_ = Bool
False
isCodeLine :: Token s -> Bool
isCodeLine :: Token s -> Bool
isCodeLine Token s
CodeLine = Bool
True
isCodeLine Token s
_ = Bool
False
isBlockOpen :: Token s -> Bool
isBlockOpen :: Token s -> Bool
isBlockOpen (BlockOpen Maybe s
_ Language
_ Format
_) = Bool
True
isBlockOpen Token s
_ = Bool
False
isBlockClose :: Token s -> Bool
isBlockClose :: Token s -> Bool
isBlockClose Token s
BlockClose = Bool
True
isBlockClose Token s
_ = Bool
False
unsafeContent :: Token a -> a
unsafeContent :: Token a -> a
unsafeContent = Maybe a -> a
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe a -> a) -> (Token a -> Maybe a) -> Token a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Token a -> Maybe a
forall a. Token a -> Maybe a
contentOf
contentOf :: Token a -> Maybe a
contentOf :: Token a -> Maybe a
contentOf (Statement a
c) = a -> Maybe a
forall a. a -> Maybe a
Just a
c
contentOf (PropLine a
c) = a -> Maybe a
forall a. a -> Maybe a
Just a
c
contentOf (TextLine a
c) = a -> Maybe a
forall a. a -> Maybe a
Just a
c
contentOf Token a
_ = Maybe a
forall a. Maybe a
Nothing
tokensFrom :: String -> [Loc (Token String)]
tokensFrom :: String -> [Loc (Token String)]
tokensFrom = [String] -> [Loc (Token String)]
tokens ([String] -> [Loc (Token String)])
-> (String -> [String]) -> String -> [Loc (Token String)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
lines (String -> [String]) -> ShowS -> String -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> ShowS
forall a. (a -> Bool) -> [a] -> [a]
filter (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'\r')
tokens :: [String] -> [Loc TokenS]
tokens :: [String] -> [Loc (Token String)]
tokens = ((Int, [Token String]) -> [Loc (Token String)])
-> [(Int, [Token String])] -> [Loc (Token String)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\(Int
l, [Token String]
vs) -> (Token String -> Loc (Token String))
-> [Token String] -> [Loc (Token String)]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> Token String -> Loc (Token String)
forall l a. l -> a -> Located l a
Located Int
l) [Token String]
vs) ([(Int, [Token String])] -> [Loc (Token String)])
-> ([String] -> [(Int, [Token String])])
-> [String]
-> [Loc (Token String)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Int] -> [[Token String]] -> [(Int, [Token String])]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0 ..] ([[Token String]] -> [(Int, [Token String])])
-> ([String] -> [[Token String]])
-> [String]
-> [(Int, [Token String])]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[Token String]] -> [[Token String]]
forall a. [a] -> [a]
reverse ([[Token String]] -> [[Token String]])
-> ([String] -> [[Token String]]) -> [String] -> [[Token String]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (State, [[Token String]]) -> [[Token String]]
forall a b. (a, b) -> b
snd ((State, [[Token String]]) -> [[Token String]])
-> ([String] -> (State, [[Token String]]))
-> [String]
-> [[Token String]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((State, [[Token String]]) -> String -> (State, [[Token String]]))
-> (State, [[Token String]])
-> [String]
-> (State, [[Token String]])
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (State, [[Token String]]) -> String -> (State, [[Token String]])
next (State
InCode, [])
where
next :: (State, [[Token String]]) -> String -> (State, [[Token String]])
next (State
st, [[Token String]]
tokens) String
ln = case Parser Char (State, [Token String])
-> String -> Either String (State, [Token String])
forall t a. Show t => Parser t a -> [t] -> Either String a
runParser (State -> Parser Char (State, [Token String])
aline State
st) String
ln of
Right (State
st', [Token String]
tokens') -> (State
st', [Token String]
tokens' [Token String] -> [[Token String]] -> [[Token String]]
forall a. a -> [a] -> [a]
: [[Token String]]
tokens)
Left String
err -> String -> (State, [[Token String]])
forall a. HasCallStack => String -> a
error (String -> (State, [[Token String]]))
-> String -> (State, [[Token String]])
forall a b. (a -> b) -> a -> b
$ [String] -> String
unwords [String
"Tokens.next failed to parse", String
ln, String
err]
aline :: State -> TParser
aline :: State -> Parser Char (State, [Token String])
aline State
InCode = Parser Char (State, [Token String])
forall s. Parser Char (State, [Token s])
optionStart Parser Char (State, [Token String])
-> Parser Char (State, [Token String])
-> Parser Char (State, [Token String])
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Char (State, [Token String])
multi Parser Char (State, [Token String])
-> Parser Char (State, [Token String])
-> Parser Char (State, [Token String])
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Char (State, [Token String])
singleOpen Parser Char (State, [Token String])
-> Parser Char (State, [Token String])
-> Parser Char (State, [Token String])
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Char (State, [Token String])
codeLine
aline State
InSingleComment = Parser Char (State, [Token String])
forall s. Parser Char (State, [Token s])
optionStart Parser Char (State, [Token String])
-> Parser Char (State, [Token String])
-> Parser Char (State, [Token String])
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Char (State, [Token String])
multi Parser Char (State, [Token String])
-> Parser Char (State, [Token String])
-> Parser Char (State, [Token String])
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Bool -> Parser Char (State, [Token String])
commentLine Bool
False Parser Char (State, [Token String])
-> Parser Char (State, [Token String])
-> Parser Char (State, [Token String])
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Char (State, [Token String])
codeLine
aline State
InMultiComment = Parser Char (State, [Token String])
multiClose Parser Char (State, [Token String])
-> Parser Char (State, [Token String])
-> Parser Char (State, [Token String])
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Bool -> Parser Char (State, [Token String])
commentLine Bool
True
multi :: TParser
multi :: Parser Char (State, [Token String])
multi = Parser Char (State, [Token String])
multiOpenClose Parser Char (State, [Token String])
-> Parser Char (State, [Token String])
-> Parser Char (State, [Token String])
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Char (State, [Token String])
multiOpen
codeLine :: TParser
codeLine :: Parser Char (State, [Token String])
codeLine = (State
InCode, [Token String
forall s. Token s
CodeLine]) (State, [Token String])
-> Parser Char String -> Parser Char (State, [Token String])
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser Char String
forall t. Parser t [t]
tillEnd
multiOpenClose :: TParser
multiOpenClose :: Parser Char (State, [Token String])
multiOpenClose = (Parser Char ()
multiStart Parser Char ()
-> Parser Char (State, [Token String])
-> Parser Char (State, [Token String])
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser Char (State, [Token String])
multiClose) Parser Char (State, [Token String])
-> (State, [Token String]) -> Parser Char (State, [Token String])
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> (State
InCode, [Token String
forall s. Token s
CodeLine])
multiOpen :: TParser
multiOpen :: Parser Char (State, [Token String])
multiOpen =
( \() (Maybe Language
maybeLanguage, Maybe String
maybeName) Token String
tk ->
(State
InMultiComment, [Maybe String -> Language -> Format -> Token String
forall s. Maybe s -> Language -> Format -> Token s
BlockOpen Maybe String
maybeName (Maybe Language -> Language
defLang Maybe Language
maybeLanguage) Format
MultiLine, Token String
tk])
)
(()
-> (Maybe Language, Maybe String)
-> Token String
-> (State, [Token String]))
-> Parser Char ()
-> Parser
Char
((Maybe Language, Maybe String)
-> Token String -> (State, [Token String]))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Char ()
multiStart
Parser
Char
((Maybe Language, Maybe String)
-> Token String -> (State, [Token String]))
-> Parser Char (Maybe Language, Maybe String)
-> Parser Char (Token String -> (State, [Token String]))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Char (Maybe Language, Maybe String)
languageAndName
Parser Char (Token String -> (State, [Token String]))
-> Parser Char (Token String)
-> Parser Char (State, [Token String])
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Char (Token String)
commentRest
singleOpen :: TParser
singleOpen :: Parser Char (State, [Token String])
singleOpen =
( \() (Maybe Language
maybeLanguage, Maybe String
maybeName) Token String
tk ->
(State
InSingleComment, [Maybe String -> Language -> Format -> Token String
forall s. Maybe s -> Language -> Format -> Token s
BlockOpen Maybe String
maybeName (Maybe Language -> Language
defLang Maybe Language
maybeLanguage) Format
SingleLine, Token String
tk])
)
(()
-> (Maybe Language, Maybe String)
-> Token String
-> (State, [Token String]))
-> Parser Char ()
-> Parser
Char
((Maybe Language, Maybe String)
-> Token String -> (State, [Token String]))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Char ()
singleStart
Parser
Char
((Maybe Language, Maybe String)
-> Token String -> (State, [Token String]))
-> Parser Char (Maybe Language, Maybe String)
-> Parser Char (Token String -> (State, [Token String]))
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Char (Maybe Language, Maybe String)
languageAndName
Parser Char (Token String -> (State, [Token String]))
-> Parser Char (Token String)
-> Parser Char (State, [Token String])
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Char (Token String)
commentRest
commentLine :: Bool -> TParser
Bool
noPrefix =
(\Token String
tk -> (Bool -> State
commentState Bool
noPrefix, [Token String
tk])) (Token String -> (State, [Token String]))
-> Parser Char (Token String)
-> Parser Char (State, [Token String])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Bool -> Parser Char ()
optLineStart Bool
noPrefix Parser Char ()
-> Parser Char (Token String) -> Parser Char (Token String)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Char (Token String)
commentBody)
commentRest :: Parser Char (Token [Char])
= Parser Char Char -> Parser Char String
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many Parser Char Char
space Parser Char String
-> Parser Char (Token String) -> Parser Char (Token String)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Char (Token String)
commentBody
commentBody :: Parser Char (Token [Char])
commentBody :: Parser Char (Token String)
commentBody = Parser Char (Token String)
stmt Parser Char (Token String)
-> Parser Char (Token String) -> Parser Char (Token String)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Char (Token String)
prop Parser Char (Token String)
-> Parser Char (Token String) -> Parser Char (Token String)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Char (Token String)
forall t. Parser t (Token [t])
txt
where
txt :: Parser t (Token [t])
txt = [t] -> Token [t]
forall s. s -> Token s
TextLine ([t] -> Token [t]) -> Parser t [t] -> Parser t (Token [t])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser t [t]
forall t. Parser t [t]
tillEnd
stmt :: Parser Char (Token String)
stmt = String -> Token String
forall s. s -> Token s
Statement (String -> Token String)
-> Parser Char String -> Parser Char (Token String)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (String -> Parser Char String
string String
">>>" Parser Char String -> Parser Char String -> Parser Char String
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Char String
forall t. Parser t [t]
tillEnd)
prop :: Parser Char (Token String)
prop = String -> Token String
forall s. s -> Token s
PropLine (String -> Token String)
-> Parser Char String -> Parser Char (Token String)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (String -> Parser Char String
string String
"prop>" Parser Char String -> Parser Char String -> Parser Char String
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Char String
forall t. Parser t [t]
tillEnd)
optLineStart :: Bool -> Parser Char ()
optLineStart :: Bool -> Parser Char ()
optLineStart Bool
noPrefix
| Bool
noPrefix = () -> Parser Char ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
| Bool
otherwise = Parser Char ()
singleStart
singleStart :: Parser Char ()
singleStart :: Parser Char ()
singleStart = (String -> Parser Char String
string String
"--" Parser Char String
-> Parser Char (Maybe Char) -> Parser Char (Maybe Char)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Char Char -> Parser Char (Maybe Char)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional Parser Char Char
space) Parser Char (Maybe Char) -> () -> Parser Char ()
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> ()
multiStart :: Parser Char ()
multiStart :: Parser Char ()
multiStart = String -> Parser Char String
sstring String
"{-" Parser Char String -> () -> Parser Char ()
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> ()
multiClose :: TParser
multiClose :: Parser Char (State, [Token String])
multiClose = Parser Char Char -> Parser Char String -> Parser Char String
forall (m :: * -> *) a end. MonadPlus m => m a -> m end -> m end
skipManyTill ((Char -> Bool) -> Parser Char Char
forall t. (t -> Bool) -> Parser t t
satisfy (Bool -> Char -> Bool
forall a b. a -> b -> a
const Bool
True)) (String -> Parser Char String
string String
"-}" Parser Char String -> Parser Char String -> Parser Char String
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Char Char -> Parser Char String
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many Parser Char Char
space) Parser Char String
-> Parser Char (State, [Token String])
-> Parser Char (State, [Token String])
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (State, [Token String]) -> Parser Char (State, [Token String])
forall (m :: * -> *) a. Monad m => a -> m a
return (State
InCode, [Token String
forall s. Token s
BlockClose])
optionStart :: Parser Char (State, [Token s])
optionStart :: Parser Char (State, [Token s])
optionStart = (String -> Parser Char String
string String
"{-#" Parser Char String -> Parser Char String -> Parser Char String
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Char String
forall t. Parser t [t]
tillEnd) Parser Char String
-> (State, [Token s]) -> Parser Char (State, [Token s])
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> (State
InCode, [Token s
forall s. Token s
CodeLine])
name :: Parser Char [Char]
name :: Parser Char String
name = (:) (Char -> ShowS) -> Parser Char Char -> Parser Char ShowS
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Char Char
letterChar Parser Char ShowS -> Parser Char String -> Parser Char String
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Char Char -> Parser Char String
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many (Parser Char Char
alphaNumChar Parser Char Char -> Parser Char Char -> Parser Char Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Char -> Parser Char Char
char Char
'_')
sstring :: String -> Parser Char [Char]
sstring :: String -> Parser Char String
sstring String
s = Parser Char Char -> Parser Char String
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many Parser Char Char
space Parser Char String -> Parser Char String -> Parser Char String
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> String -> Parser Char String
string String
s Parser Char String -> Parser Char String -> Parser Char String
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser Char Char -> Parser Char String
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many Parser Char Char
space
languageAndName :: Parser Char (Maybe Language, Maybe String)
languageAndName :: Parser Char (Maybe Language, Maybe String)
languageAndName =
(,) (Maybe Language -> Maybe String -> (Maybe Language, Maybe String))
-> Parser Char (Maybe Language)
-> Parser Char (Maybe String -> (Maybe Language, Maybe String))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Char Language -> Parser Char (Maybe Language)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional ((Char -> Parser Char Char
char Char
'|' Parser Char Char -> Parser Char Char -> Parser Char Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Char -> Parser Char Char
char Char
'^') Parser Char Char -> Parser Char Language -> Parser Char Language
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Language -> Parser Char Language
forall (f :: * -> *) a. Applicative f => a -> f a
pure Language
Haddock)
Parser Char (Maybe String -> (Maybe Language, Maybe String))
-> Parser Char (Maybe String)
-> Parser Char (Maybe Language, Maybe String)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Char String -> Parser Char (Maybe String)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional
(Char -> Parser Char Char
char Char
'$' Parser Char Char -> Parser Char String -> Parser Char String
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe String
"" (Maybe String -> String)
-> Parser Char (Maybe String) -> Parser Char String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Char String -> Parser Char (Maybe String)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional Parser Char String
name))
defLang :: Maybe Language -> Language
defLang :: Maybe Language -> Language
defLang = Language -> Maybe Language -> Language
forall a. a -> Maybe a -> a
fromMaybe Language
Plain