Parsing 解决yacc/ocamlyacc中的reduce/reduce冲突
我试图在ocamlyacc中解析一个语法(与常规的yacc几乎相同),它支持没有运算符的函数应用程序(如Ocaml或Haskell),以及二进制和一元运算符的正常组合。我得到了一个与“-”操作符的reduce/reduce冲突,它可以用于减法和求反。下面是我使用的语法示例:Parsing 解决yacc/ocamlyacc中的reduce/reduce冲突,parsing,ocaml,grammar,yacc,Parsing,Ocaml,Grammar,Yacc,我试图在ocamlyacc中解析一个语法(与常规的yacc几乎相同),它支持没有运算符的函数应用程序(如Ocaml或Haskell),以及二进制和一元运算符的正常组合。我得到了一个与“-”操作符的reduce/reduce冲突,它可以用于减法和求反。下面是我使用的语法示例: %token <int> INT %token <string> ID %token MINUS %start expr %type <expr> expr %nonassoc INT
%token <int> INT
%token <string> ID
%token MINUS
%start expr
%type <expr> expr
%nonassoc INT ID
%left MINUS
%left APPLY
%%
expr: INT
{ ExprInt $1 }
| ID
{ ExprId $1 }
| expr MINUS expr
{ ExprSub($1, $3) }
| MINUS expr
{ ExprNeg $2 }
| expr expr %prec APPLY
{ ExprApply($1, $2) };
%token INT
%令牌ID
%代币负号
%启动表达式
%类型表达式
%非对称整数ID
%左减
%左应用
%%
表达式:INT
{ExprInt$1}
|身份证
{ExprId$1}
|expr减去expr
{ExprSub($1,$3)}
|负表达式
{解释$2}
|expr expr%prec应用
{ExprApply($1,$2)};
问题是,当您得到一个像“a-b”这样的表达式时,解析器不知道应该将其缩减为“a(-b)”(b的求反,后跟application)还是“a-b”(减法)。减法是正确的。如何解决冲突以支持该规则?不幸的是,我能想出的唯一答案意味着增加语法的复杂性
expr
拆分为simple\u expr
和expr\u加前缀
简单表达式
或(带前缀的表达式)
a(b(c))
还是(a(b))(c)
?您还需要在语法中断开应用的表达式
和required(应用的表达式)
我想这样可以,但我不确定:
expr := INT
| parenthesized_expr
| expr MINUS expr
parenthesized_expr := ( expr )
| ( applied_expr )
| ( expr_with_prefix )
applied_expr := expr expr
expr_with_prefix := MINUS expr
这个最简单的答案就是忽略它,让默认的reduce/reduce解析来处理它——减少语法中首先出现的规则。在这种情况下,这意味着减少
expr减去expr
,而不是减去expr
,这正是您想要的。看到a-b
后,您希望将其解析为二进制减号,而不是一元减号,然后再解析为apply。左apply/%prec apply
解决了a-b-c
的歧义——它的左关联性(因此它的(a-b)c)和比其他任何东西都低的优先级。问题在于,优先规则对于表现为reduce/reduce冲突的歧义不起作用。