ProjectSet Grammar::GetClosure(const Pair & pair1) { int iNum = pair1.one; int iPos = pair1.two; ProjectSet temp; temp.Insert(Pair(iNum, iPos)); int iCount = 0; while (iCount < temp.Size()) { iNum = temp.GetAt(iCount).one; iPos = temp.GetAt(iCount).two; string strRight = P[iNum].GetRight(); if (iPos < strRight.length()) { if (Vn.Find(strRight[iPos])) { for (int j = 0; j < nP; j++) { if (P[j].GetLeft()[0] == strRight[iPos]) temp.Insert(Pair(j,0)); } } } iCount++; } return temp; }代码详细解释
时间: 2024-03-29 15:34:25 浏览: 53
这段代码实现了一个文法中的项目集闭包算法,接受一个二元组pair1作为输入,输出一个ProjectSet类型的对象。
首先,将pair1插入到一个名为temp的ProjectSet对象中,表示该项目集的闭包。接着,使用一个while循环对temp中的每个项目进行扫描和扩展。循环条件是iCount < temp.Size(),即temp中还有项目未被扫描。在循环内部,首先获取temp中第iCount个项目的产生式编号和扫描位置,即iNum和iPos。然后,从文法中获取iNum所对应的产生式的右部字符串,即strRight。如果iPos小于strRight的长度,说明该产生式还有符号未被扫描,需要进行扩展。如果strRight[iPos]是一个非终结符(即在Vn集合中),则需要遍历文法中的所有产生式,找到所有左部为该非终结符的产生式,并将它们的(产生式编号, 0)插入到temp中。这里的0表示扫描位置从头开始。
最后,返回temp即可。由于该算法中使用了while循环,该算法的复杂度是O(n^2)的,其中n是文法中的产生式总数。
相关问题
ProjectSet Grammar::GetClosure(const Pair & pair1) { int iNum = pair1.one; int iPos = pair1.two; ProjectSet temp; temp.Insert(Pair(iNum, iPos)); int iCount = 0; while (iCount < temp.Size()) { iNum = temp.GetAt(iCount).one; iPos = temp.GetAt(iCount).two; string strRight = P[iNum].GetRight(); if (iPos < strRight.length()) { if (Vn.Find(strRight[iPos])) { for (int j = 0; j < nP; j++) { if (P[j].GetLeft()[0] == strRight[iPos]) temp.Insert(Pair(j,0)); } } } iCount++; } return temp; }代码思路详细解释
这段代码实现了一个文法中的项目集闭包算法。该算法的输入是一个二元组pair1,表示文法中的某个项目集中的一个项目,即一个产生式和该产生式中的某个位置。输出是一个ProjectSet类型的对象,表示包含了pair1所在的项目集的闭包。
首先,将pair1插入到一个名为temp的ProjectSet对象中。然后,循环遍历temp中的所有项目,对于每个项目,检查该项目所在产生式的右部是否还有符号未扫描。如果有,检查该符号是否为非终结符。若是,则遍历文法中所有产生式,找到左部为该非终结符的产生式,并将该产生式的(产生式编号, 0)插入到temp中,表示该产生式的第一个符号已经扫描。
最后,返回temp,即为pair1所在项目集的闭包。
bool Grammar::FillTable(int nLine, char cChar, Pair p) { int iPos; if (cChar == '#') iPos = nLine * (nVt + 1 + nVn) + nVt; else if ((iPos = Vn.FindPos(cChar)) != -1) iPos += (nLine * (nVt + 1 + nVn) + nVt + 1); else if ((iPos = Vt.FindPos(cChar)) != -1) iPos += (nLine * (nVt + 1 + nVn)); else assert(false); if (pTable[iPos] == Pair(0,0)) pTable[iPos] = p; else { if(!(pTable[iPos] == p)) return false; } return true; }代码详细解释
这是一个C++函数,用于填充LR(1)语法分析表中的某个位置。下面是对每一行代码的详细解释:
1. bool Grammar::FillTable(int nLine, char cChar, Pair p)
这是一个名为FillTable的成员函数,它属于Grammar类。函数有三个参数:nLine表示当前要填充表格的行数,cChar表示当前要填充表格的列的字符,p是一个Pair类型的值,表示要填充到表格中的内容。函数返回一个bool类型的值,表示填充是否成功。
2. int iPos;
在函数中定义了一个整型变量iPos,表示当前要填充的表格位置。iPos的值将在后面的代码中被赋值。
3. if (cChar == '#')
如果当前要填充的列是#,则说明当前位置是在表格中的最后一列,也就是在nVt和nVn之后。此时,表格中该位置的下标可以计算为nLine * (nVt + 1 + nVn) + nVt。
4. else if ((iPos = Vn.FindPos(cChar)) != -1)
如果当前要填充的列是非终结符,则通过调用Vn.FindPos函数查找该非终结符在类成员变量Vn中的位置,如果找到则更新iPos的值。此时,表格中该位置的下标可以计算为nLine * (nVt + 1 + nVn) + nVt + 1 + iPos。
5. else if ((iPos = Vt.FindPos(cChar)) != -1)
如果当前要填充的列是终结符,则通过调用Vt.FindPos函数查找该终结符在类成员变量Vt中的位置,如果找到则更新iPos的值。此时,表格中该位置的下标可以计算为nLine * (nVt + 1 + nVn) + iPos。
6. else assert(false);
如果当前要填充的列既不是终结符也不是非终结符,则说明输入的字符有误,此时程序会抛出一个assertion error。
7. if (pTable[iPos] == Pair(0,0))
如果当前要填充的位置还没有被填充过,则将p填充到该位置。
8. else
否则,说明当前要填充的位置已经被填充过了,此时需要进行冲突检测。
9. if(!(pTable[iPos] == p))
如果当前要填充的位置已经被填充过,并且要填充的内容p与原来的内容不相等,则说明发生了冲突,此时函数返回false。
10. return true;
如果填充成功,函数返回true。
阅读全文