public static CfgLalr1ParseTable ToLalr1ParseTable(this CfgDocument cfg, IProgress <CfgLalr1Progress> progress = null) { CfgLalr1ParseTable result = null; var msgs = TryToLalr1ParseTable(cfg, progress, out result); CfgException.ThrowIfErrors(msgs); return(result); }
public Lalr1DebugParser(CfgDocument cfg, IEnumerable <Token> tokenizer, CfgLalr1ParseTable parseTable = null) { _cfg = cfg; _PopulateAttrs(); _stack = new Stack <int>(); _tokenEnum = tokenizer.GetEnumerator(); _parseTable = parseTable ?? cfg.ToLalr1ParseTable(); _nodeType = LRNodeType.Initial; }
public static IList <CfgMessage> TryToLalr1ParseTable(this CfgDocument cfg, IProgress <CfgLalr1Progress> progress, out CfgLalr1ParseTable parseTable) { var result = new List <CfgMessage>(); var start = cfg.GetAugmentedStartId(cfg.StartSymbol); var lrfa = _ToLrfa(cfg, progress); var trnsCfg = _ToLRTransitionGrammar(cfg, lrfa, progress); trnsCfg.RebuildCache(); var closure = new List <Lrfa>(); parseTable = new CfgLalr1ParseTable(); var itemSets = new List <ICollection <LRItem> >(); lrfa.FillClosure(closure); var i = 0; foreach (var p in closure) { itemSets.Add(p.AcceptSymbol); parseTable.Add(new Dictionary <string, (int RuleOrStateId, string Left, string[] Right)>()); ++i; } i = 0; foreach (var p in closure) { foreach (var trn in p.Transitions) { var idx = closure.IndexOf(trn.Value); parseTable[i].Add( trn.Key, (idx, null, null) ); } foreach (var item in p.AcceptSymbol) { if (Equals(item.Rule.Left, start) && item.RightIndex == item.Rule.Right.Count) { parseTable[i].Add( "#EOS", (-1, null, null)); break; } } ++i; } var follows = trnsCfg.FillFollows(); // work on our reductions now var map = new Dictionary <CfgRule, ICollection <string> >(_TransitionMergeRuleComparer.Default); foreach (var rule in trnsCfg.Rules) { ICollection <string> f; if (!map.TryGetValue(rule, out f)) { map.Add(rule, follows[rule.Left]); } else { foreach (var o in follows[rule.Left]) { if (!f.Contains(o)) { f.Add(o); } } } } var j = 0; foreach (var mapEntry in map) { if (null != progress) { progress.Report(new CfgLalr1Progress(CfgLalr1Status.ComputingReductions, j)); } var rule = mapEntry.Key; var lr = _LrtSymbol.Parse(rule.Right[rule.Right.Count - 1]); var left = _LrtSymbol.Parse(rule.Left).Id; var right = new List <string>(); foreach (var s in rule.Right) { right.Add(_LrtSymbol.Parse(s).Id); } var newRule = new CfgRule(left, right); if (!Equals(left, start)) { foreach (var f in mapEntry.Value) { // build the rule data var rr = new string[newRule.Right.Count]; for (var ri = 0; ri < rr.Length; ri++) { rr[ri] = newRule.Right[ri]; } var iid = _LrtSymbol.Parse(f).Id; (int RuleOrStateId, string Left, string[] Right)tuple; var rid = cfg.Rules.IndexOf(newRule); var newTuple = (RuleOrStateId : rid, Left : newRule.Left, Right : rr); // this gets rid of duplicate entries which crop up in the table if (!parseTable[lr.To].TryGetValue(iid, out tuple)) { parseTable[lr.To].Add(_LrtSymbol.Parse(f).Id, newTuple); } else { // TODO: Verify this - may need the dragon book if (null == tuple.Right) { var nr = cfg.Rules[rid]; var msg = new CfgMessage(CfgErrorLevel.Warning, -1, string.Format("Shift-Reduce conflict on rule {0}, token {1}", nr, iid), nr.Line, nr.Column, nr.Position); if (!result.Contains(msg)) { result.Add(msg); } } else { if (rid != newTuple.RuleOrStateId) { var nr = cfg.Rules[rid]; var msg = new CfgMessage(CfgErrorLevel.Error, -1, string.Format("Reduce-Reduce conflict on rule {0}, token {1}", nr, iid), nr.Line, nr.Column, nr.Position); if (!result.Contains(msg)) { result.Add(msg); } } } } } } ++j; } return(result); }
public static IList <CfgMessage> TryToLalr1ParseTable(this CfgDocument cfg, out CfgLalr1ParseTable parseTable) => TryToLalr1ParseTable(cfg, null, out parseTable);