为什么我们需要在“简单声明”中使用下面的第二个定义?
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 单元格。一种解决方案是使用垂直圆圈,另一种解决方案是使用水平圆圈。
在数字逻辑中,重叠可以防止毛刺(好!)。在语言语法中,重叠会产生解析歧义(糟糕!)。
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 单元格。一种解决方案是使用垂直圆圈,另一种解决方案是使用水平圆圈。
在数字逻辑中,重叠可以防止毛刺(好!)。在语言语法中,重叠会产生解析歧义(糟糕!)。