在Parsec,有没有办法防止lexeme消费换行?

时间:2011-04-15 03:39:27

标签: haskell parsec

Text.Parsec.Token中的所有解析器礼貌地使用lexeme在令牌后吃空格。对我来说不幸的是,空格包括新行,我想将它用作表达式终止符。有没有办法说服lexeme留下新的一行?

4 个答案:

答案 0 :(得分: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)

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


2015年9月28日更新

对我来说,最终的解决方案是使用合适的词法分析器(alex)。 Parsec作为一个解析库做得很好,设计可以归结为它可以被修改为词法分析,但是除了小而简单的项目之外,它很快就会变得难以处理。我现在使用alex来创建一组线性标记,然后Parsec将它们变成AST。

答案 1 :(得分:3)

如果换行符是你的表达式终结符,也许在每个换行符处拆分输入并自行解析每一行是有意义的。

答案 2 :(得分:2)

嗯,并非Text.Parsec.Token中的所有解析器都使用lexeme,尽管所有解析器都使用Text.Parsec.Token 他们应该。最糟糕的是,没有记录哪些消耗白色 空间,其中哪些不。 decimal中的一些解析器 在lexeme之后消耗空白,其中一些没有。他们中有一些 消耗领先的空白。您应该阅读现有的问题 如果您想完全控制情况,请使用GitHub问题跟踪器。

特别是:

  • hexadecimaloctalinteger解析器不会消耗尾随 白色空间,见 the source, 和this issue;

  • Text.Parsec.Token也消耗领先的空白,请参阅 this issue;

  • 其余的可能消耗尾随空格,因此换行, 然而,这很难确定,因为Parsec的代码是 特别毛茸茸(恕我直言),该项目没有测试套件(3除外) 但是,检查已经修复的错误的测试不再出现 它不足以阻止回归和源的每一个变化 break your code in next release of Parsec)。

如何使其可配置(应该是什么,有各种各样的命题 被认为是空白区域),由于某些原因,它们都没有被合并或评论。

但真正的问题在于makeTokenParser的设计,它会锁定 用户转换为 else { Response.Redirect("AdministratorPage.aspx", true); } 构建的解决方案。这种设计尤其如此 不灵活。在许多情况下,只有一个解决方案是复制 整个模块并根据需要进行编辑。

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

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

答案 3 :(得分:1)

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