我有一个使用lemon解析器生成器构建的SQL语法。解析命令的正常入口点是一个语句(如SELECT ...
),因此该语句是语法中的%start
非终结符。到目前为止,一切正常。
现在我想做一个"部分解析",例如,只解析一个表达式,或WHERE
子句。基本上,这意味着我希望%start
非终端在运行时更改。我在文档中找不到任何相关信息。这在柠檬中可行吗?
如果没有,我正在考虑做一些事情,比如让解析在我自定义的起点失败。这感觉有点像黑客,有更干净的方法吗?
一个标准的LALR解析器生成器(比如LEMON)不会(实际上不能)让你做你想做的。
要做到这一点,你必须创建一个开始状态,它愿意接受你感兴趣的任何非终结符(例如,SELECT_clause, WHERE_clause)。要做到这一点,可以有效地更改以下语法:
GOAL = TOP ;
RULEn = ... ;
SG = .... ;
,其中SG是次要目标(例如;(WHERE子句)到
GOAL = TOP | SG ;
RULEn = ... ;
SG = ... ;
这样做的坏消息是,通常违反了LALR状态生成可接受的条件(例如,前瞻集不再区分缩减),并且现在您的解析器生成器不再工作。
使用GLR解析器生成器就容易多了,它可以处理任何与上下文无关的语法。(事实上,对于DMS Software Reengineering Toolkit中根据非终结符定义的模式,我们正是这样做的。事实上,我们做得有点过头了,把每个非终结符都放在目标生成中。虽然这听起来很疯狂,但它允许我们从语言中识别任何格式良好的(非终结符)短语