寻找跟随集 - 无限递归

时间:2014-03-13 04:15:42

标签: parsing recursion compiler-construction

在寻找跟随集,规则如 A->aA可以导致无限递归。是否有任何编码技术可以避免它?

请注意,上面的示例只是一个示例,实际上这种递归也可能间接发生。

以下是我用于查找跟随集的示例C代码。语法存储为链表列表。 请告诉我代码是否在任何时候都不清楚。

set findFollowSet(char nonTerminal[], Grammar G, hashTable2 h)  //later assume that all first sets are already in the hashtable.
{
    LINK temp1 = find2(h, nonTerminal);     
    set s= createEmptySet();
    set temp = createEmptySet();
    char lhs[80] = "\0";
    int i;

    //special case
    if(temp1->numRightSideOf==0)     //its not on right side of any grammar rule
        return insert(s, "$");

    for(i=0;i<temp1->numRightSideOf;i++)
    {
        link l = G.rules[temp1->rightSideOf[i]];

        strcpy(lhs, l->symbol);     //storing the lhs just in case the nonTerm appears on the rightmost end of the rule.
        printf("!!!!! %s\n", lhs);
        sleep(1);
        //finding nonTerminal in G
        while(l!=NULL)
        {
            if(strcmp(l->symbol, nonTerminal) == 0)
            break;

            l=l->next;
        }
        //found the nonTerminal in G

        if(l->next!=NULL)
        {
            temp = findFirstSet(l->next, G, h);
            temp = removeElement(temp, "EPSILON");
        }

        else    //its on the rightmost end of the rule
            temp = findFollowSet(lhs, G, h);

        s = setUnion(s, temp);  destroySet(temp);   
    }
    return s;
}

2 个答案:

答案 0 :(得分:2)

FIRST和FOLLOW集是递归定义的,因此您需要找到递归闭包。这在实践中的意思是你没有找到单个非终端的FOLLOW集合 - 你可以同时找到所有终端的所有FOLLOW集合,从所有集合开始为空并超越语法添加符号到不同的集合,直到不再有任何符号添加到任何集合。所以你最终得到的结果是:

FOLLOW[*] = {};  // all follow sets start empty
done = false;
while (!done)
    done = true;
    for (R : each rule in the grammar)
        A = RHS[R];
        tmp = FOLLOW[A];
        for (S : each symbol in LHS[R] from right to left)
            if (S is terminal)
                tmp = {S};
            else
                if (!(FOLLOW[S] contains tmp))
                    done = false
                    FOLLOW[S] |= tmp
                if (epsilon in FIRST[S])
                    tmp |= FIRST[S] - epsilon
                else
                    tmp = FIRST[S]

答案 1 :(得分:0)

好的,我得到了答案,但效率低下。 因此,如果有人想提出一些更有效的答案,请感受到欢迎。

只显式存储递归堆栈,并在每次递归调用时检查该条目是否已存在于堆栈中。 请注意,您需要检查整个堆栈而不仅仅是它的顶部。