在寻找跟随集,规则如
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;
}
答案 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)
好的,我得到了答案,但效率低下。 因此,如果有人想提出一些更有效的答案,请感受到欢迎。
只显式存储递归堆栈,并在每次递归调用时检查该条目是否已存在于堆栈中。 请注意,您需要检查整个堆栈而不仅仅是它的顶部。