我有一个使用柠檬解析器生成器构建的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 软件再工程工具包的非终结符定义的模式,我们确实这样做了。事实上,我们有点过分,将每个非终结符都放在目标生产中。虽然这听起来很疯狂,但它让我们能够识别语言中的任何格式良好的(非终结)短语)。