C解析器如何区分类型转换和函数调用?

Ord*_*Ord 19 c parsing casting function-call

我正在尝试为自己的教育编写一个C语法分析器.我知道我可以使用像YACC这样的工具来简化流程,但我想从经验中尽可能多地学习,所以我从头开始.

我的问题是我应该如何处理这样的一行:

doSomethingWith((foo)(bar));
Run Code Online (Sandbox Code Playgroud)

它可能(foo)(bar)是一个类型转换,如:

typedef int foo;

void doSomethingWith(foo aFoo) { ... }

int main() {
    float bar = 23.6;

    doSomethingWith((foo)(bar));

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

或者,它可能(foo)(bar)是一个函数调用,如:

int foo(int bar) { return bar; }

void doSomethingWith(int anInt) { ... }

int main() {
    int bar = 10;

    doSomethingWith((foo)(bar));

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在我看来,解析器无法单独通过查看行来确定它处理的两种情况中的哪一种.doSomethingWith((foo)(bar));这让我很烦恼,因为我希望能够将解析阶段与您实际确定的"解释"阶段分开该行typedef int foo;表示foo现在是有效类型.在我想象的场景中,Type a = b + c * d即使Type,a,b,c和d没有在任何地方定义,也会解析得很好,并且只有在实际尝试"解析"标识符时才会出现问题.

所以,我的问题是:"真正的"C解析器如何处理这个?两个阶段之间的分离是我希望只是一个天真的愿望,还是我错过了什么?

Kei*_*son 16

从历史上看,类型定义是一个相对较晚除了C.之前,他们被添加到语言,类型名称由关键字(int,char,double,struct,等)和标点字符(*,[],()),因此很容易明确地认识.标识符永远不能是类型名称,因此括号中的标识符后跟表达式不能是强制转换表达式.

Typedef使用户定义的标识符成为一个类型名称,这相当严重地混淆了语法.

看一下C标准中type-specifier的语法(我将使用C90版本,因为它稍微简单一些):

type-specifier:
void
char
short
int
long
float
double
signed
unsigned
struct-or-union-specifier
enum-specifier
typedef-name

除了最后一个之外的所有内容都可以轻松识别,因为它们是关键字,或者以关键字开头.但是typedef-name只是一个标识符.

当C编译器处理typedef声明时,它实际上需要将typedef名称作为新关键字引入.这意味着,与具有无上下文语法的语言不同,需要从符号表到解析器的反馈.

甚至那有点过于简单了.在内部作用域中,仍可以将typedef名称重新定义为另一个typedef或其他类型:

{
    typedef int foo; /* foo is a typedef name */
    {
        int foo;     /* foo is now an ordinary identifier, an object name */
    }
                     /* And now foo is a typedef name again */
}
Run Code Online (Sandbox Code Playgroud)

因此,如果typedef名称在类型名称有效的上下文中使用,则它实际上是用户定义的关键字,但如果重新声明,则仍然是普通标识符.

TL; DR:解析C很难.

  • "TL; DR:解析C很难." 阿门!:-) (8认同)

Sne*_*tel 13

你所谈论的是一个"无上下文语法",你可以解析一切,而不必记住什么是类型和什么是变量(或者,通常,使用与标识符相关的任何语义属性).不幸的是,C不是没有背景的,所以你没有那么奢侈.

  • 是的.这是[相关链接](http://eli.thegreenplace.net/2007/11/24/the-context-sensitivity-of-cs-grammar/). (3认同)