git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Consolidate all parsing in psci into one parsec parser
commitaea20d4f78ac3e1f46f3d690e68182a2e602cc28 authorPhil Freeman <paf31@cantab.net> dateFri 21 Feb 2014, 16:35 (13 years ago) parent39c8913
3 files changed+42−95
psci/Commands.hs+5−7 psci/Main.hs+13−20 psci/Parser.hs+24−68
psci/Commands.hs+5−7
@@ -17,8 +17,6 @@ module Commands where
1717
1818import Language.PureScript
1919
20−import Text.Parsec
21−
2220-- |
2321-- Valid Meta-commands for PSCI
2422--
@@ -30,7 +28,7 @@ data Command
3028 -- |
3129 -- A purescript expression
3230 --
33− | Expression String
31+ | Expression Value
3432 -- |
3533 -- Show the help command
3634 --
@@ -52,13 +50,13 @@ data Command
5250 --
5351 | Reload
5452 -- |
55− -- Find the type of an expression
53+ -- Binds a value to a name
5654 --
57− | TypeOf String
55+ | Let (Value -> Value)
5856 -- |
59− -- An attempt at a meta command that wasn't recognized.
57+ -- Find the type of an expression
6058 --
61− | Unknown ParseError
59+ | TypeOf Value
6260
6361-- |
6462-- The help menu.
psci/Main.hs+13−20
@@ -38,7 +38,7 @@ import System.Environment.XDG.BaseDir
3838import System.FilePath ((</>), isPathSeparator)
3939import System.Process
4040
41−import Text.Parsec (choice)
41+import Text.Parsec (ParseError)
4242
4343import qualified Data.Map as M
4444import qualified Language.PureScript as P
@@ -118,7 +118,7 @@ getPreludeFilename = Paths.getDataFileName "prelude/prelude.purs"
118118-- Loads a file for use with imports.
119119--
120120loadModule :: FilePath -> IO (Either String [P.Module])
121−loadModule = fmap (either (Left . show) Right . parseModules) . U.readFile
121+loadModule filename = either (Left . show) Right . P.runIndentParser filename P.parseModules <$> U.readFile filename
122122
123123-- |
124124-- Expands tilde in path.
@@ -241,16 +241,13 @@ handleTypeOf value (PSCI imports loadedModules lets) = do
241241-- |
242242-- Parses the input and returns either a Metacommand or an expression.
243243--
244−getCommand :: InputT IO Command
244+getCommand :: InputT IO (Either ParseError (Maybe Command))
245245getCommand = do
246246 firstLine <- getInputLine "> "
247247 case firstLine of
248− Nothing -> return Empty
249− Just line -> case parseCommands line of
250− Left err -> return $ Unknown err
251− Right c -> case c of
252− Expression expr -> Expression <$> go [expr]
253− _ -> lift $ return c
248+ Nothing -> return (Right Nothing)
249+ Just s@ (':' : _) -> return . either Left (Right . Just) $ parseCommand s -- The start of a command
250+ Just s -> either Left (Right . Just) . parseCommand <$> go [s]
254251 where
255252 go :: [String] -> InputT IO String
256253 go ls = maybe (return . unlines $ reverse ls) (go . (:ls)) =<< getInputLine " "
@@ -260,11 +257,8 @@ getCommand = do
260257--
261258handleCommand :: Command -> StateT PSCI (InputT IO) ()
262259handleCommand Empty = return ()
263−handleCommand (Expression ls) =
264− case psciParser (choice [Left <$> psciLet, Right <$> psciExpression]) ls of
265− Left err -> inputTToState $ outputStrLn (show err)
266− Right (Left l) -> modify (updateLets l)
267− Right (Right decl) -> get >>= inputTToState . handleDeclaration decl
260+handleCommand (Expression val) = get >>= inputTToState . handleDeclaration val
261+handleCommand (Let l) = modify (updateLets l)
268262handleCommand Help = inputTToState $ outputStrLn helpMessage
269263handleCommand (Import moduleName) = modify (updateImports moduleName)
270264handleCommand (LoadFile filePath) = do
@@ -277,10 +271,7 @@ handleCommand (LoadFile filePath) = do
277271handleCommand Reload = do
278272 (Right prelude) <- ioToState $ loadModule =<< getPreludeFilename
279273 put (PSCI defaultImports prelude [])
280−handleCommand (TypeOf expr) =
281− case parseExpression expr of
282− Left err -> inputTToState $ outputStrLn (show err)
283− Right expr' -> get >>= inputTToState . handleTypeOf expr'
274+handleCommand (TypeOf val) = get >>= inputTToState . handleTypeOf val
284275handleCommand _ = outputTStrLn "Unknown command"
285276
286277-- Command helpers
@@ -314,5 +305,7 @@ main = do
314305 go = do
315306 c <- inputTToState getCommand
316307 case c of
317− Quit -> outputTStrLn quitMessage
318− _ -> handleCommand c >> go
308+ Left err -> outputTStrLn (show err) >> go
309+ Right Nothing -> go
310+ Right (Just Quit) -> outputTStrLn quitMessage
311+ Right (Just c') -> handleCommand c' >> go
psci/Parser.hs+24−68
@@ -13,124 +13,80 @@
1313--
1414-----------------------------------------------------------------------------
1515
16−module Parser where
16+module Parser (
17+ parseCommand
18+ ) where
1719
1820import Commands
1921
22+import Data.Char (isSpace)
23+
2024import Control.Applicative hiding (many)
2125
2226import Text.Parsec hiding ((<|>))
2327
2428import qualified Language.PureScript as P
2529
26−-- |
27−-- PSCI version of modules
28−--
29−psciModules :: Parsec String P.ParseState [P.Module]
30−psciModules = P.parseModules
31−
3230-- |
3331-- PSCI version of @let@.
3432-- This is essentially let from do-notation.
3533-- However, since we don't support the @Eff@ monad,
3634-- we actually want the normal @let@.
3735--
38−psciLet :: Parsec String P.ParseState (P.Value -> P.Value)
39−psciLet = P.Let <$> (P.reserved "let" *> P.indented *> P.parseBinder)
40− <*> (P.indented *> P.reservedOp "=" *> P.parseValue)
41−
42−-- |
43−-- PSCI version of any other valid expression.
44−--
45−psciExpression :: Parsec String P.ParseState P.Value
46−psciExpression = P.whiteSpace *> P.parseValue <* eof
47−
48−-- |
49−-- Parser for PSCI.
50−-- This is really just a wrapper around 'Language.PureScript.runIndentParser'
51−--
52−psciParser :: Parsec String P.ParseState a -> String -> Either ParseError a
53−psciParser = P.runIndentParser ""
54−
55−-- |
56−-- Parses PSCI modules.
57−--
58−parseModules :: String -> Either ParseError [P.Module]
59−parseModules = psciParser psciModules
60−
61−-- |
62−-- Parses PSCI @let@ bindings.
63−--
64−parseLet :: String -> Either ParseError (P.Value -> P.Value)
65−parseLet = psciParser psciLet
66−
67−-- |
68−-- Parses PSCI @expressions@.
69−--
70−parseExpression :: String -> Either ParseError P.Value
71−parseExpression = psciParser psciExpression
36+psciLet :: Parsec String P.ParseState Command
37+psciLet = Let <$> (P.Let <$> (P.reserved "let" *> P.indented *> P.parseBinder)
38+ <*> (P.indented *> P.reservedOp "=" *> P.parseValue))
7239
7340-- |
7441-- Parses PSCI metacommands or expressions input from the user.
7542--
76−parseCommands :: String -> Either ParseError Command
77−parseCommands = psciParser $ choice (map try availableCommands)
43+parseCommand :: String -> Either ParseError Command
44+parseCommand = P.runIndentParser "" $ choice
45+ [ P.whiteSpace *> char ':' *> (psciHelp <|> psciImport <|> psciLoadFile <|> psciQuit <|> psciReload <|> psciTypeOf)
46+ , try psciLet
47+ , psciExpression
48+ ] <* eof
7849
7950-- |
8051-- Parses expressions entered at the PSCI repl.
8152--
82−psciExpr :: Parsec String P.ParseState Command
83−psciExpr = Expression <$> (lookAhead (try (noneOf ":")) *> many1 anyChar)
53+psciExpression :: Parsec String P.ParseState Command
54+psciExpression = Expression <$> P.parseValue
8455
8556-- |
8657-- Parses 'Commands.Help' command.
8758--
8859psciHelp :: Parsec String P.ParseState Command
89−psciHelp = Help <$ (spaces *> string ":?" *> spaces)
60+psciHelp = Help <$ char '?'
9061
9162-- |
9263-- Parses 'Commands.Import' command.
9364--
9465psciImport :: Parsec String P.ParseState Command
95−psciImport = Import <$> (spaces *> string ":i" *> spaces *> P.moduleName)
66+psciImport = Import <$> (char 'i' *> P.whiteSpace *> P.moduleName)
9667
9768-- |
9869-- Parses 'Commands.LoadFile' command.
9970--
10071psciLoadFile :: Parsec String P.ParseState Command
101−psciLoadFile = LoadFile <$> do
102− spaces
103− string ":m"
104− spaces
105− try (manyTill anyChar space) <|> many1 anyChar
72+psciLoadFile = LoadFile . trimEnd <$> (char 'm' *> P.whiteSpace *> manyTill anyChar eof)
73+ where
74+ trimEnd = reverse . dropWhile isSpace . reverse
10675
10776-- |
10877-- Parses 'Commands.Quit' command.
10978--
11079psciQuit :: Parsec String P.ParseState Command
111−psciQuit = Quit <$ (spaces *> string ":q" *> spaces)
80+psciQuit = Quit <$ char 'q'
11281
11382-- |
11483-- Parses 'Commands.Reload' command.
11584--
11685psciReload :: Parsec String P.ParseState Command
117−psciReload = Reload <$ (spaces *> string ":r" *> spaces)
86+psciReload = Reload <$ char 'r'
11887
11988-- |
12089-- Parses 'Commands.TypeOf' command.
12190--
12291psciTypeOf :: Parsec String P.ParseState Command
123−psciTypeOf = TypeOf <$> (spaces *> string ":t" *> spaces *> many anyChar)
124−
125−-- |
126−-- List of commands that are available from PSCI.
127−--
128−availableCommands :: [Parsec String P.ParseState Command]
129−availableCommands = [ psciExpr
130− , psciHelp
131− , psciImport
132− , psciLoadFile
133− , psciQuit
134− , psciReload
135− , psciTypeOf
136− ]
92+psciTypeOf = TypeOf <$> (char 't' *> P.whiteSpace *> P.parseValue)