stevev@tekchips.LABS.TEK.COM (Steve Vegdahl) (03/15/89)
I am working on a preprocessor that needs to---among other things---transform
between "cast-style" types and "declaration-style" types. For example,
the user's input might contain the string:
(int (*)())
The preprocessor would need to tranform this into the declaration:
int (*foo)();
I am treating this problem as a transformation from a list of tokens to
a list of tokens. (We can assume that the original list is a well-formed
cast expression.)
Not being an expert on C type-declarations, I would appreciate opinions as
to whether this method handles all cases and, if not, some examples
cast-expressions on which it will fail.
Thanks.
Steve Vegdahl
Computer Research Lab
Tektronix Labs
Beaverton, Oregon
----------------------------------------------------------------
Alleged algorithm for transforming cast-style type into a declaration.
1. strip away the outer parentheses of the cast expression
2. find the position to insert the to-be-declared identifier
a. skip over all identifiers, left parentheses, and asterisks (i.e.,
go until you hit a right parenthesis, left bracket or end of string)
b. if the token that "stopped us" was a right parentheses, and the
previous tokens a left parentheses, back up on
3. insert the identifer in the current position
4. add a semicolon to the end
Example #1: declare "foo" as a "(float *)":
after step 1: "float *"
after step 2: "float * "
^current position
after step 3: "float * foo"
after step 4: "float * foo;"
Example #2: declare "foo" as an "(unsigned float **[]())"
after step 1: "unsigned float **[]()"
after step 2: "unsigned float ** []()"
^current position
after step 3: "unsigned float ** foo []()"
after step 4: "unsigned float ** foo []();"
Example #3: declare "foo" as an "(int (*)())"
after step 1: "int (*)()"
after step 2: "int (* )()"
^current position
after step 3: "int (*foo)()"
after step 4: "int (*foo)();"
(Is the algorithm for going the other direction simply that of removing the
declared name and the semicolon and surrounding the entire thing with
parentheses?)mouse@mcgill-vision.UUCP (der Mouse) (03/29/89)
In article <3698@tekcrl.LABS.TEK.COM>, stevev@tekchips.LABS.TEK.COM (Steve Vegdahl) writes: > [is building something to transform casts to declarations] > Not being an expert on C type-declarations, I would appreciate > opinions as to whether this method handles all cases and, if not, > some examples cast-expressions on which it will fail. > Alleged algorithm for transforming cast into a declaration. [compressed slightly -dM] > 1. strip away the outer parentheses of the cast expression > 2. find the position to insert the to-be-declared identifier: > a. skip over all identifiers, left parentheses, and asterisks [You have to treat type keywords as "identifiers" to make that work] > b. if we stopped just after ( and just before ), back up > 3. insert the identifer in the current position > 4. add a semicolon to the end I think this is correct, though I am not at all certain. In a declaration, the only things that can appear before the identifier being declared are certain keywords, typedef names, left parentheses, and *s. (This is based on an examination of the grammar in the back of K&RV2; I'm sure I'll be, er, "corrected" if I'm wrong.) However, the identifier does not necessarily fit into the spot found by the above algorithm, though I *think* it will, provided the cast is legal. (Definitely not for some illegal casts; consider, for example, (int ()), a cast to function returning int (which isn't legal). Your algorithm will place the identifier so as to make this a declaration of an int variable.) All the cases I have been able to construct where the algorithm fails involve casts to function types; I have tried to convince myself this must be so, but so far have failed. > (Is the algorithm for going the other direction simply that of > removing the declared name and the semicolon and surrounding the > entire thing with parentheses?) You have to remove at least some redundant parentheses first. For example, int (foo); declares foo as an int, but (int ()) is the (pseudo-)cast I mentioned above to function-returning-int. I find this disturbing, in view of the statement near the top of page 221 of K&RV2, when discussing abstract types (as used in, eg, casts): It is possible to identify uniquely the location in the abstract-declarator where the identifier would appear if the construction were a declarator in a declaration. As far as I can see, the only thing that allows us to deduce that (int ()) is a cast to function-returning-int rather than to int is the fact that "int foo();" is semantically illegal, while "int (foo);" is legal. Huh? Isn't that backwards? And wait a minute! "int foo();" *is* legal - when foo is a formal parameter: see the paragraph beginning on the fifth line of page 226. Yet I'm sure that (int ()) is understood as a cast to function rather than to int; our (pcc-based) compiler certainly does this ("illegal lhs of assignment operator", not the best possible error), and while pcc does some strange things, a basic misunderstanding of casts strikes me as unlikely to be among them. Is this apparent weirdness due to (a) a real ambiguity, (b) me being confused about something, or (c) K&R being less pedantic than the (p)ANS in their wording? (Or something else?) der Mouse old: mcgill-vision!mouse new: mouse@larry.mcrcim.mcgill.edu