A.0 About This Annex
This annex collects the complete grammar of Ocean Edition I. It repeats, in one place, the productions that appear throughout clause 6, and it is the copy an implementation is expected to transcribe. Where a grammar fragment inside a language clause disagrees with this annex, this annex wins.
The notation is described in clause 0.6. An element followed by opt is optional. Repetition is written by recursion.
The grammar is ambiguous without declaration information, because a typedef name and an ordinary identifier are spelled the same way. Resolving that requires the parser to track declarations. See clause 6.7.7.
A.1 Lexical Grammar
A.1.1 Tokens
token:
keyword
identifier
constant
string-literal
punctuator
preprocessing-token:
header-name
identifier
pp-number
character-constant
string-literal
punctuator
each non-white-space character that cannot be one of the above
A.1.2 Keywords
keyword: one of
bool break case char const
continue default do double else
enum extern false float for
goto if inline int long
namespace null NULL restrict return
short signed sizeof static struct
switch true typedef union unsigned
void volatile while
The identifiers auto, register, and _Bool are reserved and are not keywords. See clause 6.4.1.1.
A.1.3 Identifiers
identifier:
identifier-nondigit
identifier identifier-nondigit
identifier digit
identifier-nondigit:
nondigit
universal-character-name
other implementation-defined characters
nondigit: one of
_ a b c d e f g h i j k l m n o p q r s t u v w x y z
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
digit: one of
0 1 2 3 4 5 6 7 8 9
qualified-identifier:
:: identifier
namespace-qualification :: identifier
namespace-qualification:
namespace-name
namespace-qualification :: namespace-name
namespace-name:
identifier
A qualified-identifier is not a token. It is a sequence of tokens, defined here so that both the lexical grammar and the phrase structure grammar can refer to it. See clause 6.5.1.1.
A.1.4 Universal Character Names
universal-character-name:
\u hex-quad
\U hex-quad hex-quad
hex-quad:
hexadecimal-digit hexadecimal-digit hexadecimal-digit hexadecimal-digit
A.1.5 Constants
constant:
integer-constant
floating-constant
enumeration-constant
character-constant
boolean-constant
null-constant
integer-constant:
decimal-constant integer-suffix-opt
octal-constant integer-suffix-opt
hexadecimal-constant integer-suffix-opt
decimal-constant:
nonzero-digit
decimal-constant digit
octal-constant:
0
octal-constant octal-digit
hexadecimal-constant:
hexadecimal-prefix hexadecimal-digit
hexadecimal-constant hexadecimal-digit
hexadecimal-prefix: one of
0x 0X
nonzero-digit: one of
1 2 3 4 5 6 7 8 9
octal-digit: one of
0 1 2 3 4 5 6 7
hexadecimal-digit: one of
0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F
integer-suffix:
unsigned-suffix long-suffix-opt
unsigned-suffix long-long-suffix
long-suffix unsigned-suffix-opt
long-long-suffix unsigned-suffix-opt
unsigned-suffix: one of
u U
long-suffix: one of
l L
long-long-suffix: one of
ll LL
floating-constant:
decimal-floating-constant
hexadecimal-floating-constant
decimal-floating-constant:
fractional-constant exponent-part-opt floating-suffix-opt
digit-sequence exponent-part floating-suffix-opt
hexadecimal-floating-constant:
hexadecimal-prefix hexadecimal-fractional-constant
binary-exponent-part floating-suffix-opt
hexadecimal-prefix hexadecimal-digit-sequence
binary-exponent-part floating-suffix-opt
fractional-constant:
digit-sequence-opt . digit-sequence
digit-sequence .
exponent-part:
e sign-opt digit-sequence
E sign-opt digit-sequence
sign: one of
+ -
digit-sequence:
digit
digit-sequence digit
hexadecimal-fractional-constant:
hexadecimal-digit-sequence-opt . hexadecimal-digit-sequence
hexadecimal-digit-sequence .
binary-exponent-part:
p sign-opt digit-sequence
P sign-opt digit-sequence
hexadecimal-digit-sequence:
hexadecimal-digit
hexadecimal-digit-sequence hexadecimal-digit
floating-suffix: one of
f l F L
enumeration-constant:
identifier
qualified-identifier
boolean-constant: one of
true false
null-constant: one of
null NULL
character-constant:
' c-char-sequence '
L' c-char-sequence '
c-char-sequence:
c-char
c-char:
any member of the source character set except ' , \ , or a new-line
escape-sequence
A c-char-sequence contains exactly one c-char. Multi-character constants are not part of this edition. See clause 6.4.4.4.
escape-sequence:
simple-escape-sequence
octal-escape-sequence
hexadecimal-escape-sequence
universal-character-name
simple-escape-sequence: one of
\' \" \? \\ \a \b \f \n \r \t \v
octal-escape-sequence:
\ octal-digit
\ octal-digit octal-digit
\ octal-digit octal-digit octal-digit
hexadecimal-escape-sequence:
\x hexadecimal-digit
hexadecimal-escape-sequence hexadecimal-digit
A.1.6 String Literals
string-literal:
" s-char-sequence-opt "
L" s-char-sequence-opt "
s-char-sequence:
s-char
s-char-sequence s-char
s-char:
any member of the source character set except " , \ , or a new-line
escape-sequence
A.1.7 Punctuators
punctuator: one of
[ ] ( ) { } . ->
++ -- & * + - ~ !
/ % << >> < > <= >= == != ^ | && ||
? : :: ; ...
= *= /= %= += -= <<= >>= &= ^= |=
, # ##
Digraph spellings are not part of this edition. See clause 5.2.1.1.
A.1.8 Header Names
header-name:
< h-char-sequence >
" q-char-sequence "
h-char-sequence:
h-char
h-char-sequence h-char
h-char:
any member of the source character set except a new-line or >
q-char-sequence:
q-char
q-char-sequence q-char
q-char:
any member of the source character set except a new-line or "
A.1.9 Preprocessing Numbers
pp-number:
digit
. digit
pp-number digit
pp-number identifier-nondigit
pp-number e sign
pp-number E sign
pp-number p sign
pp-number P sign
pp-number .
A.2 Phrase Structure Grammar
A.2.1 Expressions
primary-expression:
identifier
qualified-identifier
constant
string-literal
( expression )
qualified-identifier is defined in clause A.1.3, because it is built from identifiers and a punctuator and is referred to by both the lexical and the phrase structure grammar.
postfix-expression:
primary-expression
postfix-expression [ expression ]
postfix-expression ( argument-expression-list-opt )
postfix-expression . identifier
postfix-expression -> identifier
postfix-expression ++
postfix-expression --
( type-name ) { initializer-list }
( type-name ) { initializer-list , }
argument-expression-list:
assignment-expression
argument-expression-list , assignment-expression
unary-expression:
postfix-expression
++ unary-expression
-- unary-expression
unary-operator cast-expression
sizeof unary-expression
sizeof ( type-name )
unary-operator: one of
& * + - ~ !
cast-expression:
unary-expression
( type-name ) cast-expression
multiplicative-expression:
cast-expression
multiplicative-expression * cast-expression
multiplicative-expression / cast-expression
multiplicative-expression % cast-expression
additive-expression:
multiplicative-expression
additive-expression + multiplicative-expression
additive-expression - multiplicative-expression
shift-expression:
additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression
relational-expression:
shift-expression
relational-expression < shift-expression
relational-expression > shift-expression
relational-expression <= shift-expression
relational-expression >= shift-expression
equality-expression:
relational-expression
equality-expression == relational-expression
equality-expression != relational-expression
AND-expression:
equality-expression
AND-expression & equality-expression
exclusive-OR-expression:
AND-expression
exclusive-OR-expression ^ AND-expression
inclusive-OR-expression:
exclusive-OR-expression
inclusive-OR-expression | exclusive-OR-expression
logical-AND-expression:
inclusive-OR-expression
logical-AND-expression && inclusive-OR-expression
logical-OR-expression:
logical-AND-expression
logical-OR-expression || logical-AND-expression
conditional-expression:
logical-OR-expression
logical-OR-expression ? expression : conditional-expression
assignment-expression:
conditional-expression
unary-expression assignment-operator assignment-expression
assignment-operator: one of
= *= /= %= += -= <<= >>= &= ^= |=
expression:
assignment-expression
expression , assignment-expression
constant-expression:
conditional-expression
A.2.2 Declarations
declaration:
declaration-specifiers init-declarator-list-opt ;
declaration-specifiers:
storage-class-specifier-opt type-qualifier-list-opt
function-specifier-opt type-specifier
init-declarator-list:
init-declarator
init-declarator-list , init-declarator
init-declarator:
declarator
declarator = initializer
The order of components in declaration-specifiers is fixed. See clause 6.7.8.
storage-class-specifier:
typedef
extern
static
type-specifier:
void
bool
char
signed char
unsigned char
short
unsigned short
int
unsigned int
long
unsigned long
long long
unsigned long long
float
double
long double
struct-or-union-specifier
enum-specifier
typedef-name
These are the canonical spellings, and they are the only spellings. See clause 6.7.2.1.
struct-or-union-specifier:
struct-or-union identifier-opt { struct-declaration-list }
struct-or-union identifier
struct-or-union qualified-identifier
struct-or-union:
struct
union
struct-declaration-list:
struct-declaration
struct-declaration-list struct-declaration
struct-declaration:
specifier-qualifier-list struct-declarator-list ;
specifier-qualifier-list:
type-qualifier-list-opt type-specifier
struct-declarator-list:
struct-declarator
struct-declarator-list , struct-declarator
struct-declarator:
declarator
declarator-opt : constant-expression
enum-specifier:
enum identifier-opt { enumerator-list }
enum identifier-opt { enumerator-list , }
enum identifier
enum qualified-identifier
enumerator-list:
enumerator
enumerator-list , enumerator
enumerator:
enumeration-constant
enumeration-constant = constant-expression
type-qualifier:
const
volatile
restrict
type-qualifier-list:
type-qualifier
type-qualifier-list type-qualifier
function-specifier:
inline
inline shall appear only together with static. See clause 6.7.4.
declarator:
pointer-opt direct-declarator
direct-declarator:
identifier
( declarator )
direct-declarator [ constant-expression-opt ]
direct-declarator ( parameter-type-list )
pointer:
* type-qualifier-list-opt
* type-qualifier-list-opt pointer
parameter-type-list:
void
parameter-list
parameter-list , ...
parameter-list:
parameter-declaration
parameter-list , parameter-declaration
parameter-declaration:
declaration-specifiers declarator
declaration-specifiers abstract-declarator-opt
A direct-declarator with omitted constant-expression is permitted only for a definition with an initializer and for a flexible array member. Qualifiers and static do not appear inside array brackets. There is no identifier-list production, because old-style function definitions do not exist. See clause 6.7.5.
type-name:
specifier-qualifier-list abstract-declarator-opt
abstract-declarator:
pointer
pointer-opt direct-abstract-declarator
direct-abstract-declarator:
( abstract-declarator )
direct-abstract-declarator-opt [ constant-expression-opt ]
direct-abstract-declarator-opt ( parameter-type-list-opt )
typedef-name:
identifier
qualified-identifier
initializer:
assignment-expression
{ initializer-list }
{ initializer-list , }
initializer-list:
designation-opt initializer
initializer-list , designation-opt initializer
designation:
designator-list =
designator-list:
designator
designator-list designator
designator:
[ constant-expression ]
. identifier
A.2.3 Statements
statement:
labeled-statement
compound-statement
expression-statement
selection-statement
iteration-statement
jump-statement
labeled-statement:
identifier : statement
case constant-expression : statement
default : statement
compound-statement:
{ block-item-list-opt }
block-item-list:
block-item
block-item-list block-item
block-item:
declaration
statement
expression-statement:
expression-opt ;
selection-statement:
if ( expression ) statement
if ( expression ) statement else statement
switch ( expression ) statement
iteration-statement:
while ( expression ) statement
do statement while ( expression ) ;
for ( expression-opt ; expression-opt ; expression-opt ) statement
for ( declaration expression-opt ; expression-opt ) statement
jump-statement:
goto identifier ;
continue ;
break ;
return expression-opt ;
A.2.4 External Definitions
translation-unit:
external-declaration
translation-unit external-declaration
external-declaration:
function-definition
declaration
namespace-definition
function-definition:
declaration-specifiers declarator compound-statement
namespace-definition:
namespace namespace-qualification { external-declaration-list-opt }
external-declaration-list:
external-declaration
external-declaration-list external-declaration
There is no declaration-list between the declarator and the body. See clause 6.7.5.3.
A.3 Preprocessing Directives
preprocessing-file:
group-opt
group:
group-part
group group-part
group-part:
if-section
control-line
text-line
# non-directive
if-section:
if-group elif-groups-opt else-group-opt endif-line
if-group:
# if constant-expression new-line group-opt
# ifdef identifier new-line group-opt
# ifndef identifier new-line group-opt
elif-groups:
elif-group
elif-groups elif-group
elif-group:
# elif constant-expression new-line group-opt
else-group:
# else new-line group-opt
endif-line:
# endif new-line
control-line:
# include pp-tokens new-line
# define identifier replacement-list new-line
# define identifier lparen identifier-list-opt ) replacement-list new-line
# define identifier lparen ... ) replacement-list new-line
# define identifier lparen identifier-list , ... ) replacement-list new-line
# undef identifier new-line
# line pp-tokens new-line
# error pp-tokens-opt new-line
# warning pp-tokens-opt new-line
# pragma pp-tokens-opt new-line
# namespace string-literal new-line
# import pp-tokens new-line
# new-line
text-line:
pp-tokens-opt new-line
non-directive:
pp-tokens new-line
lparen:
a ( character not immediately preceded by white space
replacement-list:
pp-tokens-opt
pp-tokens:
preprocessing-token
pp-tokens preprocessing-token
identifier-list:
identifier
identifier-list , identifier
new-line:
the new-line character
The defined operator and the __has_include operator appear only in the controlling expression of # if and # elif. See clause 6.10.1.
A.4 Productions ISO C99 Has and This Edition Does Not
For readers transcribing a C99 grammar into an Ocean Edition I one, these productions are deleted:
| Deleted production | Replacement |
|---|---|
storage-class-specifier: auto |
ordinary block-scope declaration |
storage-class-specifier: register |
ordinary declaration |
direct-declarator: direct-declarator [ type-qualifier-list-opt assignment-expression-opt ] |
constant array bounds only |
direct-declarator: direct-declarator [ static type-qualifier-list-opt assignment-expression ] |
write the pointer type |
direct-declarator: direct-declarator [ type-qualifier-list static assignment-expression ] |
write the pointer type |
direct-declarator: direct-declarator [ type-qualifier-list-opt * ] |
variable-length arrays are removed |
direct-declarator: direct-declarator ( identifier-list-opt ) |
prototypes only |
function-definition: declaration-specifiers declarator declaration-list compound-statement |
prototype-style definitions only |
type-specifier: _Bool |
bool, now a keyword |
type-specifier: _Complex |
optional extension |
type-specifier: _Imaginary |
optional extension |
| digraph punctuators | spell the punctuator |
And these productions are constrained rather than deleted:
| Production | Constraint |
|---|---|
declaration-specifiers |
fixed component order, clause 6.7.8 |
type-specifier |
canonical spellings only, clause 6.7.2.1 |
function-specifier: inline |
only together with static, clause 6.7.4 |
c-char-sequence |
exactly one character, clause 6.4.4.4 |
And these productions are added:
| Added production | Reason |
|---|---|
type-specifier: bool |
boolean type promoted to the core language, clause 6.2.5.2 |
constant: boolean-constant |
true and false promoted to the core language, clause 6.4.4.5 |
constant: null-constant |
null and NULL promoted to the core language, clause 6.4.4.6 |
control-line: # warning pp-tokens-opt new-line |
clause 6.10.5.1 |
keyword: namespace |
namespace definitions, clause 6.7.10 |
punctuator: :: |
namespace qualification, clause 6.5.1.1 |
primary-expression: qualified-identifier |
clause 6.5.1.1 |
external-declaration: namespace-definition |
clause 6.7.10 |
control-line: # namespace string-literal new-line |
clause 6.10.10 |
control-line: # import pp-tokens new-line |
clause 6.10.11 |
typedef-name: qualified-identifier |
qualified typedef names, clause 6.7.7 |
enumeration-constant: qualified-identifier |
qualified enumerators, clause 6.7.2.3 |
struct-or-union-specifier: struct-or-union qualified-identifier |
qualified tag reference, clause 6.7.2.2 |
enum-specifier: enum qualified-identifier |
qualified tag reference, clause 6.7.2.3 |
The productions in the last block are the only additions this edition makes to the C grammar, and clause 1.5 states the test they had to pass.