@@ -13,8 +13,8 @@
14-----------------------------------------------------------------------------
14-----------------------------------------------------------------------------
16−module Parser (
16+module Parser
17− parseCommand
17+ ( parseCommand
20import Prelude hiding (lex)
20import Prelude hiding (lex)
@@ -38,53 +38,88 @@ parseCommand :: String -> Either String C.Command
38parseCommand cmdString =
38parseCommand cmdString =
39 case cmdString of
39 case cmdString of
40 (':' : cmd) -> parseDirective cmd
40 (':' : cmd) -> parseDirective cmd
41− _ -> parseRest (psciImport <|> psciLet <|> psciExpression) cmdString
41+ _ -> parseRest psciCommand cmdString
43+parseRest :: P.TokenParser a -> String -> Either String a
44+parseRest p s = either (Left . show) Right $ do
46+ P.runTokenParser "" (p <* eof) ts
48+psciCommand :: P.TokenParser C.Command
49+psciCommand = choice (map try parsers)
43− parseRest :: P.TokenParser a -> String -> Either String a
51+ parsers =
44− parseRest p s = either (Left . show) Right $ do
52+ [ psciLet
45− ts <- P.lex "" s
53+ , psciImport
46− P.runTokenParser "" (p <* eof) ts
54+ , psciOtherDeclaration
48− trim :: String -> String
58+trim :: String -> String
49− trim = trimEnd . trimStart
59+trim = trimEnd . trimStart
51− trimStart :: String -> String
61+trimStart :: String -> String
52− trimStart = dropWhile isSpace
62+trimStart = dropWhile isSpace
54− trimEnd :: String -> String
64+trimEnd :: String -> String
55− trimEnd = reverse . trimStart . reverse
65+trimEnd = reverse . trimStart . reverse
57− parseDirective :: String -> Either String C.Command
67+parseDirective :: String -> Either String C.Command
58− parseDirective cmd =
68+parseDirective cmd =
59− case D.parseDirective dstr of
69+ case D.parseDirective dstr of
60− Just D.Help -> return C.Help
70+ Just D.Help -> return C.Help
61− Just D.Quit -> return C.Quit
71+ Just D.Quit -> return C.Quit
62− Just D.Reset -> return C.Reset
72+ Just D.Reset -> return C.Reset
63− Just D.Browse -> C.Browse <$> parseRest P.moduleName arg
73+ Just D.Browse -> C.Browse <$> parseRest P.moduleName arg
64− Just D.Load -> return $ C.LoadFile (trim arg)
74+ Just D.Load -> return $ C.LoadFile (trim arg)
65− Just D.Show -> return $ C.Show (trim arg)
75+ Just D.Show -> return $ C.Show (trim arg)
66− Just D.Type -> C.TypeOf <$> parseRest P.parseValue arg
76+ Just D.Type -> C.TypeOf <$> parseRest P.parseValue arg
67− Just D.Kind -> C.KindOf <$> parseRest P.parseType arg
77+ Just D.Kind -> C.KindOf <$> parseRest P.parseType arg
68− Nothing -> Left $ "Unrecognized command. Type :? for help."
78+ Nothing -> Left $ "Unrecognized command. Type :? for help."
69− where (dstr, arg) = break isSpace cmd
79+ where (dstr, arg) = break isSpace cmd
72− -- Parses expressions entered at the PSCI repl.
82+-- Parses expressions entered at the PSCI repl.
74− psciExpression :: P.TokenParser C.Command
84+psciExpression :: P.TokenParser C.Command
75− psciExpression = C.Expression <$> P.parseValue
85+psciExpression = C.Expression <$> P.parseValue
78− -- PSCI version of @let@.
88+-- PSCI version of @let@.
79− -- This is essentially let from do-notation.
89+-- This is essentially let from do-notation.
80− -- However, since we don't support the @Eff@ monad,
90+-- However, since we don't support the @Eff@ monad,
81− -- we actually want the normal @let@.
91+-- we actually want the normal @let@.
83− psciLet :: P.TokenParser C.Command
93+psciLet :: P.TokenParser C.Command
84− psciLet = C.Let <$> (P.reserved "let" *> P.indented *> manyDecls)
94+psciLet = C.Decls <$> (P.reserved "let" *> P.indented *> manyDecls)
86− manyDecls :: P.TokenParser [P.Declaration]
96+ manyDecls :: P.TokenParser [P.Declaration]
87− manyDecls = C.mark (many1 (C.same *> P.parseDeclaration))
97+ manyDecls = C.mark (many1 (C.same *> P.parseLocalDeclaration))
99+-- | Imports must be handled separately from other declarations, so that
100+-- :show import works, for example.
89− psciImport :: P.TokenParser C.Command
101+psciImport :: P.TokenParser C.Command
90− psciImport = C.Import <$> P.parseImportDeclaration'
102+psciImport = C.Import <$> P.parseImportDeclaration'
104+-- | Any other declaration that we don't need a 'special case' parser for
105+-- (like let or import declarations).
106+psciOtherDeclaration :: P.TokenParser C.Command
107+psciOtherDeclaration = C.Decls . (:[]) <$> do
108+ decl <- discardPositionInfo <$> P.parseDeclaration
111+ else fail "this kind of declaration is not supported in psci"
113+discardPositionInfo :: P.Declaration -> P.Declaration
114+discardPositionInfo (P.PositionedDeclaration _ _ d) = d
115+discardPositionInfo d = d
117+acceptable :: P.Declaration -> Bool
118+acceptable (P.DataDeclaration _ _ _ _) = True
119+acceptable (P.TypeSynonymDeclaration _ _ _) = True
120+acceptable (P.ExternDeclaration _ _ _ _) = True
121+acceptable (P.ExternDataDeclaration _ _) = True
122+acceptable (P.ExternInstanceDeclaration _ _ _ _) = True
123+acceptable (P.TypeClassDeclaration _ _ _ _) = True
124+acceptable (P.TypeInstanceDeclaration _ _ _ _ _) = True