Haskell:Parsec遇到了模式问题

时间:2013-04-30 23:12:29

标签: haskell parsec

供参考,这是我的代码:http://hpaste.org/86949

我正在尝试解析以下表达式:if (a[1].b[2].c.d[999].e[1+1].f > 3) { }。播放的方法是varExpr,它解析变量成员链。

上下文

在我正在解析的语言中,点可以指定访问成员变量。由于成员变量可以是另一个对象,因此可以生成链:a.b.c或基本上(a.b).c。不要认为点是功能组合。

实施

逻辑是这样的:

  • 首先,before <- many vocc收集varname .的所有实例及其可选数组表达式,只留下一个标识符

  • this <- vtrm收集剩余的标识符和数组表达式 - 唯一一个没有点的

问题

我有两个问题:

首先,第一个术语[由于我无法确定的原因]似乎总是要求它被括在括号中以供解析器接受它,即:(a[1]).b[2].c... - 后续术语不需要这样。

其次,many vocc不会停止解析。它总是需要另一个标识符和另一个点,我无法终止表达式以捕获最后一个vtrm

我正在寻找可以帮助我解决问题/头痛的提示或解决方案。感谢。

1 个答案:

答案 0 :(得分:4)

varExpr运行时,会检查下一位输入是否与voccvtrm匹配。

varExpr = do before <- many vocc  -- Zero or more occurrences
             this <- vtrm
             return undefined

问题是,vtrm匹配的任何输入也会与vocc的第一步匹配。运行varExpr时,它会运行vocc,运行vobj,运行vtrm

vocc = vobj <* symbol "."
vobj = choice [try vtrm, try $ parens vtrm]

many vocc失败而没有消耗输入时,vocc的解析结束。当vtrmparens vtrm都失败时会发生这种情况。但是,在many vocc结束后,下一个要运行的解析器是vtrm - 这个解析器肯定会失败!

如果输入中没有找到vocc,您希望"."在不消耗输入的情况下失败。为此,您需要使用try

vocc = try $ vobj <* symbol "."

或者,如果vobjvtrm确实应该是相同的语法,则可以将varExpr定义为vobj `sepBy1` symbol "."