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