如何使用 BNF 解析器进行 BNF 匹配?

How to do BNF matching with a BNF parser?

我正在使用 https://github.com/sylvainhalle/Bullwinkle/,一个 BNF 解析器。但是它只能识别单个完整句子的 BNF 模式,如何在段落中找到 BNF 匹配项? 我正在尝试识别人类说话中的某些命令。对于 BNF 示例:

<S>: <lightcmd>;
<lightcmd>: <do> <obj> | <do> <a> <obj>;
<do>: turn on | turn off;
<a>: a | an | the;
<obj>: light;

我可以通过说“开灯”来解析正确的命令,但是我无法从“请打开灯”来解析它。

当您尝试根据该语法解析“请打开灯”时,解析器将尝试解析整个话语……因为解析器就是这样做的。但是你想要的是匹配话语的一部分。

现在您可以处理如下内容:

<S>: <words> <lightcmd> <words>;
<lightcmd>: <do> <obj> | <do> <a> <obj>;
<do>: turn on | turn off;
<a>: a | an | the;
<obj>: light;
<words>: <word> | <words> <word>
<word>: // one or more letters 

但你开始陷入歧义问题。

我认为一个更好的主意是尝试解析词流的子序列。所以如果用户说

please turn on a light and make a cup of tea

您尝试以“请”开头进行解析。然后,当失败时,您尝试从“turn”开始。然后当你到达“光”你忽略其余的词。

不知道Bullwinkle能不能这样用。如果没有,请寻找替代的解析器生成器。


但是,还应该注意,像这样简单的语法也可以写成正则表达式,其中单词被视为基本符号。你只需要一个简单的正则表达式引擎来处理这个。 (如果这个语法是典型的,你只需要分组和交替。从头开始实现它应该只需要几个小时的工作。)