static Lrfa _ToLrfa(CfgDocument cfg, IProgress <CfgLalr1Progress> progress) { if (null != progress) { progress.Report(new CfgLalr1Progress(CfgLalr1Status.ComputingStates, 0)); } // TODO: this takes a long time sometimes var map = new Dictionary <ICollection <LRItem>, Lrfa>(_LRItemSetComparer.Default); // create an augmented grammar - add rule {start} -> [[StartId]] var start = new CfgRule(cfg.GetAugmentedStartId(cfg.StartSymbol), new string[] { cfg.StartSymbol }); var cl = new HashSet <LRItem>(); cl.Add(new LRItem(start, 0)); _FillLRClosureInPlace(cfg, progress, cl); var lrfa = new Lrfa(true, cl); var items = cl.Count; map.Add(cl, lrfa); var done = false; var oc = 0; while (!done) { done = true; var arr = map.Keys.ToArray(); for (var i = 0; i < arr.Length; ++i) { var itemSet = arr[i]; foreach (var item in itemSet) { var next = item.RightIndex < item.Rule.Right.Count ? item.Rule.Right[item.RightIndex] : null; if (item.RightIndex < item.Rule.Right.Count) { var n = _FillLRMove(cfg, itemSet, next, progress); if (!_ContainsItemSet(map.Keys, n)) { done = false; var npda = new Lrfa(true, n); map.Add(n, npda); items += n.Count; if (null != progress) { progress.Report(new CfgLalr1Progress(CfgLalr1Status.ComputingConfigurations, items)); } } map[itemSet].Transitions[next] = map[n]; } } } if (!done) { oc = map.Count; if (null != progress) { progress.Report(new CfgLalr1Progress(CfgLalr1Status.ComputingStates, oc)); } } } return(lrfa); }
static CfgDocument _ToLRTransitionGrammar(CfgDocument cfg, Lrfa lrfa, IProgress <CfgLalr1Progress> progress) { var result = new CfgDocument(); var closure = new List <Lrfa>(); var itemSets = new List <ICollection <LRItem> >(); lrfa.FillClosure(closure); foreach (var p in closure) { itemSets.Add(p.AcceptSymbol); } _LrtSymbol start = null; int j = 0; foreach (var p in closure) { if (null != progress) { progress.Report(new CfgLalr1Progress(CfgLalr1Status.CreatingLookaheadGrammar, j)); } int si = itemSets.IndexOf(p.AcceptSymbol, _LRItemSetComparer.Default); foreach (var item in p.AcceptSymbol) { if (0 == item.RightIndex) { var next = item.RightIndex < item.Rule.Right.Count ? item.Rule.Right[item.RightIndex] : null; var rule = item.Rule; if (item.RightIndex < item.Rule.Right.Count) { int dst = -1; Lrfa dsts; if (p.Transitions.ContainsKey(rule.Left)) { dsts = p.Transitions[rule.Left]; dst = itemSets.IndexOf(dsts.AcceptSymbol, _LRItemSetComparer.Default); } _LrtSymbol left = new _LrtSymbol(si, rule.Left, dst); if (null == start) { start = left; } var right = new List <string>(); var pc = p; foreach (var sym in rule.Right) { int s1 = itemSets.IndexOf(pc.AcceptSymbol, _LRItemSetComparer.Default); var pt = pc.Transitions[sym]; int s2 = itemSets.IndexOf(pt.AcceptSymbol, _LRItemSetComparer.Default); _LrtSymbol n = new _LrtSymbol(s1, sym, s2); right.Add(n.ToString()); pc = pt; } result.Rules.Add(new CfgRule(left.ToString(), right)); } } } ++j; } result.StartSymbol = start.ToString(); return(result); }