|Declaration unwinding (was: ... C dec. parser) firstname.lastname@example.org (1995-02-18)|
|From:||email@example.com (Mark Hopkins)|
|Date:||Sat, 18 Feb 1995 09:31:52 GMT|
In the documentation I distributed with my C-BC interpreter (C-BC is a
major extension of UNIX BC), I came up with a rather elegant description
for how the declarations are processed. Since the extended language is
for all intents and purposes an interpreted dialect of C the same basic
description applies to C and you may be able to even come up with a
parsing automaton based on the description.
(Description to follow):
Declarations can be made globally, outside any function. Global variables
and array variables can be declared in this context, and functions can be
forward-referenced. Unlike ANSI-C, there are no old-style function
declarations or definitions at all. Also, all parameters must be explicitly
listed and named in any function declaration. Future implementations can
generalize this to make it conform more to ANSI-C.
In a global context, a declaration takes on the following form:
type declarator, ..., declarator ;
Local variables and array variables can be declared inside functions. For
purposes of defining "inside" and "outside", parameters are considered to lie
inside the function.
A parameter declaration takes on the form:
and a local variable one of the following forms:
type declarator, ..., declarator ;
auto optional-type declarator, ..., declarator ;
Unlike in BC, the use of the word "auto" is optional, but if it is not
present a type indicator must be made explicit.
Each declarator is understood to apply to one of the following types:
number, complex, galois, or string, and any of these names can be used in
place of "type" above. If a type is not explicitly indicated it is understood
to be number by default, like in C.
Also, as in C, any variable or array variable that is used before being
declared is understood to be of type number or array of number, respectively.
Functions, however, must be explicitly declared before being used. This is
a point of departure from both C and BC.
A declarator can take on one of the following forms:
(D) ------------- used for grouping
name ------------ simple declarators
*D -------------- pointer declarators
D ------------- array declarators
D(P, ..., P) ---- function declarators
where D is a declarator, and the P's denote a comma-separated list of 0 or
If a declarator, D, is understood to apply to scalar type s (number,
galois, string), then its interpretation is obtained by taking
s :: D
and applying the following reduction rules on it:
T :: (D) => T :: D
T :: *D => pointer to T :: D
T :: D => array of T :: D
T :: D(p1...pn) => function of T1, ..., Tn returning T :: D
This process of what I call Declaration Unwinding. The result of this
reduction is an item of the form: T :: name, which is interpreted as the
statement "name is declared as a T". The item, T, is called the declarator's
type. In the reduction above, T1 ... Tn are the declarator types that result
from unwinding the parameter declarations p1 through pn.
number *a => number :: *a
=> pointer to number :: a
=> array of pointer to number :: a
number f(x, complex y) => number :: f(x, complex y)
=> function of (number, complex) returning number :: f
Note the way precedence is handled in the first example. It is not possible
to declare a pointer to an array, except by using brackets (e.g. (*a)).
As in ANSI-C, functions cannot return other functions or arrays. But in
addition, in the current version of C-BC, pointers to functions are not
allowed. A second restriction to note is that functions can only be declared
in a global context. There is, in general, nothing in C-BC analogous to
locally declared globals objects.
Repeated declarations, however, are allowed as long as the types match any
Return to the
Search the comp.compilers archives again.