2017-05-26 32 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消耗零个或多个个字符。