2

我試圖用optparse-applicative解析列表對。解析單個對可行,但使用many組合子失敗任意解析。optparse-applicative:解析列表對

import   Options.Applicative 

pairParser = (,) <$> argument str (metavar "s1") 
       <*> argument str (metavar "s2") 

testParser p = getParseResult . execParserPure (prefs idm) 
    (info (helper <*> p) fullDesc) 

main = do 
    print $ testParser pairParser ["one", "two"] 
    print $ testParser (many pairParser) [] 
    print $ testParser (many pairParser) ["one", "two"] 
    print $ testParser (many pairParser) ["one", "two", "three", "four"] 

輸出:

Just ("one","two") <- good 
Just []    <- still good 
Nothing    <- does not work 
Nothing    <- also does not work 

任何想法?

回答

1

免責聲明:我沒有做高級optparse-applicative技巧的經驗,所以我可能會失去一些明顯的東西。讀者:請指出,如果是這樣的話。

您的問題是,many所做的是(在手動描述中)將解析器應用於每個輸入塊,在這種情況下塊由單個參數組成,然後收集結果。因此,many pairParserpairParser應用於["one"],然後應用到["two"],並且兩個解析都失敗。既然如此,你可以用一個函數來代替execParserPure,這個函數能夠以合適的方式對參數進行分塊並相應地調整程序的其餘部分,或者(我懷疑是更容易的選擇)放棄pairParser並且只是後處理分析的參數,如:

pairArgs :: [a] -> [(a, a)] 
pairArgs = noLeftover . foldr pairNext (Nothing, []) 
    where 
    noLeftover (m, ps) = case m of 
     Nothing -> ps 
     _  -> [] 
    pairNext x (m, ps) = case m of 
     Just y -> (Nothing, (x, y) : ps) 
     Nothing -> (Just x, ps) 

manyPairsParser :: Parser [(String, String)] 
manyPairsParser = pairArgs <$> many (argument str (metavar "s1 s2..")) 
GHCi> testParser manyPairsParser [] 
Just [] 
GHCi> testParser manyPairsParser ["foo"] 
Just [] 
GHCi> testParser manyPairsParser ["foo","bar"] 
Just [("foo","bar")] 
GHCi> testParser manyPairsParser ["foo","bar","baz"] 
Just [] 
GHCi> testParser manyPairsParser ["foo","bar","baz","quux"] 
Just [("foo","bar"),("baz","quux")] 

(請注意,在演示上面我處理故障通過返回對空列表,並考慮奇數的參數應該導致失敗你」。如果你想要不同的行爲,你需要做一些調整。)

+0

謝謝!我發現'many'的行爲真的讓人困惑,因爲我預計它更像Parsec ......是否存在更多的Parsec風格的命令行解析器? – gedenkt

+0

@gedenkt不是我所知道的。像optparse-applicative這樣的庫是精簡的,專門用來處理更常見的參數和選項傳遞用例。順便說一句,你可能嘗試的另一件事(雖然我沒有測試過)爲你的對指定了一個自定義格式,就像'{item1,item2}'而不是'item1 item2'一樣。我相信[readme](https://hackage.haskell.org/package/optparse-applicative-0.11.0.2)中的FluxCapacitor示例提供了一種使用'optparse-applicative'實現該功能的方法。 – duplode