为什么我们需要在“简单声明”中使用下面的第二个定义?

Why do we need the second definition below in a `simple-declaration`?

simple-declaration:
decl-specifier-seq init-declarator-listopt ;
attribute-specifier-seq decl-specifier-seq init-declarator-list ; <====
属性说明符序列opt decl-specifier-seq ref-qualifieropt [identifier-list]初始化器 ;

请注意,此定义中需要 attribute-specifier-seq。什么时候发生?

鉴于我们希望我们的语法接受:

DSS;
DSS IDL;
ASS DSS IDL;

(加上接受数组形式,这个答案不会进一步处理)

但不是

ASS DSS;

也就是说,如果提供了属性说明符(s),则需要init-declarator-list

问题中所示的语法产生式提供了这一点,重要的是仅以一种方式解析任何合法的简单声明

每个没有 attribute-specifier-seq 的声明都使用第一种情况进行解析。每个声明都使用第二种情况进行解析。两种情况之间没有重叠。

如果第二种情况是

attribute-specifier-seqopt decl-specifier-seq init-declarator-list ;

那么相同的输入将被允许,但规则重叠——DSS IDL; 形式的输入将匹配第一个和第二个,创建一个模糊的解析。

不需要重叠的规则。

使用非重叠规则解决此问题的方法不止一种。以下也可以:

decl-specifier-seq ;

attribute-specifier-seqopt decl-specifier-seq init-declarator-list ;

实际上,这来自 Karnaugh map 的真值 table 的蕴涵运算符(提供的 ASS 意味着提供了 IDL),它在 L 模式中具有三个 True 单元格。一种解决方案是使用垂直圆圈,另一种解决方案是使用水平圆圈。

在数字逻辑中,重叠可以防止毛刺(好!)。在语言语法中,重叠会产生解析歧义(糟糕!)。