【问题标题】:Parsec parse string `sepBy` endlineParsec 解析字符串`sepBy` endline
【发布时间】:2017-05-26 10:33:46
【问题描述】:

在解析简单字符串的情况下,我遇到了 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)] 等。

附:在这种情况下,我根本无法理解 parsec 如何遍历带有 \n 符号的行。例如,如果我们有

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

并测试这样的例子:

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

输出:

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

但是\n 符号不是sepBy 中的分隔符!

【问题讨论】:

  • 我的问题是spaces 不仅接受空格字符,还接受制表符、换行符等。这就是atom 接受所有字符串的原因。
  • 是的,看起来是这样的
  • spacesisSapace 函数设计,它就是这样做的。

标签: haskell parsec


【解决方案1】:

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

使用oneOf " \t" 代替spacesendOfLine 代替newline。哦,optionaloptional spaces 中是无关紧要的,因为spaces 消耗零个或多个 个字符。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多