private HashSet <string> GetProductionFirstSet(NonTerminalProductionItemInfo pitem) { var r = new HashSet <string>(); var onlyepsilon = true; foreach (var citem in pitem.Content) { if (citem != "epsilon") { foreach (var yitem in FirstSet[citem]) { r.Add(yitem); } if (!FirstSet[citem].Contains("epsilon")) { onlyepsilon = false; break; } } } if (onlyepsilon) { r.Add("epsilon"); } return(r); }
/// <summary> /// 消除公因子 /// </summary> private void EliminateCommonFactor() { var n = NewNTPList.Count; var newntpid = 0; var newntpnameprefix = Production_Parser.SysNamePrefix + "U_"; for (var i = 0; i < n; i++) { var lastdiff = 0; var hasdiff = false; var minn = NewNTPList[i].Item[0].Content.Count; for (var j = 1; j < NewNTPList[i].Item.Count; j++) { minn = Math.Min(minn, NewNTPList[i].Item[j].Content.Count); } while (!hasdiff && lastdiff < minn) { var curitem = NewNTPList[i].Item[0].Content[lastdiff]; for (var j = 1; j < NewNTPList[i].Item.Count; j++) { if (curitem != NewNTPList[i].Item[j].Content[lastdiff]) { hasdiff = true; break; } } if (!hasdiff) { lastdiff++; } } if (lastdiff > 0) { //存在公共部分,需要分离 var needepsilon = false; //存在重复项,意味着分离出的非公共部分需要包含epsilon if (lastdiff == minn) { needepsilon = true; } var newntp = new NonTerminalProductionInfo(); newntp.Name = newntpnameprefix + (newntpid++); newntp.Item = new List <NonTerminalProductionItemInfo>(); var hadepsilon = false; //加入非公共部分 foreach (var pitem in NewNTPList[i].Item) { if (pitem.Content.Count > lastdiff) { var isepsilon = true; foreach (var item in pitem.Content) { if (item != "epsilon") { isepsilon = false; } } //判断是否为epsilon项,若是,则设定needepsilon标记留作后面处理 if (isepsilon) { if (!hadepsilon) { hadepsilon = true; needepsilon = true; } } else { var newcontent = new NonTerminalProductionItemInfo(); newcontent.Content = new List <string>(); for (var j = lastdiff; j < pitem.Content.Count; j++) { newcontent.Content.Add(pitem.Content[j]); } newntp.Item.Add(newcontent); } } } //加入epsilon项 if (needepsilon) { newntp.Item.Add(new NonTerminalProductionItemInfo { Content = new string[] { "epsilon" }.ToList() }); } //清空原产生式所有项,仅保留公共项,并在最后追加到该新产生式的引用 var content = NewNTPList[i].Item[0]; NewNTPList[i].Item.Clear(); content.Content.RemoveRange(lastdiff, content.Content.Count - lastdiff); content.Content.Add(newntp.Name); NewNTPList[i].Item.Add(content); NewNTPList.Add(newntp); } } }
/// <summary> /// 消除左递归 /// </summary> private bool EliminateLeftRecursion(out string ErrorText) { ErrorText = ""; var ntplist = ProductionInfo.Production_ParserResult.ntplist; //首先建立矩阵方程X = XA + B,其中X是1 * n的,A是n * n的,B是1 * n的,n为非终结符的总数 var n = ntplist.Length; var ntpmap = new Dictionary <string, int>();//非终结符映射表 var X = new string[n]; for (var i = 0; i < n; i++) { X[i] = ntplist[i].Name; ntpmap[X[i]] = i; } var A = new List <List <string> > [n, n]; var B = new List <string[]> [n]; for (var i = 0; i < n; i++) { for (var j = 0; j < n; j++) { A[i, j] = null; } } for (var i = 0; i < n; i++) { foreach (var item in ntplist[i].Item) { var headerindex = 0; while (headerindex < item.Content.Length && item.Content[headerindex] == "epsilon") { headerindex++; } if (headerindex >= item.Content.Length) { headerindex = item.Content.Length - 1;//全为epsilon,留出一项即可 } if (ntpmap.ContainsKey(item.Content[headerindex])) { //开头为非终结符,表明该项应该属于A矩阵 var line = ntpmap[item.Content[headerindex]]; //第line行第i列表示第i个产生式的第line项 if (A[line, i] == null) { A[line, i] = new List <List <string> >(); } //创建一个新列表,将头非终结符之后的所有的符号全部加入该列表并追加到A矩阵当前项中 var list = new List <string>(); for (var j = headerindex + 1; j < item.Content.Length; j++) { list.Add(item.Content[j]); } //防止程序崩溃的保护措施 if (list.Count == 0) { list.Add("epsilon"); } A[line, i].Add(list); } else { //开头为终结符,表示该项应该属于B矩阵 if (B[i] == null) { B[i] = new List <string[]>(); } B[i].Add(item.Content); } } } //方程转化为X = BZ,Z = I + AZ //将方程转化为产生式序列 var newntplist = new List <NonTerminalProductionInfo>(); var newntpitemprefex = Production_Parser.SysNamePrefix + "Z_"; var nullZ = new HashSet <string>(); //生成Z产生式 for (var i = 0; i < n; i++) { for (var j = 0; j < n; j++) { var newntp = new NonTerminalProductionInfo(); newntp.Name = newntpitemprefex + (i + 1) + "_" + (j + 1); newntp.Item = new List <NonTerminalProductionItemInfo>(); for (var k = 0; k < n; k++) { if (A[i, k] != null) { foreach (var pitem in A[i, k]) { var newcontent = new NonTerminalProductionItemInfo(); newcontent.Content = pitem.ToList(); newcontent.Content.Add(newntpitemprefex + (k + 1) + "_" + (j + 1)); newntp.Item.Add(newcontent); } } } //+ I if (i == j) { newntp.Item.Add(new NonTerminalProductionItemInfo { Content = new string[] { "epsilon" }.ToList() }); } if (newntp.Item.Count == 0) { nullZ.Add(newntp.Name); } else { newntplist.Add(newntp); } } } //移除所有无效的Z产生式 var updated = true; while (updated) { updated = false; for (var i = newntplist.Count - 1; i >= 0; i--) { for (var j = newntplist[i].Item.Count - 1; j >= 0; j--) { var hasunknownitem = false; foreach (var item in newntplist[i].Item[j].Content) { if (nullZ.Contains(item)) { hasunknownitem = true; break; } } if (hasunknownitem) { newntplist[i].Item.RemoveAt(j); updated = true; } } if (newntplist[i].Item.Count == 0) { nullZ.Add(newntplist[i].Name); newntplist.RemoveAt(i); updated = true; } } } //产生式选择 for (var i = 0; i < n; i++) { var newntp = new NonTerminalProductionInfo(); newntp.Name = X[i]; newntp.Item = new List <NonTerminalProductionItemInfo>(); //遍历B矩阵的每一项,与Z矩阵进行相乘操作 var hasnonnull = false; for (var j = 0; j < n; j++) { if (B[j] != null && !nullZ.Contains(newntpitemprefex + (j + 1) + "_" + (i + 1))) { hasnonnull = true; foreach (var pitem in B[j]) { var newcontent = new NonTerminalProductionItemInfo(); newcontent.Content = pitem.ToList(); newcontent.Content.Add(newntpitemprefex + (j + 1) + "_" + (i + 1)); newntp.Item.Add(newcontent); } } } if (!hasnonnull) { ErrorText = "[GrammarCompiler_LL_1]:该文法不是LL(1)文法!在进行左递归消除时,对于非终结符\"" + newntp.Name + "\"而言,B矩阵各项全为null,疑似存在循环引用!\n"; return(false); } newntplist.Add(newntp); } //删除多余产生式,采用从开始符号的引用分析方法 var visited = new Dictionary <string, bool>(); for (var i = 0; i < newntplist.Count; i++) { visited[newntplist[i].Name] = false; ntpmap[newntplist[i].Name] = i; } var queue = new Queue <string>(); queue.Enqueue(StartSymbol); visited[StartSymbol] = true; while (queue.Count > 0) { var curntp = queue.Dequeue(); foreach (var pitem in newntplist[ntpmap[curntp]].Item) { foreach (var item in pitem.Content) { if (visited.ContainsKey(item) && !visited[item]) { visited[item] = true; queue.Enqueue(item); } } } } for (var i = newntplist.Count - 1; i >= 0; i--) { if (!visited[newntplist[i].Name]) { newntplist.RemoveAt(i); } } NewNTPList = newntplist; return(true); }