1 module Language.Haskell.LSP.Test.Script where
3 import Control.Applicative ( (<|>), some )
6 import qualified Data.Text as T
7 import qualified Data.HashMap.Lazy as HM
9 import Text.ParserCombinators.ReadP
11 data Block = Block String Wait [Action]
14 data Wait = WaitPred [Predicate]
18 data Predicate = Predicate Accessor Comparison
21 data Accessor = AccessorTerm String
22 | Accessor String Accessor
25 data Comparison = EqualsNumber Scientific
27 | ContainsString String
30 data Action = OpenDoc FilePath String
31 | Request String Method MessageParam
32 | Reply Method MessageParam
33 | Notify Method MessageParam
38 data MessageParam = ParamObject (HM.HashMap T.Text MessageParam)
43 -- | Parse a string literal like "foo".
44 strLiteral :: ReadP String
45 strLiteral = between (char '"') (char '"') (many (satisfy (/= '"')))
47 -- | Parse mandatory whitespace, including newlines
49 space = void $ some (satisfy isSpace)
56 between (char '{') (char '}') $ do
59 actions <- option [] $ do
65 return $ Block name w actions
72 where f = string "any" >> return WaitAny
73 g = WaitPred <$> some predicate
75 predicate :: ReadP Predicate
78 Predicate x <$> comparison
80 accessor :: ReadP Accessor
82 x:xs <- reverse <$> sepBy1 property (char '.')
83 return $ foldl (flip Accessor) (AccessorTerm x) xs
84 where property = many (satisfy isAlphaNum)
86 comparison :: ReadP Comparison
89 operator <- string "==" <|> string "is in"
91 choice [eqString, eqNumber]
92 -- todo: contains string
93 where eqString = EqualsString <$> strLiteral
94 eqNumber = EqualsNumber . read <$> some (satisfy isNumber)
96 action :: ReadP Action
100 , sendAction "reply" Reply
101 , sendAction "notify" Notify
106 identifier <- manyTill (satisfy isAlphaNum) (skipSpaces >> char ':')
108 sendAction "request" (Request identifier)
110 openAction :: ReadP Action
117 OpenDoc fp <$> strLiteral
119 sendAction :: String -> (String -> MessageParam -> Action) -> ReadP Action
120 sendAction keyword con = do
126 con method <$> messageParam
128 messageParam :: ReadP MessageParam
129 messageParam = choice [uriParam, stringParam, objParam]
139 stringParam = ParamString . T.pack <$> strLiteral
142 props <- between (char '{') (char '}') (some parseProp)
143 return (ParamObject (HM.fromList props))
147 name <- many (satisfy (\x -> (x /= ':') && isAlphaNum x))
150 param <- messageParam
152 return (T.pack name, param)
154 parseScript :: String -> [Block]
156 case readP_to_S parser str of
157 [] -> error "Couldn't parse"