在野牛,我怎么能specity左结合了一个非终端?(in Bison, how can I spec

2019-10-20 03:46发布

我有以下的野牛语法片段:

binary_op:         BINARY_OP
                    {
                        ...
                    }
                    | '|' %prec BINARY_OP
                    {
                        ...
                    }
;

non_keyword_expr:   non_keyword_expr binary_op non_keyword_expr %prec BINARY_SEND_PREC %dprec 2
                    {
                        ...
                    }
;

| 已经超负荷的意义在我的语法,所以我不能只是从我的词法分析器返回它的令牌BINARY_OP。 这可能是根据上下文不同的令牌。

如果我用这个作为我的输入:

4 OR 5 OR 6

我可以成功地解析它(或识别为词法分析器BINARY_OP令牌)。

但是,如果我的输入是这样的:

4 | 5 | 6

我得到一个模棱两可的语法错误。 (该|没有被确认为左结合)

我怎样才能为左联non_keyword_exprbinary_op?%precbinary_op第二规则语句似乎没有任何效果。

编辑 :这是一个GLR分析器

Answer 1:

答案很简单:你不能。 优先级(和结合)只适用于作品(左侧)和终端(右)。 他们并不适用于非终端。

这不是一个武断的决定; 这是固有的换挡方式野牛手柄分辨率/减少冲突。 在每一个解析步骤,超前记号(终端)必须或者最终被移动,但可能的是,有在终端移动之前,其可以减少生产。 如果不立即进行还原,它永远不会被执行。 的LR(1)语法允许解析器来决定基于当前解析堆栈和超前记号上的降低是否应当执行或超前记号是否应立即移位。 如果这两个动作是可能的,那么语法是说有一个转变/减少冲突,这并不是严格意义LR(1)。

优先级和结合规则用于解决移位/减少冲突。 制作可以具有隐式或显式优先级:显式优先级是由提供%prec声明; 否则,使用在生产的最后一个终端的优先级。 在移位的事件/减少冲突,其可降低生产的优先级进行比较,其可移动先行终端的优先级,并取其具有较大优先获胜。 而已。 的优先级不保留或继承。 事实上,这是不准确的说,优先级进行比较,因为这并不在解析过程中发生的; 解析器具有操作或转换表,该表定义了在特定堆叠配置(“国家”)和超前记号的情况下做的,优先级信息是在解析器代时间用于填充在动作表中的条目否则会产生歧义。

在生产的情况下,

binary_op: '|' %prec BINARY_OP

%prec声明是没用的,因为binary_op必须立即减少; 它不能参与的转变/减少冲突。 移位/减少冲突自带non_keyword_expression生产,标有(不同的) %prec声明,那就是将被用于该生产的声明。

该生产non_keyword_expression没有终端,所以它没有隐含的优先级无论是。 这通常不是你想要的,并采用类似作品的:

binary_op: '|' | "OR" ;

不符合使用优先解决冲突的解析真正兼容。


注1:如果你问一个GLR分析器这并不完全正确。 的GLR解析器可以执行这两个移和降低,因为它(有效地)同时保持数分析器状态。 最终,这些国家的所有,但一个必须被淘汰; 否则,解析是不明确的。 GLR分析器使用优先级(和%prec在完全相同的方式,非GLR分析器做的声明); 通过优先淘汰解析器动作确实消除,不会导致并行状态。 然而,GLR解析器还可以处理降低/减少冲突,其中有两个可能的减少(可能以相同的非端子)。 这些冲突可以使用分辨%dprec (“动态优先级”)的声明。



Answer 2:

野牛的优先级对规则的工作原理是规则的优先级比较所有冲突令牌的优先转移,解决了S / R冲突时。 因此,比较BINARY_SEND_PREC到的优先级“|” 和 'OR'。 对于“或”它挑选降低。 要获得减少“|” 以及令牌“|” 本身就必须%left '|' 。 他们一起工作“|” 和“OR”需要相同的优先级。

没有为这类问题的变通方法,如果你可以指定终端“或”的associativty和“|”等,并设置它们的优先级相同。 一对夫妇改变缀计算器例如可以分析这样的输入:

2 PLUS -3 TIMES 4 ^ 2 + 3

-43

主要的变化是这样的:

%token PLUS
%token TAKE
%left '-' '+' PLUS TAKE

... 

add:      '+' | PLUS;
exp:      NUM                           { $$ = $1;         }
        | exp add exp        %prec '+'  { $$ = $1 + $3;    }

在非终端优先将是一个有用的扩展野牛恕我直言。 这将允许用户通过有利于减少以固定S / R冲突当非终端的前缀可以被移动(并且当它可以被移动一非末端与优先级-可存在其它有效的理由转移)。 事实上,我发现这个问题,试图实现一个Haskell风格的功能应用的语法即在

 x y z -> ((x y) z)

但因为单独一个终端也是有效这里,减少的x / Y / Z到非终端是有效的。 Therfore野牛将达到non-term_x non-term_y | z non-term_x non-term_y | z|是堆叠/先行边界)和不知道是否减少到non-term_x_y或移位ž。 (类似的伎俩幸运在这里工作)

我在野牛源周围挖了一点,但我看不到一个简单的方法,允许在非终端%PREC。 当S / R conficts都解决了,只有还原规则是已知的,发生冲突的令牌转移,其中优先级进行比较。 您需要知道这里所有有效shifiting原因,并有办法访问confliciting换挡规则,所以也许..你将需要可切换的令牌分为相应的规则,他们最终将减少组,然后比较规则“优先级。 事端,我会看看有一天...



文章来源: in Bison, how can I specity left associativity for a non-terminal?
标签: bison glr