c systems notebook

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).

Abbildung

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, else oder 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: abstract_declarator

additive expression: additive_expression

alignment specifier: alignment_specifier

AND expression: AND_expression

argument expression list: argument_expression_list

array abstract declarator: array_abstract_declarator

array declarator: array_declarator

assignment expression: assignment_expression

assignment operator: assignment_operator

atomic type specifier: atomic_type_specifier

attribute argument clause: attribute_argument_clause

attribute declaration: attribute_declaration

attribute list: attribute_list

attribute prefix: attribute_prefix

attribute prefixed token: attribute_prefixed_token

attribute specifier sequence: attribute_specifier_sequence

attribute specifier: attribute_specifier

attribute token: attribute_token

attribute: attribute

balanced token sequence: balanced_token_sequence

balanced token: balanced_token

binary digit: binary_digit

binary exponent part: binary_exponent_part

binary prefix: binary_prefix

bit precise int suffix: bit_precise_int_suffix

block item list: block_item_list

block item: block_item

braced initializer: braced_initializer

c char sequence: c_char_sequence

c char: c_char

cast expression: cast_expression

character constant: character_constant

compound literal: compound_literal

compound statement: compound_statement

conditional expression: conditional_expression

constant expression: constant_expression

constant: constant

control line: control_line

d char sequence: d_char_sequence

d wchar sequence: d_wchar_sequence

dec direction: dec_direction

decimal constant: decimal_constant

decimal floating constant: decimal_floating_constant

declaration specifier: declaration_specifier

declaration specifiers: declaration_specifiers

declaration: declaration

declarator: declarator

defined macro expression: defined_macro_expression

designation: designation

designator list: designator_list

designator: designator

digit sequence: digit_sequence

digit: digit

direct abstract declarator: direct_abstract_declarator

direct declarator: direct_declarator

direction: direction

elif group: elif_group

elif groups: elif_groups

else group: else_group

embed parameter sequence: embed_parameter_sequence

encoding prefix: encoding_prefix

endif line: endif_line

enum specifier: enum_specifier

enum type specifier: enum_type_specifier

enumeration constant: enumeration_constant

enumerator list: enumerator_list

enumerator: enumerator

equality expression: equality_expression

escape sequence: escape_sequence

exclusive OR expression: exclusive_OR_expression

exponent part: exponent_part

expression statement: expression_statement

expression: expression

external declaration: external_declaration

floating constant: floating_constant

floating suffix: floating_suffix

fractional constant: fractional_constant

function abstract declarator: function_abstract_declarator

function body: function_body

function declarator: function_declarator

function definition: function_definition

function specifier: function_specifier

generic assoc list: generic_assoc_list

generic association: generic_association

generic selection: generic_selection

group part: group_part

group: group

h char sequence: h_char_sequence

h pp tokens: h_pp_tokens

h preprocessing token: h_preprocessing_token

has c attribute express: has_c_attribute_express

has embed expression: has_embed_expression

has include expression: has_include_expression

header name tokens: header_name_tokens

header name: header_name

hex quad: hex_quad

hexadecimal constant: hexadecimal_constant

hexadecimal digit sequence: hexadecimal_digit_sequence

hexadecimal digit: hexadecimal_digit

hexadecimal floating constant: hexadecimal_floating_constant

hexadecimal fractional constant: hexadecimal_fractional_constant

hexadecimal prefix: hexadecimal_prefix

identifier continue: identifier_continue

identifier list: identifier_list

identifier start: identifier_start

identifier: identifier

if group: if_group

if section: if_section

inclusive OR expression: inclusive_OR_expression

init declarator list: init_declarator_list

init declarator: init_declarator

initializer list: initializer_list

initializer: initializer

integer constant: integer_constant

integer suffix: integer_suffix

iteration statement: iteration_statement

jump statement: jump_statement

keyword: keyword

label: label

labeled statement: labeled_statement

logical AND expression: logical_AND_expression

logical OR expression: logical_OR_expression

long long suffix: long_long_suffix

long suffix: long_suffix

member declaration list: member_declaration_list

member declaration: member_declaration

member declarator list: member_declarator_list

member declarator: member_declarator

multiplicative expression: multiplicative_expression

n char sequence: n_char_sequence

n wchar sequence: n_wchar_sequence

new line: new_line

non directive: non_directive

nondigit: nondigit

nonzero digit: nonzero_digit

octal constant: octal_constant

octal digit: octal_digit

octal escape sequence: octal_escape_sequence

on off switch: on_off_switch

parameter declaration: parameter_declaration

parameter list: parameter_list

parameter type list: parameter_type_list

pointer: pointer

pp balanced token sequence: pp_balanced_token_sequence

pp balanced token: pp_balanced_token

pp parameter clause: pp_parameter_clause

pp parameter name: pp_parameter_name

pp parameter: pp_parameter

pp prefixed parameter: pp_prefixed_parameter

pp standard parameter: pp_standard_parameter

pp tokens: pp_tokens

preprocessing file: preprocessing_file

preprocessing token: preprocessing_token

primary block: primary_block

primary expression: primary_expression

punctuator: punctuator

q char sequence: q_char_sequence

relational expression: relational_expression

replacement list: replacement_list

s char sequence: s_char_sequence

s char: s_char

secondary block: secondary_block

selection statement: selection_statement

shift expression: shift_expression

sign: sign

simple escape sequence: simple_escape_sequence

specifier qualifier list: specifier_qualifier_list

standard attribute: standard_attribute

standard pragma: standard_pragma

statement: statement

static assert declaration: static_assert_declaration

storage class specifier: storage_class_specifier

storage class specifiers: storage_class_specifiers

string literal: string_literal

struct or union specifier: struct_or_union_specifier

struct or union: struct_or_union

text line: text_line

token: token

translation unit: translation_unit

type name: type_name

type qualifier list: type_qualifier_list

type qualifier: type_qualifier

type specifier qualifier: type_specifier_qualifier

type specifier: type_specifier

typedef name: typedef_name

typeof specifier argument: typeof_specifier_argument

typeof specifier: typeof_specifier

unary expression: unary_expression

unary operator: unary_operator

universal character name: universal_character_name

unlabeled statement: unlabeled_statement

unsigned suffix: unsigned_suffix

va opt replacement: va_opt_replacement

Abbildung