yangnas 发表于 2010-08-13 01:28

看过LCC源码的高人进,重温一下这段代码的意思。。。

最近在看LCC的源代码在看到分析表达式一节中时遇到一个函数,代码如下:

Tree expr1(int tok) {
        static char stop[] = { IF, ID, 0 };
        Tree p = expr2();

        if (t == '='
        || (prec >=6 && prec <=8)
        || (prec >= 11 && prec <= 13)) {
                int op = t;
                t = gettok();
                if (oper == ASGN)
                        p = asgntree(ASGN, p, value(expr1(0)));
                else
                        {
                                expect('=');
                                p = incr(op, p, expr1(0));
                        }
        }
        if (tok)       
                test(tok, stop);
        return p;
}

这个函数是下面赋值表达式文法的转换函数,文法如下:

assignment-expression:
    conditional-expression
    unary-expression assign-operator assignment-expression

可是令我不解的是,为什么这个expr1函数,一进来就先调用expr2呢?(expr2是条件表达式的分析函数)

我一开始的想法是,既然assignment-expression的文法,产生式右端的两项是“或”的关系,理论上应该翻译成:

if( t 属于 condition-expression )
expr2();
else (t 属于 unary-expression assign-operator assignment-expression )
other();

才对呀?

是不是我哪里想错了?

EricFisher 发表于 2010-08-13 08:55

书上说,a = b = c这样的多重赋值语句,解释为a = (b = c),赋值操作为右结合。

所以,对于
assignment-expression:
unary-expression {assign-operator conditional-expression}

应该先分析conditional-expression,也就是先调用expr2。

yangnas 发表于 2010-08-14 02:20

谢谢,EricFisher 。:emn1:

yangnas 发表于 2010-08-14 03:22

有点明白了。。。
原来是assignment-expression的翻译,没完全遵照文法,为的是有"强大"的错误处理能力。。。书上这么说的。

yangnas 发表于 2010-08-16 00:52

明白了,原来是因为虽然赋值表达式的文法如下所示:
assignment-expression:
    conditional-expression
    unary-expression assign-operator assignment-expression
但第一个产生式被去掉,然后第二个产生式被修改。
最后新的产生式,实际上是
assignment-expression:
    conditional-expression assign-operator assignment-expression
因为conditional-expression包含unary-expression,这样以来,只要等分析返回时通过语义分析就可判定出那些不合法的产生式。这样就实现了更强的出错处理能力了。
页: [1]
查看完整版本: 看过LCC源码的高人进,重温一下这段代码的意思。。。