13

所有的解析器都Text.Parsec.Token礼貌地lexeme在令牌后使用空格。对我来说不幸的是,空格包含新行,我想将其用作表达式终止符。有没有办法说服lexeme离开新线路?

4

4 回答 4

6

不它不是。这是相关的代码。

来自Text.Parsec.Token

lexeme p
    = do{ x <- p; whiteSpace; return x  }


--whiteSpace
whiteSpace
    | noLine && noMulti  = skipMany (simpleSpace <?> "")
    | noLine             = skipMany (simpleSpace <|> multiLineComment <?> "")
    | noMulti            = skipMany (simpleSpace <|> oneLineComment <?> "")
    | otherwise          = skipMany (simpleSpace <|> oneLineComment <|> multiLineComment <?> "")
    where
      noLine  = null (commentLine languageDef)
      noMulti = null (commentStart languageDef)

人们会注意到,在 where 子句中whitespace,唯一的选项是处理注释。该lexeme函数使用whitespace,并且在parsec.token.


2015 年 9 月 28 日更新

对我来说最终的解决方案是使用适当的词法分析器(alex)。Parsec 作为一个解析库做得非常好,它的设计值得称赞,它可以进行词法分析,但是对于除了小而简单的项目之外的所有项目,它很快就会变得笨拙。我现在使用 alex 创建一组线性标记,然后 Parsec 将它们转换为 AST。

于 2011-04-17T15:53:16.253 回答
3

如果换行符是您的表达式终止符,那么在每个换行符处拆分输入并自行解析每一行可能是有意义的。

于 2011-04-15T07:14:32.163 回答
2

好吧,不是所有的解析器都在Text.Parsec.Token使用lexeme,尽管它们都应该。最糟糕的是,没有记录其中哪些消耗空白,哪些不消耗。中的一些解析器Text.Parsec.Token 确实在词位之后消耗了空格,而其中一些则没有。其中一些也消耗前导空格。如果您想完全控制情况,您应该阅读 GitHub 问题跟踪器上的现有问题。

尤其:

  • decimal, hexadecimal, 和octal解析器消耗尾随空格,请参阅 源代码这个问题

  • integer也消耗前导空格,请参阅 此问题

  • 他们中的其他人可能会消耗尾随空格并因此换行,但这很难确定,因为 Parsec 的代码特别多毛(恕我直言)并且该项目没有测试套件(除了 3 个测试检查已经修复的错误没有出现再次,但是这还不足以防止回归,并且源代码中的每一次更改都可能 在 Parsec 的下一个版本中破坏您的代码。)

有各种建议如何使其可配置(什么应该被视为空白),由于某种原因,它们都没有被合并或评论。

但真正的问题在于设计Text.Parsec.Token,它将用户锁定在由makeTokenParser. 这种设计特别不灵活。在很多情况下,只有一种解决方案是复制整个模块并根据需要对其进行编辑。

但是,如果您想要现代且一致的 Parsec,则可以选择切换到 Megaparsec,其中不存在这个(和许多其他)问题。


披露:我是 Megaparsec 的作者之一。

于 2015-09-25T16:27:39.083 回答
1

尽管关于不可能的其他答案是正确的,但我想指出,字符解析器没有使用词素解析器。
我使用 parsec 来分析一些 html mustache 模板。空格在该分析中很重要。我所做的只是用Text.Parsec.Char.string.
由于我对标签之间的空格而不是它们内部的空格感兴趣,我仍然可以使用保留的运算符来解析“<”和“{{”等,因为词位解析器只使用尾随空格。

于 2012-12-06T17:24:15.730 回答