You've effectively defined h
as:
void h(int(int)) {}
The parameter is interpreted as an unnamed function pointer that takes an int
and returns an int
. When you try to pass 42
to it, the compiler complains that you are trying to make a function pointer from an integer.
I think what you are asking for is how do compilers handle (unnamed) function pointer types and their possibly ambiguous parses. Your question is related to the the most vexing parse in C++.
There they decided that whenever there was ambiguity between a function pointer type and another way to parse, then it would be interpreted as a function pointer. They did that because there are other ways to disambiguate when you don't want it to be a function pointer (e.g. - surround it in parentheses, use {} initializer syntax, etc.).
Getting into the specifics of how a parser writer might deal with this parse, here's a lexical analyzer and grammar for C11: http://quut.com/c/ANSI-C-grammar-l-2011.html In your example, before the typedef, x
will be an IDENTIFIER
token while after, it will be a TYPEDEF_NAME
token because the analyzer is being informed through the symbol table that x
is now a type. In this particular case, the parsing is unambiguous then. The "pipeline feedback" that you seem to be referring to occurs through the symbol table in this case, where the lexical analyzer is informed about context by the higher levels that affects its output as the compilation progresses.
EDIT: These three articles, found by the OP, describe this problem and how it is solved by some C parsers / compilers very nicely. Basically, a context free grammar (CFG) that only accepts / generates legal C syntax can almost be specified. With the introduction of a scoped lookup table that allows the lexical analyzer to distinguish between identifiers and typedef-names appropriately, then a CFG [and more importantly a LALR(1) parser (e.g. - yacc generated)] that only accepts / generates legal C syntax can be specified.
Here's an even scarier example than the OP's:
typedef int x;
int main() { x x = 5; return x; } /* crazily enough this is legal C syntax and a well formed C program */
x
as or about the grammar rules that interpret this as a function pointer rather than another parse? – SouthwesterlyHow do parser writers deal with this situation?
There must be some standard idioms, patterns, whatever, because I bet there are dozens of these exceptions to deal with in real world parsers. – Gilbreathx
will be interpreted as anIDENTIFIER
while after, it will be interpreted as aTYPEDEF_NAME
because the analyzer is being informed through the symbol table thatx
is now a type. In this particular case, the parsing is pretty straightforward then. The feedback occurs through the symbol table in this case. – Southwesterlyvoid foo() { typedef int x; { int x; } }
illegal, becauseint x;
would now be parsed asINT TYPEDEF_NAME
? – Gilbreathx
is depending on its scope. Again, that is feedback occurring from the semantic level down to the lexer through the symbol table. – Southwesterly