next up previous
Next: Declarators Up: Syntactic structure Previous: Expressions

Declarations

A declaration specifies the interpretation and attributes of a set of identifiers. The declaration_specifiers phrase consists of a sequence of specifiers that indicate the linkage, storage duration, and part of the type of the entities denoted in the init_declarator_list_opt.

Syntactic elements[12]:

declaration:
  declaration_specifiers init_declarator_list_opt &'Reset state[31]' ';' .

init_declarator_list:
  init_declarator /
  init_declarator_list ',' init_declarator .

init_declarator:
  declarator &'Deferred binding[46] End parameters[53]' /
  declarator &'Deferred binding[46] End parameters[53]' '=' initializer .
This macro is defined in definitions 3, 7, 8, 9, 10, 11, 12, 13, 14, 1, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, and 27.
This macro is invoked in definition 6.

Specifiers appearing in the declaration_specifiers phrase must be drawn from one of the three sets (storage class specifiers, type specifiers, type qualifiers) defined in Section 6.5 of the standard.

Five of the type specifiers can only appear in lists of one element; the other seven can be used to form lists of one or more elements. It is important to distinguish the two kinds of type specifiers syntactically in order to parse a sequence like ``int j;'' properly when j has been declared in an outer scope to be a typedef_name: If the parser knows that a typedef_name cannot follow the type_specifier int, then it will be forced to re-classify j as an identifier. If this information is not available to the parser, then it will detect a syntax error after accepting j as a type_specifier and not finding an identifier. At that point, however, it is too late to re-classify j.

The type_specifiers that must appear singly are therefore classified as type_specifier_1s, and those that may appear in groups are classified as type_specifier_2s.

The phrase declaration_specifiers is then defined to enforce the constraint syntactically. All lists must be left-recursive here in order to detect the error at the proper symbol:

Syntactic elements[13]:

declaration_specifiers:
  ds0 / ds1 / ds2.

  ds0:  /* List without type specifiers */
    storage_class_specifier / ds0 storage_class_specifier /
    type_qualifier / ds0 type_qualifier .

  ds1:  /* List with a single type_specifier_1 */
    type_specifier_1 / ds0 type_specifier_1 /
    ds1 storage_class_specifier / ds1 type_qualifier .

  ds2:  /* List with one or more type_specifier_2's */
    type_specifier_2 / ds0 type_specifier_2 /
    ds2 type_specifier_2 / ds2 storage_class_specifier / ds2 type_qualifier .

storage_class_specifier:
  'typedef' &'Accept a typedef specifier[32]' /
  'extern' /
  'static' /
  'auto' /
  'register' .

type_specifier_1:
  'void' /
  'float' /
  struct_or_union_specifier /
  enum_specifier /
  typedef_name .

type_specifier_2:
  'char' /
  'short' /
  'int' /
  'long' /
  'double' /
  'signed' /
  'unsigned' .

struct_or_union_specifier:
  struct_or_union identifier
    &'Nest[34](`member_def',`0')' '{' struct_declaration_list &'Restore[36]' '}' /
  struct_or_union
    &'Nest[34](`member_def',`0')' '{' struct_declaration_list &'Restore[36]' '}' /
  struct_or_union identifier $';' .
This macro is defined in definitions 3, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, and 27.
This macro is invoked in definition 6.

The modifier $';' in the last line above prevents a reduction to struct_or_union_specifier if the lookahead symbol is ;. A modifier is only effective, however, if there is a conflict. There is no conflict in this grammar involving that alternative: struct_or_union identifier may be followed by either a declarator or a ; and the reduction to a struct_or_union_specifier is valid.

Section 6.5.2.3 of the standard gives the two cases quite different semantics, however. If struct_or_union identifier is followed by a ; then the identifier is a structure or union tag that specifies a new type distinct from any type with the same tag in an enclosing scope (if any). Otherwise it will specify a new type only if there is no structure or union with that tag visible at that point.

When constructing an abstract syntax tree, it is useful to distinguish these contexts by first reducing the identifier to a separate nonterminal and then reducing the result. If this is done, and the given modifier is not present, then a conflict will be introduced into the grammar. The modifier is therefore inserted here in order to allow construction of an appropriate abstract syntax tree without the need to alter this specification.

Syntactic elements[14]:

struct_or_union:
  'struct' /
  'union' .

struct_declaration_list: struct_declaration+ .

struct_declaration:
  specifier_qualifier_list struct_declarator_list ';'.
This macro is defined in definitions 3, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, and 27.
This macro is invoked in definition 6.

A specifier_qualifier_list phrase differs from a declaration_specifiers phrase only in the fact that storage class specifiers are not allowed. The same problem with type specifiers must be solved, and the same mechanism is used.

Syntactic elements[15]:

specifier_qualifier_list:
  sq0 / sq1 / sq2 .

  sq0:  /* List without type specifiers */
    type_qualifier / sq0 type_qualifier .

  sq1:  /* List with a single type_specifier_1 */
    type_specifier_1 / sq0 type_specifier_1 / sq1 type_qualifier .

  sq2:  /* List with one or more type_specifier_2's */
    type_specifier_2 / sq0 type_specifier_2 /
    sq2 type_specifier_2 / sq2 type_qualifier .

struct_declarator_list: struct_declarator // ',' .

struct_declarator:
  member_declarator                         /
  member_declarator ':' constant_expression /
                    ':' constant_expression .

member_declarator:
  member_pointer_declarator /
  member_direct_declarator .

member_direct_declarator:
  MemberIdDef $')'          /
  '(' member_declarator ')' /
  member_array_declarator   /
  member_function_declarator .

member_pointer_declarator:
  '*' type_qualifier_list_opt member_declarator .

member_array_declarator:
  member_direct_declarator '[' constant_exp_opt ']' .

member_function_declarator:
  member_direct_declarator '(' empty_parameter_type_list                ')' /
  member_direct_declarator
    '(' &'Nest[34](`identifier',`0')' parameter_type_list &'Restore[36]' ')' .

MemberIdDef:
  member_def &'Bind[47]' /
  '(' MemberIdDef ')' .

enum_specifier:
  'enum' identifier
    &'Nest[34](`identifier',`1')' '{' enumerator_list &'Restore[36]' '}' /
  'enum'
    &'Nest[34](`identifier',`1')' '{' enumerator_list &'Restore[36]' '}' /
  'enum' identifier .

enumerator_list:
  enumerator /
  enumerator_list ',' enumerator .

enumerator:
  enumeration_constant /
  enumeration_constant '=' constant_expression.

enumeration_constant:
  identifier &'Bind[47]' .

type_qualifier:
  'const' /
  'volatile'.
This macro is defined in definitions 3, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, and 27.
This macro is invoked in definition 6.



Subsections
next up previous
Next: Declarators Up: Syntactic structure Previous: Expressions
2008-08-30