【问题标题】:"Batteries" for Parsec in HaskellHaskell 中 Parsec 的“电池”
【发布时间】:2017-07-24 17:48:37
【问题描述】:

我是 Haskell 的新手,我一直在尝试使用 Parsec 作为练习来编写 JSON 解析器。这大部分进展顺利,我能够用相对较少的代码解析列表和对象,这也是可读的(太棒了!)。但是,对于 JSON,我还需要解析像

这样的原语
  • 整数(可能有符号)
  • 浮点数(可能使用科学记数法,例如“3.4e-8”)
  • 字符串,例如转义引号

我希望找到现成的解析器来处理这些事情,作为 Parsec 的一部分。我得到的最接近的是 Parsec.Tokens 模块(定义integer 和朋友),但是这些解析器需要一个“语言定义”,这似乎超出了我解析像 JSON 这样简单的东西所应该做的——它似乎专为编程语言而设计。

所以我的问题是:

  1. Parsec.Token 中的函数是正确的方法吗?如果有,如何做出合适的语言定义?

  2. 是否在其他地方定义了整数等的“原始”解析器?也许在另一个包里?

  3. 我应该自己编写这些低级解析器吗?我可以看到自己经常重复使用它们...(晦涩的科学数据格式等)

我注意到这个网站上的一个问题说 Megaparsec 包含这些原语 [1],但我想这些不能与 parsec 一起使用。

相关问题:

How do I get Parsec to let me call `read` :: Int?

How to parse an Integer with parsec

【问题讨论】:

  • 你可以只传入空字符串和列表以及总是失败的解析器来处理那些不适用于你的选项(我猜是所有选项)。
  • 如果可以,请使用megaparsec。这是对parsec 的更好的现代重写(实际上是由国王维护的)。

标签: parsing haskell parsec


【解决方案1】:

Parsec.Token 中的函数是正确的方法吗?

是的,他们是。如果您不关心minutiae specified by a language definition(即您不打算使用依赖于它们的解析器,例如identifier or reserved),只需使用emptyDef 作为默认值:

import Text.Parsec
import qualified Text.Parsec.Token as P
import Text.Parsec.Language (emptyDef)

lexer = P.makeTokenParser emptyDef

integer = P.integer lexer

正如您所指出的,这对于您的用例来说显得过于笨拙。值得一提的是,megaparsec(参见Alec's suggestion)提供了一个对应的integer 解析器,没有仪式。 (另一方面是 megaparsec 不会尝试支持例如保留字,但 isn't difficult to implement 在您实际需要的情况下。)

【讨论】:

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