0

我试图模拟 EBNF 表达式

("declare" "namespace" ";")* ("declare" "variable" ";")*

我已经建立了 yacc(我使用 MPPG)语法,它似乎代表了这一点,但它与我的测试表达式不匹配。

我要匹配的测试用例是

declare variable;

来自词法分析器的令牌流是

KW_Declare
KW_Variable
Separator

语法分析表明存在“Shift/Reduce 冲突,KW_Declare 上的状态 6”。我试图用“%left PrologHeaderList PrologBodyList”解决这个问题,但两种解决方案都不起作用。

Program                     : Prolog;
Prolog                      : PrologHeaderList PrologBodyList;

PrologHeaderList            : /*EMPTY*/
                            | PrologHeaderList PrologHeader;
PrologHeader                : KW_Declare KW_Namespace Separator;

PrologBodyList              : /*EMPTY*/
                            | PrologBodyList PrologBody;
PrologBody                  : KW_Declare KW_Variable Separator;

KW_Declare KW_Namespace KW_Variable 分隔符都是具有值“declare”、“naemsapce”、“variable”、“;”的标记。

4

2 回答 2

3

我已经很久没有使用任何类似 yacc 的东西了,但这里有一些可能会或可能不会有帮助的建议。

在这种情况下,您似乎需要一个 2 令牌前瞻。解析器到达最后一个PrologHeader,它必须决定下一个构造是PrologHeader还是PrologBody,它无法从 KW_Declare 中分辨出来。如果在这种情况下有增加前瞻的指令,它可能会解决问题。

您还可以在您的操作中引入上下文:与其定义PrologHeaderListPrologBodyList,不如定义PrologRuleList并让操作在标题出现在正文之后时引发错误。丑陋,但有时你必须这样做:在语法中看起来很简单的东西在生成的解析器中可能并不简单。

一种骇人听闻的方法可能是组合标记:而不是KW_DeclareKW_Variable,让您的词法分析器识别空间并使用KW_Declare_Variable。由于两者都是关键字,因此您不会遇到命名空间冲突问题。

于 2009-06-04T11:57:37.590 回答
0

顶部的语法是常规的,因此 IIRC 您可以将其绘制为 DFA(或 NDA 并将其转换为 DFA),然后将 DFA 转换为语法。有一段时间了,所以我将把这项工作作为练习留给读者。

于 2009-06-04T16:48:49.440 回答