This commit is contained in:
Andrew Gibiansky 2014-01-08 15:02:00 -05:00
parent 145ebb5221
commit ce80fe6d86
2 changed files with 42 additions and 62 deletions

View File

@ -541,25 +541,22 @@ parseStringTests = describe "Parser" $ do
Located 4 (Expression "second")])
parseShellTests =
describe "Parsing Shell Commands" $ do
test "A" ["A"]
test ":load A" [":load", "A"]
test ":!l ~/Downloads/MyFile\\ Has\\ Spaces.txt"
[":!l", "~/Downloads/MyFile\\ Has\\ Spaces.txt"]
test ":!l \"~/Downloads/MyFile Has Spaces.txt\" /Another/File\\ WithSpaces.doc"
[":!l", "~/Downloads/MyFile Has Spaces.txt", "/Another/File\\ WithSpaces.doc" ]
where
test string expected =
it ("parses " ++ string ++ " correctly") $
string `shouldParseTo` expected
testParseShell string expected
= do describe "parseShell" $ do
it ("parses " ++ string ++ " correctly: \n\t" ++ show expected) $ do
string `shouldParseTo` expected
where shouldParseTo :: String -> [String] -> Expectation
shouldParseTo xs ys = fun ys (parseShell xs)
where fun ys (Right xs') = xs' `shouldBe` ys
fun ys (Left e) = assertFailure $ "parseShell returned error: \n" ++ show e
parseShellTests = do
testParseShell "A" ["A"]
testParseShell ":load A" [":load", "A"]
testParseShell ":!l ~/Downloads/MyFile\\ Has\\ Spaces.txt"
[":!l", "~/Downloads/MyFile\\ Has\\ Spaces.txt"]
testParseShell ":!l \"~/Downloads/MyFile Has Spaces.txt\" /Another/File\\ WithSpaces.doc"
[":!l", "~/Downloads/MyFile Has Spaces.txt", "/Another/File\\ WithSpaces.doc" ]
shouldParseTo xs ys = fun ys (parseShell xs)
where fun ys (Right xs') = xs' `shouldBe` ys
fun ys (Left e) = assertFailure $ "parseShell returned error: \n" ++ show e
-- Useful HSpec expectations ----

View File

@ -7,70 +7,53 @@ import Prelude hiding (words)
import Text.ParserCombinators.Parsec hiding (manyTill)
import Control.Applicative hiding ((<|>), many, optional)
import Debug.Trace
import Test.Hspec
import Test.Hspec.HUnit
import Test.HUnit (assertBool, assertFailure)
debug = False
trace' x a = if debug then trace x a else a
eol :: Parser Char
eol = do x <- oneOf "\n\r"
return x
<?> "end of line"
eol = oneOf "\n\r" <?> "end of line"
quote :: Parser Char
quote = char '\"'
quote = char '\"'
manyTill :: Parser a -> Parser [a] -> Parser [a]
-- | @manyTill p end@ from hidden @manyTill@ in that it appends the result of @end@
manyTill p end = do scan
where
scan = do{ x <- end; return x }
<|>
do{ x <- p; xs <- scan; return $ x:xs }
manyTill :: Parser a -> Parser [a] -> Parser [a]
manyTill p end = scan
where
scan = end <|> do
x <- p
xs <- scan
return $ x:xs
manyTill1 p end = do x <- p
xs <- manyTill p end
return $ x : xs
unescapedChar :: Parser Char -> Parser String
unescapedChar p = try $ do x <- noneOf ['\\']
lookAhead p
return $ x : []
unescapedChar p = try $ do
x <- noneOf "\\"
lookAhead p
return [x]
quotedString = (trace' "in quotedString")
(do quote <?> "expected starting quote"
manyTill anyChar end <* quote)
<?> "unexpected in quoted String "
where end = unescapedChar quote
quotedString = do
quote <?> "expected starting quote"
(manyTill anyChar (unescapedChar quote) <* quote) <?> "unexpected in quoted String "
unquotedString = (trace' "in unquotedString")
manyTill1 anyChar end
where end = unescapedChar space
<|> do x <- lookAhead eol
return []
unquotedString = manyTill1 anyChar end
where end = unescapedChar space
<|> (lookAhead eol >> return [])
word = quotedString <|> unquotedString <?> "word"
separator :: Parser String
separator = many1 space <?> "separator"
words :: Parser [String ]
-- | Input must terminate in a space character (like a \n)
words = try (eof *> return []) <|>
do x <- word
rest1 <- trace' ("word: " ++ show x) lookAhead (many anyToken)
ss <- trace' ("rest1: " ++ show rest1) separator
rest2 <- trace' ("spaces: " ++ show ss) lookAhead (many anyToken)
xs <- trace' ("rest2: " ++ show rest2) words
return $ x : xs
words :: Parser [String]
words = try (eof *> return []) <|> do
x <- word
rest1 <- lookAhead (many anyToken)
ss <- separator
rest2 <- lookAhead (many anyToken)
xs <- words
return $ x : xs
parseShell :: String -> Either ParseError [String]
parseShell string = parse words "shell" (string ++ "\n")