我正在尝试编写一个 C 解析器,用于我自己的教育。我知道我可以使用 YACC 之类的工具来简化流程,但我想尽可能多地从经验中学习,所以我从头开始。
我的问题是我应该如何处理这样的一行:
doSomethingWith((foo)(bar));
这可能(foo)(bar)
是一种类型转换,如:
typedef int foo;
void doSomethingWith(foo aFoo) { ... }
int main() {
float bar = 23.6;
doSomethingWith((foo)(bar));
return 0;
}
或者,它可能(foo)(bar)
是一个函数调用,如:
int foo(int bar) { return bar; }
void doSomethingWith(int anInt) { ... }
int main() {
int bar = 10;
doSomethingWith((foo)(bar));
return 0;
}
在我看来,解析器无法仅通过查看这行doSomethingWith((foo)(bar));
这让我很恼火来确定它正在处理的两种情况中的哪一种,因为我希望能够将解析阶段与您实际确定的“解释”阶段分开这条线typedef int foo;
意味着foo
现在是一个有效的类型。在我想象的场景中Type a = b + c * d
,即使 Type、a、b、c 和 d 没有在任何地方定义,也可以很好地解析,并且问题只会在以后实际尝试“解析”标识符时出现。
所以,我的问题是:“真正的”C 解析器如何处理这个问题?我希望的两个阶段之间的分离只是一个天真的愿望,还是我错过了什么?