Many declarations in implementation files have consistent styles, regardless of
the scope in which the declaration appears. These common declarations are
constants, type specifications, variable declarations, function declarations,
construct declaration keywords, and conditional expressions.
Constants
EnumeratedConstant ::= IdentifierName
EnumeratedConstantBlockName ::= IdentifierName
Constant ::= EnumeratedConstant | Number | ShortString | BooleanValueKeyword
A constant evaluates to an unchanging load at
compile-time. This can be an enumerated constant, a number,
a short string, or the Boolean keywords
true or false.
Enumerated constant names must be declared in an enumerated
constant block prior to their usage if they are to be interpreted
as constants during compilation.
Type Specifications
EndianTypeModifier ::= ('bigendian' | 'littleendian')?
SignAndEndianTypeModifiers ::= (('signed' | 'unsigned')? ('bigendian' |
'littleendian')?) | (('bigendian' | 'littleendian')? ('signed' | 'unsigned')?)
SimpleType ::= (SignAndEndianTypeModifiers?
SimpleIntegralTypeName) | (EndianTypeModifier? SimpleFloatingTypeName)
DataStructureType ::= SimpleType | IdentifierName
When specifying a simple type or structured type,
as used with variable types, function return types, unorganized block unit
types, and other contexts like typecasts and memory
allocation, either SimpleType or DataStructureType
can be used.
Simple types can make use of type qualifiers: littleendian
and bigendian for all simple types, and signed
and unsigned for integral types. The
SignAndEndianTypeModifier expression demonstrates that keyword
ordering is not important if there is a need to introduce both
byte order qualifications and sign qualifications
to a simple type.
A structured type must be defined in a structure definition
prior to usage as a valid DataStructureType.
Variable Declarations
VariableDeclaration ::= (*)? S? IdentifierName S? ('[' S? Constant? S? ']'
S? ('[' S? Constant S? ']')?)? (S? '=' S? Initializer)?
Most variable declarations allow for optional pointer
qualification (asterisk), optional one-dimensional array
qualification, optional two-dimensional array qualification,
and optional initializer.
BitFieldVariableDeclaration ::= IdentifierName S? : S? Constant (S? '=' S?
Initializer)?
Bit field variable declarations lack pointer or
array qualification. Instead, bit fields require a colon
and a sizing constant, which specifies the number
of bits occupied by the bit field. A bit field has an
optional initializer.
ParameterVariableDeclaration ::= (*)? S? IdentifierName
Parameter variables, used in function declarations,
differ from VariableDeclaration in that array
qualification and initializer cannot appear.
LocalVariableDeclaration ::= (*)? S? IdentifierName (S? '=' S?
Expression)?
Local variables, used in function bodies, differ
from VariableDeclaration in that array qualification
cannot appear, and optional initializer is replaced by an
optional assigned expression. The expression, if it
appears, makes the local variable declaration serve a dual purpose: variable
declaration and variable assignment at run-time.
If there is no assigned expression, the variable defaults to
zero (for scalar contents) or null (for pointer contents).
Function Declarations
FunctionDeclaration ::= (DataStructureType | void) S (*)? S?
IdentifierName S? ( S? ParameterList S? ) S? { S? FunctionBodyDefinition
S? } S? ;
Function declarations, for both global and
member functions, always assume a common template, FunctionDeclaration.
It is never necessary to qualify namespaces for
member functions, since member functions must always be declared and defined
inside a construct definition.
The asterisk is optional; it identifies the return type as a
pointer to the given type.
The function return type is either a keyword representing one of the built-in
simple types (void, char, short,
long, longlong, float, or
double) or an identifier for a data structure
name. If a data structure name is used, an asterisk
is required.
ParameterList ::= ((DataStructureType | void) S
ParameterVariableDeclaration) (S? , S? (DataStructureType | void) S
ParameterVariableDeclaration)*)?
Parameter lists can contain as many as 255 parameters, and as
few as none.
Variable types identify the base type of parameters. The
type is either a keyword representing one of the built-in
simple types (void, char, short,
long, longlong, float, or
double) or an identifier for a data structure
name. If the void type or a structured type
is used, an asterisk is required to qualify the type as a pointer
(cannot have void parameter type or whole structured type passed by
value).
Variable names uniquely identify parameters. The name is
an identifier that has not appeared earlier in the file as a
construct name, an enumerated constant block name, an
enumerated constant name, or in the parameter list as
another parameter variable name.
The function body must always be defined at time of function
declaration; no prototyping is allowed.
Construct Declaration Keywords
StructKeyword ::= 'struct' | 'class'
Structure declarations can use struct or class
interchangeably; there is no fundamental difference (all structure members are
public).
BlockKeyword ::= 'block' | 'fileformatframework'
Block declarations use block in all cases
except where declaring the top-level construct, in which case,
fileformatframework should be used.
BlockTypeOrganized ::= 'organized' (S 'bitscan')?
BlockTypeUnorganized ::= 'unorganized' (S 'textual')?
BlockType ::= BlockTypeOrganized | BlockTypeUnorganized
When declaring a block, it must be immediately classified as a specific
construct: either organized block (using the 'organized'
keyword) or unorganized block (using the 'unorganized'
keyword).
Optionally, an organized block can be further refined into a
bitscan block with the bitscan attribute, while
an unorganized block can be further refined into a text
block with the textual attribute.
Conditional Expressions
ConditionalExpression ::= ( S? Expression S? )
A conditional expression, enclosed within parentheses,
appears in various function statements. The result of
the expression must be either a scalar or pointer value;
it cannot be void.
BAR does not perform short-circuit evaluation in conditional
expressions. Assume that every load in a conditional expression will be
evaluated.
See also: [Deserialization:
Critical steps] [Serialization: Critical
steps] [Fundamental components]
[Common declarations] [File
scope] [Structure scope] [Block
scope]
[Node list scope] [Decision
list scope] [Function scope] [Expressions]
[Compiler errors] [Compiler
warnings]
|