【问题标题】:Make Parsec function fail instead of expecting more input使 Parsec 函数失败而不是期望更多输入
【发布时间】:2014-10-13 08:34:23
【问题描述】:

我正在使用 Parsec 解析一些表达式(有关更多上下文,请参阅 this question),我的代码中最相关的部分是:

statement :: Parser Stmt
statement = assignStmt <|> simpleStmt

assignStmt :: Parser Stmt
assignStmt =
    do var  <- identifier
       reservedOp "="
       expr <- expression
       return $ Assign var expr

simpleStmt :: Parser Stmt
simpleStmt =
    do expr <- expression
       return $ Simple expr

在行动:

boobla> foo = 100 + ~100
167
boobla>
解析器错误:(第 1 行,第 4 列):
输入意外结束
期待字母或数字或“=”

第二个表达式应该计算为167,值为foo

我认为Parsec尝试提取令牌reservedOp "="时应该失败,因为字符串中没有这样的令牌,然后尝试第二个函数simpleStmt并成功。但它的工作方式不同:它需要更多的输入并且只是抛出这个异常。

如果字符串(或当前行)中没有更多字符,我应该使用什么来使assignStmt 失败。 foo = 10 应该用assignStmt 解析,foo 应该用simpleStmt 解析。

【问题讨论】:

  • 我想你需要说try assignStmt &lt;|&gt; simpleStmt。查找try 的文档。
  • @MathematicalOrchid,它有效。请将其作为答案发布,并简要说明正在发生的事情。如果您不想浪费时间,请说 - 我会将其发布为社区 wiki :-)

标签: haskell parsec


【解决方案1】:

您缺少try 函数。

默认情况下,&lt;|&gt; 运算符会尝试左侧解析器,如果失败没有消耗任何字符,它将尝试右侧解析器。

但是,如果 - 就像你的情况一样 - 解析器在消耗了一些字符之后 失败,并且正确的解析器从未尝试过。请注意,这通常是您想要的行为;如果你有类似的东西

parseForLoop <|> parseWhileLoop

如果输入类似于“for break”,那么这不是一个有效的 for 循环,尝试将其解析为 while 循环是没有意义的,因为这肯定也会失败。

try 组合器改变了这种行为。具体来说,它使失败的解析器看起来没有消耗任何输入。 (这有空间损失;输入可能会被丢弃,但 try 让它挂起。)

【讨论】:

    猜你喜欢
    • 2017-03-26
    • 2020-06-26
    • 1970-01-01
    • 2020-10-21
    • 2014-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多