void Grammar::CalculateFirstSet() { if(pCanEmptyTable == 0) MakeCanReachEmptyTable(); for(int i = 0; i < nVn; i ++) { Set tempSet; FirstSet.push_back(tempSet); } bool flag; do { flag = false; string strLeft, strRight; for(int i = 0; i< nP; i ++) { strLeft = P[i].GetLeft(); strRight = P[i].GetRight(); int iPos = Vn.FindPos(strLeft[0]); if (Vn.Find(strLeft[0])) { if ((strRight == "@")||(Vt.Find(strRight[0]))) flag |= FirstSet[iPos].Insert(strRight[0]); else { unsigned int j = 0; do { char cChar = strRight[j]; if (Vn.Find(cChar)) { flag |= (FirstSet[iPos].Add((GetFirstSet(cChar) - Set('@'))) != 0); if (!CanReachEmpty(cChar)) break; } j ++; }while(j < strRight.length()); if (j == strRight.length()) flag |= FirstSet[iPos].Insert('@'); } } } }while(flag); }代码详细解释
时间: 2024-03-30 14:38:18 浏览: 87
pl0-compiler:用C ++编写的pl0编译器
这段代码是一个计算文法的 First 集合的函数。首先,它调用了 MakeCanReachEmptyTable 函数来计算文法中哪些非终结符可以推出空串。
然后,它遍历所有的产生式,对于每个非终结符,初始化一个空的集合,表示该非终结符的 First 集合。
接着,它进入一个 do-while 循环,该循环会一直执行直到没有新的终结符被加入某个非终结符的 First 集合中。在循环内部,它遍历所有的产生式,对于每个产生式,找到产生式左侧的非终结符在非终结符集合中的位置,然后根据产生式右侧的符号来更新该非终结符的 First 集合。
如果产生式右侧是空串或终结符,则将该终结符加入该非终结符的 First 集合中。
如果产生式右侧是非终结符,则递归地计算该非终结符的 First 集合,并将其加入该非终结符的 First 集合中。如果该非终结符可以推出空串,则继续计算右侧符号的 First 集合。
最后,当没有新的终结符被加入 First 集合时,循环结束,函数返回计算出的 First 集合。
阅读全文