2017-05-26 31 views
0

我在解析簡單的字符串秒差距解析字符串'sepBy`底線

的情況下,面臨着 parsec奇怪的行爲

琴絃的例子是:

1 C1   1.1650  2.7470 -0.1840 ca   1 MOL  0.408200 
    2 N1   -0.0550  2.1750 -0.0380 nb   1 MOL  -0.665000 
    3 C2   -0.2180  0.8450  0.1920 ca   1 MOL  0.450600 
    4 C3   -1.6310  0.3330  0.3310 c3   1 MOL  -0.140700 

我解析器是

atom = do 
    str <- optional spaces *> (many1 $ (letter <|> digit <|> oneOf "-+.")) `sepBy` spaces 

    let id = read $ head str :: Int 
    let charge = (read.head.reverse) str :: Double  
    return (id,(str !! 1),charge) 

records = atom `sepEndBy1` newline 

我需要使用​​解析器解析每個字符串。如果我只使用原子分析器來處理它的工作。

但是,如果嘗試使用records解析器,它看起來像第一個原子解析器吃整個字符串。所以我有(1,C1,-0.140700)而不是陣列[(1,C1,-0.408200),(2,N1,0.665000)]

P.S.在這種情況下,我根本無法理解parsec如何遍歷\n符號。例如,如果我們有

onlyForTest = (many1 $ (letter <|> digit <|> oneOf "-+.")) `sepBy` spaces 

和測試這樣的例子:

*Main> parseTest onlyForTest "bla bl\na bla" 

輸出:

["bla","bl","a","bla"] 

\n符號是不是在sepBy一個分隔符!

+0

我的問題是'空格'不僅接受空格字符而且接受制表符,換行符等。這就是爲什麼'atom'接受所有字符串。 – freestyle

+0

是的,它看起來像是由'isSapace'函數設計的空間' –

+1

,它是這樣做的。 – freestyle

回答

0

正如@freestyle說,spaces使用Data.Char.isSpace,以確定是否一個字符應消耗,並且同時包括\n\r

使用oneOf " \t"而不是spacesendOfLine而不是newline。哦,optionaloptional spaces中是無關的,因爲spaces消耗零個或多個個字符。