I'm trying to write a C parser, for my own education. I know that I could use tools like YACC to simplify the process, but I want to learn as much as possible from the experience, so I'm starting from scratch.
My question is how I should handle a line like this:
doSomethingWith((foo)(bar));
It could be that (foo)(bar)
is a type cast, as in:
typedef int foo;
void doSomethingWith(foo aFoo) { ... }
int main() {
float bar = 23.6;
doSomethingWith((foo)(bar));
return 0;
}
Or, it could be that (foo)(bar)
is a function call, as in:
int foo(int bar) { return bar; }
void doSomethingWith(int anInt) { ... }
int main() {
int bar = 10;
doSomethingWith((foo)(bar));
return 0;
}
It seems to me that the parser cannot determine which of the two cases it is dealing with solely by looking at the line doSomethingWith((foo)(bar));
This annoys me, because I was hoping to be able to separate the parsing stage from the "interpretation" stage where you actually determine that the line typedef int foo;
means that foo
is now a valid type. In my imagined scenario, Type a = b + c * d
would parse just fine, even if Type, a, b, c, and d aren't defined anywhere, and problems would only arise later, when actually trying to "resolve" the identifiers.
So, my question is: how do "real" C parsers deal with this? Is the separation between the two stages that I was hoping for just a naive wish, or am I missing something?