Parsec解析字符串`sepBy` endline

时间:2017-05-26 10:33:46

标签: haskell parsec

在解析简单字符串时,我遇到了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  

我需要用atom解析器解析每个字符串。如果我只使用原子解析器到它的行。

但是如果尝试使用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中的分隔符!

1 个答案:

答案 0 :(得分:0)

正如@freestyle所说,spaces使用Data.Char.isSpace来确定是否应该使用某个字符,并且包括\n\r

使用oneOf " \t"代替spacesendOfLine代替newline。哦,optional optional spacesspaces无关,因为 @Override public void onViewDragStateChanged(int state) { if (state == 0) { if (settleDestX == contentView.getLeft() && swipeOverListener != null) { swipeOverListener.onSwipeOver(settlePosition); } } } 消耗零个或多个字符。