Bison 如何解决这种歧义语法?

Bison 如何解决这种歧义语法?,bison,yacc,flex-lexer,context-free-grammar,ambiguous-grammar,Bison,Yacc,Flex Lexer,Context Free Grammar,Ambiguous Grammar,我正在创建一个编译器,我正在使用lex和bison 这是我语法的一部分: math : math binop math | VAR | INT | GREEK | "(" math ")" | math comp math | "-" math | math math | "\\sqrt" "{" math "}" ; 我已将上述内容更改为此,但它增加了reduce/reduce错误的数量。它减少了移位/减少错误的数量 m

我正在创建一个编译器,我正在使用lex和bison

这是我语法的一部分:

math
    : math binop math
    | VAR
    | INT
    | GREEK
    | "(" math ")"
    | math comp math
    | "-" math
    | math math
    | "\\sqrt" "{" math "}"
;
我已将上述内容更改为此,但它增加了reduce/reduce错误的数量。它减少了移位/减少错误的数量

math
    : math binop element
    | VAR
    | INT
    | GREEK
    | "(" math ")"
    | math comp element
    | "-" element
    | math element
    | "\\sqrt" "{" element "}"
;


element
    : VAR
    | INT
    | GREEK
    | math
;
有没有办法让它们都减少


谢谢大家!

您在正确的总体方向上迈出了一小步,但也许最好退一步,想想事情是如何开始的,以及这将如何应用于实际的表达式

让我们考虑一个表达式,例如“代码> A+B+C ”。在原始语法中,您有

math binop math
。给定
a+b+c
,它应该把它当作
a
是一个
math
+
是一个
binop
b+c
是另一个
math
,或者它应该把它当作
a+b
是一个数学,
+/code>是一个
binop
,而
c
是一个数学(然后名为
a+b
math
被进一步分解为
a
++
b
)?从稍微不同的角度来看,
a+b+c
应该被解析为
(a+b)+c
还是
a+(b+c)
?在
+
的情况下,它并没有产生任何真正的区别——但对于
-
(一个明显的例子),它确实产生了区别

根据你的第一个语法,任何一个都是可以接受的。事实上,即使是你的第二个语法,任何一个都是可以接受的(但是通过将
元素
从属于
数学
,你已经含蓄地给了yacc一些关于解析它的方法的指导)

这就把我们带到了下一个问题:在什么情况下你(认为你自己)需要使用
math binop math
production吗?如果我们定义一个
math
来解析任意复杂度的表达式,那么
元素能否基本上被限制为一个操作数?如果我们这样做,那么像
a+b+c
这样的每个表达式都必须解析为
math binop operator
,对吗?没有歧义在本例中,
a+b
部分将进一步解析为类似于
操作数binop operand
的内容

这就留下了一个相当基本的问题。我们希望如何处理不同运算符的优先级?例如,至少在通常的情况下,我们希望
*
/
具有比
+
-
更高的优先级

在yacc中有(至少)两种根本不同的处理方法。一种是在语法上,通过定义两种不同类型的子表达式:

add_expr : mul_expr '+' mul_expr
         | mul_expr '-' mul_expr
         ;

mul_expr : factor '*' factor
         | factor '/' factor
         ;
另一种是在指令中设置优先级,如:

%left '+' '-'
%left '*' '/'
%left UNARYMINUS
这让我们可以让语法本身保持不明确,但随后会告诉解析器生成器如何解决不明确的问题

因此,使用这个,我们可以得到如下结果:

expr : expr '+' operand
     | expr '-' operand
     | expr '*' operand
     | expr '/' operand
     ;

operand: VAR
       | INT
       | '(' expr ')'
       | '-' expr %prec UNARYMINUS
       ;
最后一位(
%prec UNARYMINUS
)告诉它将
-
(在本例中)视为具有我们上面为UNARYMINUS指定的优先级(我们定义的最高优先级,因为它是列表中的最后一个)


我没有试着涵盖你的全部语法,但我认为这至少涵盖了你可能需要(或至少想要)的大部分基本转换可能还值得注意的是,shift/reduce冲突通常是无害的。解析器生成器为这种情况提供的解决方案通常可以很好地工作,在某些情况下,这种歧义语法实际上比解决所有歧义的语法更有效,因此,公平的语法的数量不会试图修复所有语法。

这是你的家庭作业吗?告诉我..我可以检查我的课堂笔记,然后减少/减少和移位/减少错误,例如什么?使用规则47(数学)减少规则47(数学)减少规则55(元素)]VAR减少规则47(数学)VAR减少规则55(元素)]加上使用规则47(数学)减少加上[使用规则55(元素)减少]最小使用规则47(数学)减少最小[使用规则55(元素)减少]整数使用规则47(数学)减少整数[使用规则55(元素)减少]…哦,请把它们编辑到你的问题中。尽管难以辨认。谢谢!!这帮了大忙!