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 12:38:18 浏览: 98
这段代码是一个计算文法的 First 集合的函数。首先,它调用了 MakeCanReachEmptyTable 函数来计算文法中哪些非终结符可以推出空串。
然后,它遍历所有的产生式,对于每个非终结符,初始化一个空的集合,表示该非终结符的 First 集合。
接着,它进入一个 do-while 循环,该循环会一直执行直到没有新的终结符被加入某个非终结符的 First 集合中。在循环内部,它遍历所有的产生式,对于每个产生式,找到产生式左侧的非终结符在非终结符集合中的位置,然后根据产生式右侧的符号来更新该非终结符的 First 集合。
如果产生式右侧是空串或终结符,则将该终结符加入该非终结符的 First 集合中。
如果产生式右侧是非终结符,则递归地计算该非终结符的 First 集合,并将其加入该非终结符的 First 集合中。如果该非终结符可以推出空串,则继续计算右侧符号的 First 集合。
最后,当没有新的终结符被加入 First 集合时,循环结束,函数返回计算出的 First 集合。
相关问题
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); }代码详细解释
这是一个计算文法的First集的函数,主要实现以下功能:
1. 先判断是否已经计算出能够推出空串的非终结符集合,如果没有则调用MakeCanReachEmptyTable()函数计算。
2. 对于每个非终结符,都创建一个空的First集合。
3. 循环计算每个产生式的First集合,直到没有新元素加入集合为止。
4. 对于每个产生式A -> B1B2...Bn,如果B1是终结符或者空串,则将B1加入A的First集合。
5. 如果B1是非终结符,则将B1的First集合中除空串之外的元素加入A的First集合,如果B1能够推出空串,则继续判断B2,以此类推。
6. 如果所有的B都能够推出空串,则将空串加入A的First集合。
其中,Set是一个自定义的集合类型,Vn表示非终结符集合,Vt表示终结符集合,P是产生式集合。
void Grammar::CalculateFollowSet() { if(pCanEmptyTable == 0) MakeCanReachEmptyTable(); for(int i = 0; i < nVn; i ++) { Set tempSet; FollowSet.push_back(tempSet); } FollowSet[Vn.FindPos(cStart)].Insert('#'); bool flag = false; do { flag = false; for(int i = 0; i < nP; i ++) { string strLeft, strRight; strLeft = P[i].GetLeft(); strRight = P[i].GetRight(); for ( unsigned int j = 0; j < strRight.length() - 1; j++) { char cChar = strRight[j]; if (Vn.Find(cChar)) { string temp; for(unsigned int k = j + 1; k < strRight.length(); k++) //temp.push_back(strRight[k]); temp += strRight[k]; Set firstset = GetFirstSet(temp); flag |= (FollowSet[Vn.FindPos(cChar)].Add(firstset - Set('@')) != 0); if (CanReachEmpty(temp)) { flag |= (FollowSet[Vn.FindPos(cChar)].Add(GetFollowSet(strLeft[0])) != 0); } } } if (Vn.Find(strRight[strRight.length() -1])) flag |= (FollowSet[Vn.FindPos(strRight[strRight.length() -1])].Add(GetFollowSet(strLeft[0])) != 0); } }while(flag); }代码接详细解释
这是一个计算文法的Follow集的函数,主要实现以下功能:
1. 先判断是否已经计算出能够推出空串的非终结符集合,如果没有则调用MakeCanReachEmptyTable()函数计算。
2. 对于每个非终结符,都创建一个空的Follow集合。
3. 将起始符号的Follow集合设置为“#”。
4. 循环计算每个产生式的Follow集合,直到没有新元素加入集合为止。
5. 对于每个产生式A -> B1B2...Bn,将B1的Follow集合加入B2的Follow集合,B2的Follow集合加入B3的Follow集合,以此类推。
6. 如果Bn能够推出空串,则将A的Follow集合加入Bn-1的Follow集合。
7. 如果Bn是非终结符,则将A的Follow集合加入Bn的Follow集合。
其中,Set是一个自定义的集合类型,Vn表示非终结符集合,P是产生式集合,cStart表示文法的起始符号。
阅读全文