BartC said:
In this example:
{... a: b: c: d: f: g: h: }
this would be a syntax error (I now know). The labels need to apply to a
statement. By adding a semicolon:
{... a: b: c: d: f: g: h:; }
that satisfies the condition for h:, but it also does so for a: thru g:.
Either the empty ";" statement can have any number of label prefixes, or h:;
now forms a new statement on top of ";", which now satisfies the condition
for g:, and so on.
Each of these:
;
h:;
g: h: ;
f: g: h: ;
...
a: b: c: d: f: g: h:;
{ a: b: c: d: f: g: h:; }
is a statement. The first is a null-statement (which, oddly, is
considered to be a form of expression-statement). The last is a
compound-statement. The others are all labeled-statements.
This is apparently what C does (combine a label and a statement into a new
composite statement), which sounds a complicated way of doing things,
although it has no real affect on programming other than the minor issue of
sometimes having to add in dummy empty statements.
It's actually a reasonably simple way of defining it. Syntactic
constructs in C are defined recursively in terms of other syntactic
constructs (statements can contain statements and expression,
expression can contain expressions and statements, and so on),
until you get down to single tokens -- which are themselves defined
similarly until you get down to single characters. There are
decades of work on parsing input based on recursive grammars.
And it allows programmers to write arbitrarily complex code (which
admittedly not always an entirely good thing).
If what you mean is that it would have been simpler to define a label
as a kind of statement, rather than as part of a particular kind
of statement, I suppose that's true -- but dummy empty statements
aren't the only issue. Consider this:
if (condition)
label: statement;
If a label were a statement by itself, then `statement;` would be
executed unconditionally, since `label:` would be the only thing
controlled by the `if`.
The majority of the time, you *want* a label to apply to some
particular statement (that's executed when you branch to the label).
And for the cases where you don't want that, as you've seen, it's
easy enough to add a null statement (a semicolon).
When I program this stuff, labels are just treated as statements in their
own right, for parsing purposes anyway. (At least C *has* labels; some
potential target languages have done away with 'goto' completely.)
If that works for you, that's fine -- but I suspect you'd encounter
fewer problems if you treat labels the same way the C grammar
treats them.
As for gotoless target languages, the Böhm-Jacopini theorem implies that
gotos are never strictly necessary.
<
http://en.wikipedia.org/wiki/Structured_program_theorem>