yacc 运算符关联性声明对只有几个标记的表达式的影响

Effect of yacc operator associativity declaration on expressions that have just a few tokens

当你有这样的语法时:

B:  'a' A 'a'
|   'b' A 'b'
A:  'a' 'a'
|   'a'

%right 'a' 声明导致 aa.a 不被接受,因为在 '.' 发生了移位而不是减少, 并且 %left 'a' 既不接受 aa.aa 也不接受 ba.ab 因为解析总是在点处减少。

我不太清楚在令牌 ('a') 未直接用作运算符的情况下如何弄清楚关联性声明有什么影响。

为什么您认为 LR(1) 会更直观?语法不是 LR(1),因此任何 LR(1) 解析器生成器都应该报告 shift/reduce 冲突,就像 LALR(1) 解析器生成器一样。

当然,yacc/bison 不是纯粹的 LALR(1) 解析器生成器。如果它使用 precedence/associativity 声明解决了 shift/reduce 冲突,那么它会抑制警告。但是,这并不能使语法明确无误。使用优先级声明的(许多)问题之一是不再清楚您正在解析的语言。默默地忽略 shift/reduce 并静态解析它以支持一个或另一个操作将生成一个解析器,该解析器可以识别 一些 上下文无关语言,但它不是描述的语言语法。

不过,

None 其中与 LALR 算法有关。


回答您的问题:bison/yacc 用于解决 shift/reduce 冲突的算法非常简单。

  1. 优先声明中提到的每个终端都被分配了一个优先值。同一个声明中提及的所有终端具有相同的优先级,并且比前一个声明中提及的任何终端具有更高的优先级。

  2. 为其最后一个终端具有优先值的每个产品分配相同的优先值。 (如果产生式包含 %prec TERMINAL 修饰符,则使用该终端代替产生式中的最后一个终端。

  3. 如果产生式与某些先行符号存在移位归约冲突,并且产生式和先行符号都具有优先级值,则在产生式的优先级更高或更高时应用归约如果优先级相等并且优先级由 %left 声明分配。如果先行符号的优先级更高或优先级相等且优先级由 %right 声明分配,则应用移位。

就是这样。注意,在上面的算法中,并没有提到运算符,这实际上在任何形式的LR解析中都不是一个概念。