Haskell Parsec的indents包提供了一种解析缩进式语言(如 Haskell 和 Python)的方法。它重新定义了Parser类型,那么如何使用 ParsecText.Parsec.Token模块导出的普通Parser类型的令牌解析器函数呢?
背景
- Parsec是一个解析器组合库,不管这意味着什么。
- IndentParser 0.2.1是一个旧包,提供两个模块Text.ParserCombinators.Parsec.IndentParser和Text.ParserCombinators.Parsec.IndentParser.Token
- indents 0.3.3是一个提供单个模块的新包Text.Parsec.Indent
Parsec 带有大量的模块。它们中的大多数导出了一堆有用的解析器(例如newlinefrom Text.Parsec.Char,它解析一个换行符)或解析器组合器(例如  count n pfrom Text.Parsec.Combinator,它运行解析器p,n次)
但是,该模块Text.Parsec.Token希望导出由用户参数化的具有被解析语言特征的函数,例如,该函数将在解析“{”之后和解析“}”之前braces p运行解析器p ,忽略诸如注释之类的东西,其语法取决于您的语言。
实现这一点的方法Text.Parsec.Token是它导出一个makeTokenParser你调用的函数,给它你特定语言的参数(比如评论的样子),它返回一个包含所有函数的记录Text.Parsec.Token,适应你的语言指定的。
当然,在缩进风格的语言中,这些需要进一步调整(也许?这是我不确定的地方——我稍后会解释)所以我注意到(可能已经过时的)IndentParser 包提供了一个模块Text.ParserCombinators.Parsec.IndentParser.Token它看起来是Text.Parsec.Token.
我应该在某些时候提到所有 Parsec 解析器都是一元函数,所以它们对状态做了神奇的事情,以便错误消息可以说明错误出现在源文件的哪一行和哪一列
我的问题
由于几个小原因,在我看来indents包或多或少是 IndentParser 的当前版本,但是它不提供看起来像的模块,Text.ParserCombinators.Parsec.IndentParser.Token它只提供Text.Parsec.Indent,所以我想知道如何获得所有令牌解析器Text.Parsec.Token(比如reserved "something"解析保留关键字“某物”,或者像braces我之前提到的那样)。
在我看来,(新的)Text.Parsec.Indent通过某种单子状态魔法来计算源代码的列位是什么,因此它不需要像whiteSpacefrom那样修改令牌解析器Text.Parsec.Token,这可能就是它的原因不提供替换模块。但是我遇到了类型问题。
你看,没有Text.Parsec.Indent,我所有的解析器都是类型Parser Something,其中 Something 是返回类型,并且Parser是 Text.Parsec.String 中定义的类型别名
type Parser = Parsec String ()
但是我使用自己的定义Text.Parsec.Indent而不是导入Text.Parsec.String
type Parser a = IndentParser String () a
这使我的所有类型的解析器,其中 IndentParser 在 Text.Parsec.Indent 中定义。但是我从中获得的令牌解析器类型错误。IndentParser String () SomethingmakeTokenParserText.Parsec.Token
如果现在这没有多大意义,那是因为我有点迷路了。类型问题在这里讨论了一下。
我得到的错误是我尝试用另一个定义替换Parser上面的一个定义,但是当我尝试使用其中一个令牌解析器时Text.Parsec.Token,我得到了编译错误
Couldn't match expected type `Control.Monad.Trans.State.Lazy.State
                                Text.Parsec.Pos.SourcePos'
            with actual type `Data.Functor.Identity.Identity'
Expected type: P.GenTokenParser
                 String
                 ()
                 (Control.Monad.Trans.State.Lazy.State Text.Parsec.Pos.SourcePos)
  Actual type: P.TokenParser ()
链接
- 秒差距
- IndentParser(旧包)
- indents,提供 Text.Parsec.Indent (新包)
- 使用示例代码讨论解析器类型
- 另一个使用 Text.Parsec.Indent 的例子
遗憾的是,上述示例都没有使用像 Text.Parsec.Token 中那样的令牌解析器。