Grammatiknotation im C-Standard
Die Struktur von C-Programmen kann beschrieben und auch formal notiert werden. Der C-Standard verwendet dafür eine eigene Notation.
- Terminalsymbole (z. B. Schlüsselwörter) stehen fett, etwa
*if*oder*else*. - Nichtterminale erscheinen kursiv, z. B. [.italic]expression oder [.italic]statement.
- Alternative Schreibweisen stehen in getrennten Zeilen.
- Optionale Teile tragen den Index ~opt~.
Ein Beispiel aus der Sprachsyntax zeigt, wie Regeln ineinander greifen. Hier ein Auszug für die if-Anweisung:
selection-statement:
if ( expression ) secondary-block
if ( expression ) statement else secondary-block
Die Schlüsselwörter if und else sind feste Terminalsymbole und die kursiven Platzhalter expression, statement und secondary-block stehen für andere Regeln, die wiederum weiter definiert sind. Die Regel für expression lautet:
expression:
assignment-expression
expression *,* assignment-expression
Damit wird sichtbar, wie die Grammatik rekursiv arbeitet: Eine if-Anweisung verlangt eine expression und ein statement; die expression selbst kann wiederum eine einfache Konstante oder eine Kombination mehrerer Ausdrücke sein. Auf diese Weise entstehen aus wenigen klar definierten Regeln komplexe Strukturen.
Der komplette Überblick über die Sprachsyntax ist im Anhang A des C-Standards zu finden.
Grafische Darstellung mit Railroad-Diagrammen
Syntaktische Regeln lassen sich nicht nur in Textform (z. B. mit EBNF) angeben, sondern auch grafisch visualisieren. Eine verbreitete Darstellungsform sind sogenannte Railroad-Diagramme (auch Syntaxdiagramme genannt).

Ein Railroad-Diagramm zeigt den möglichen Aufbau einer Sprache als Flussdiagramm:
- Ovale oder abgerundete Kästen stehen für feste Schlüsselwörter oder Zeichen (Terminalsymbole), z. B.
if,elseoder auch Klammern(und). - Rechteckige Kästen bezeichnen Platzhalter für andere Regeln (Nicht-Terminalsymbole).
- Abzweigungen kennzeichnen Alternativen.
- Schleifen oder zurückführende Linien stellen Wiederholungen dar.
Das Diagramm für die Fallunterscheidung mit if macht deutlich, dass nach dem Schlüsselwort if zwingend eine öffnende runde Klammer (, eine expression
und eine schließende Klammer ) folgen müssen. Danach steht entweder ein secondary-block oder ein statement mit anschließendem else und einem weiteren secondary-block.
Auf diese Weise lassen sich auch komplexere Regeln schnell erfassen, da die grafische Struktur Alternativen, feste Terminals und Wiederholungen anschaulich sichtbar macht.
Vollständige C Grammatik als Railroad-Diagramme
abstract declarator:
additive expression:
alignment specifier:
AND expression:
argument expression list:
array abstract declarator:
array declarator:
assignment expression:
assignment operator:
atomic type specifier:
attribute argument clause:
attribute declaration:
attribute list:
attribute prefix:
attribute prefixed token:
attribute specifier sequence:
attribute specifier:
attribute token:
attribute:
balanced token sequence:
balanced token:
binary digit:
binary exponent part:
binary prefix:
bit precise int suffix:
block item list:
block item:
braced initializer:
c char sequence:
c char:
cast expression:
character constant:
compound literal:
compound statement:
conditional expression:
constant expression:
constant:
control line:
d char sequence:
d wchar sequence:
dec direction:
decimal constant:
decimal floating constant:
declaration specifier:
declaration specifiers:
declaration:
declarator:
defined macro expression:
designation:
designator list:
designator:
digit sequence:
digit:
direct abstract declarator:
direct declarator:
direction:
elif group:
elif groups:
else group:
embed parameter sequence:
encoding prefix:
endif line:
enum specifier:
enum type specifier:
enumeration constant:
enumerator list:
enumerator:
equality expression:
escape sequence:
exclusive OR expression:
exponent part:
expression statement:
expression:
external declaration:
floating constant:
floating suffix:
fractional constant:
function abstract declarator:
function body:
function declarator:
function definition:
function specifier:
generic assoc list:
generic association:
generic selection:
group part:
group:
h char sequence:
h pp tokens:
h preprocessing token:
has c attribute express:
has embed expression:
has include expression:
header name tokens:
header name:
hex quad:
hexadecimal constant:
hexadecimal digit sequence:
hexadecimal digit:
hexadecimal floating constant:
hexadecimal fractional constant:
hexadecimal prefix:
identifier continue:
identifier list:
identifier start:
identifier:
if group:
if section:
inclusive OR expression:
init declarator list:
init declarator:
initializer list:
initializer:
integer constant:
integer suffix:
iteration statement:
jump statement:
keyword:
label:
labeled statement:
logical AND expression:
logical OR expression:
long long suffix:
long suffix:
member declaration list:
member declaration:
member declarator list:
member declarator:
multiplicative expression:
n char sequence:
n wchar sequence:
new line:
non directive:
nondigit:
nonzero digit:
octal constant:
octal digit:
octal escape sequence:
on off switch:
parameter declaration:
parameter list:
parameter type list:
pointer:
pp balanced token sequence:
pp balanced token:
pp parameter clause:
pp parameter name:
pp parameter:
pp prefixed parameter:
pp standard parameter:
pp tokens:
preprocessing file:
preprocessing token:
primary block:
primary expression:
punctuator:
q char sequence:
relational expression:
replacement list:
s char sequence:
s char:
secondary block:
selection statement:
shift expression:
sign:
simple escape sequence:
specifier qualifier list:
standard attribute:
standard pragma:
statement:
static assert declaration:
storage class specifier:
storage class specifiers:
string literal:
struct or union specifier:
struct or union:
text line:
token:
translation unit:
type name:
type qualifier list:
type qualifier:
type specifier qualifier:
type specifier:
typedef name:
typeof specifier argument:
typeof specifier:
unary expression:
unary operator:
universal character name:
unlabeled statement:
unsigned suffix:
va opt replacement:
