供参考,这是我的代码: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
。
我正在寻找可以帮助我解决问题/头痛的提示或解决方案。感谢。
答案 0 :(得分:4)
当varExpr
运行时,会检查下一位输入是否与vocc
或vtrm
匹配。
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
的解析结束。当vtrm
和parens vtrm
都失败时会发生这种情况。但是,在many vocc
结束后,下一个要运行的解析器是vtrm
- 这个解析器肯定会失败!
如果输入中没有找到vocc
,您希望"."
在不消耗输入的情况下失败。为此,您需要使用try
。
vocc = try $ vobj <* symbol "."
或者,如果vobj
和vtrm
确实应该是相同的语法,则可以将varExpr定义为vobj `sepBy1` symbol "."
。