Ejemplo n.º 1
0
 public _LR0Item(CfgRule rule, int rightIndex)
 {
     Left      = rule.Left;
     _hashCode = Left.GetHashCode();
     if (!rule.IsNil)
     {
         Right = new string[rule.Right.Count];
         rule.Right.CopyTo(Right, 0);
         for (var i = 0; i < Right.Length; i++)
         {
             var right = rule.Right[i];
             _hashCode ^= right.GetHashCode();
             Right[i]   = right;
         }
     }
     else
     {
         Right = new string[] { }
     };
     _hashCode ^= rightIndex;
     RightIndex = rightIndex;
 }
Ejemplo n.º 2
0
        public IList <CfgMessage> TryToLR1ParseTable(out CfgLR1ParseTable parseTable, LRTableKind kind = LRTableKind.Lalr1, IProgress <CfgLRProgress> progress = null)
        {
            var result  = new List <CfgMessage>();
            var start   = GetAugmentedStartId(StartSymbol);
            var lrfa    = _ToLRFA(progress);
            var trnsCfg = _LRFAToLRExtendedGrammar(lrfa, progress);

            trnsCfg.RebuildCache();
            var closure = new List <_LRFA>();

            parseTable = new CfgLR1ParseTable();

            var itemSets = new List <_LR0ItemSet>();

            lrfa.FillClosure(closure);
            var i = 0;

            foreach (var p in closure)
            {
                itemSets.Add(p.Accept);
                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.Accept.Items)
                {
                    if (item.IsEnd && Equals(item.Left, start))
                    {
                        parseTable[i].Add(
                            "#EOS",
                            (-1, null, null));
                    }
                }
                ++i;
            }
            var follows = trnsCfg.FillFollows();
            // work on our reductions now
            // each rule has a follows set associated with it
            var map = new Dictionary <CfgRule, ICollection <string> >(_Lalr1MergeRuleComparer.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 CfgLRProgress(CfgLRStatus.ComputingReductions, j));
                }
                var rule  = mapEntry.Key;
                var lr    = rule.IsNil?_LRExtendedSymbol.Parse(rule.Left):_LRExtendedSymbol.Parse(rule.Right[rule.Right.Count - 1]);
                var left  = _LRExtendedSymbol.Parse(rule.Left).Id;
                var right = new List <string>();
                foreach (var s in rule.Right)
                {
                    right.Add(_LRExtendedSymbol.Parse(s).Id);
                }
                var newRule = new CfgRule(left, right);
                if (newRule.IsNil)
                {
                    lr.To = lr.From;
                }
                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 = _LRExtendedSymbol.Parse(f).Id;
                        (int RuleOrStateId, string Left, string[] Right)tuple;
                        var rid      = 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(iid,
                                                  newTuple);
                        }
                        else
                        {
                            if (null == tuple.Right)
                            {
                                var nr  = Rules[rid];
                                var msg = new CfgMessage(ErrorLevel.Warning, CfgErrors.ShiftReduceConflict, string.Format("Shift-Reduce conflict on rule {0}, token {1}", nr, iid), nr.Line, nr.Column, nr.Position, FileOrUrl);
                                if (!result.Contains(msg))
                                {
                                    result.Add(msg);
                                }
                            }
                            else
                            {
                                if (rid != tuple.RuleOrStateId)
                                {
                                    var nr  = Rules[rid];
                                    var msg = new CfgMessage(ErrorLevel.Error, CfgErrors.ReduceReduceConflict, string.Format("Reduce-Reduce conflict on rule {0}, token {1}", nr, iid), nr.Line, nr.Column, nr.Position, FileOrUrl);
                                    if (!result.Contains(msg))
                                    {
                                        result.Add(msg);
                                    }
                                }
                            }
                        }
                    }
                }
                ++j;
            }
            return(result);
        }
Ejemplo n.º 3
0
        public IList <CfgMessage> TryToGlrParseTable(out CfgGlrParseTable parseTable, LRTableKind kind = LRTableKind.Lalr1, IProgress <CfgLRProgress> progress = null)
        {
            var result  = new List <CfgMessage>();
            var start   = GetAugmentedStartId(StartSymbol);
            var lrfa    = _ToLRFA(progress);
            var trnsCfg = _LRFAToLRExtendedGrammar(lrfa, progress);

            trnsCfg.RebuildCache();
            var closure = new List <_LRFA>();

            parseTable = new CfgGlrParseTable();

            var itemSets = new List <_LR0ItemSet>();

            lrfa.FillClosure(closure);
            var i = 0;

            foreach (var p in closure)
            {
                itemSets.Add(p.Accept);
                parseTable.Add(new Dictionary <string, ICollection <(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);
                    ICollection <(int RuleOrStateId, string Left, string[] Right)> pcol;
                    if (!parseTable[i].TryGetValue(trn.Key, out pcol))
                    {
                        pcol = new List <(int RuleOrStateId, string Left, string[] Right)>();
                        parseTable[i].Add(trn.Key, pcol);
                    }
                    pcol.Add(
                        (idx, null, null)
                        );
                }
                foreach (var item in p.Accept.Items)
                {
                    if (item.IsEnd && Equals(item.Left, start))
                    {
                        ICollection <(int RuleOrStateId, string Left, string[] Right)> pcol;
                        if (!parseTable[i].TryGetValue("#EOS", out pcol))
                        {
                            pcol = new List <(int RuleOrStateId, string Left, string[] Right)>();
                            parseTable[i].Add("#EOS", pcol);
                        }

                        pcol.Add(
                            (-1, null, null));
                        //break;
                    }
                }
                ++i;
            }
            var follows = trnsCfg.FillFollows();
            // work on our reductions now
            // each rule has a follows set associated with it
            var map = new Dictionary <CfgRule, ICollection <string> >(_Lalr1MergeRuleComparer.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 CfgLRProgress(CfgLRStatus.ComputingReductions, j));
                }
                var rule  = mapEntry.Key;
                var lr    = rule.IsNil ? _LRExtendedSymbol.Parse(rule.Left) : _LRExtendedSymbol.Parse(rule.Right[rule.Right.Count - 1]);
                var left  = _LRExtendedSymbol.Parse(rule.Left).Id;
                var right = new List <string>();
                foreach (var s in rule.Right)
                {
                    right.Add(_LRExtendedSymbol.Parse(s).Id);
                }
                var newRule = new CfgRule(left, right);
                if (newRule.IsNil)
                {
                    lr.To = lr.From;
                }
                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      = _LRExtendedSymbol.Parse(f).Id;
                        var rid      = Rules.IndexOf(newRule);
                        var newTuple = (RuleOrStateId : rid, Left : newRule.Left, Right : rr);
                        // this handles duplicate entries which crop up in the table
                        ICollection <(int RuleOrStateId, string Left, string[] Right)> pcol;
                        if (!parseTable[lr.To].TryGetValue(iid, out pcol))
                        {
                            pcol = new List <(int RuleOrStateId, string Left, string[] Right)>();
                            parseTable[lr.To].Add(iid, pcol);
                        }
                        var found = false;
                        foreach (var t in pcol)
                        {
                            if (t.Left == newTuple.Left && t.RuleOrStateId == newTuple.RuleOrStateId)
                            {
                                if ((t.Right == null && newTuple.Right == null) ||
                                    t.Right?.Length == newTuple.Right?.Length)
                                {
                                    if (t.Right != null)
                                    {
                                        found = true;
                                        for (var ii = 0; ii < t.Right.Length; ++ii)
                                        {
                                            if (t.Right[ii] != newTuple.Right[ii])
                                            {
                                                found = false;
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                            if (found)
                            {
                                break;
                            }
                        }
                        if (!found)
                        {
                            pcol.Add(newTuple);
                        }
                    }
                }
                ++j;
            }
            return(result);
        }
Ejemplo n.º 4
0
        _LRFA _ToLRFA(IProgress <CfgLRProgress> progress)
        {
            if (null != progress)
            {
                progress.Report(new CfgLRProgress(CfgLRStatus.ComputingStates, 0));
            }
            var moves = new Dictionary <KeyValuePair <_LR0ItemSet, string>, _LR0ItemSet>();
            // TODO: this takes a long time sometimes
            var map = new Dictionary <_LR0ItemSet, _LRFA>();
            // create an augmented grammar - add rule {start} -> [[StartId]]
            var ss    = StartSymbol;
            var start = new CfgRule(GetAugmentedStartId(ss), new string[] { ss });
            var cl    = new _LR0ItemSet();

            cl.AddItem(new _LR0Item(start, 0));

            _FillLRClosureInPlace(progress, cl);
            var lrfa = new _LRFA();

            lrfa.Accept = cl;
            var items = cl.Items.Count;

            map.Add(cl, lrfa);
            var done = false;
            int oc;

            while (!done)
            {
                done = true;
                var arr = new _LR0ItemSet[map.Keys.Count];
                map.Keys.CopyTo(arr, 0);
                for (var i = 0; i < arr.Length; ++i)
                {
                    var itemSet = arr[i];
                    foreach (var item in itemSet.Items)
                    {
                        var next = item.Next;
                        if (!item.IsEnd)
                        {
                            _LR0ItemSet n;
                            var         key = new KeyValuePair <_LR0ItemSet, string>(itemSet, next);
                            if (!moves.TryGetValue(key, out n))
                            {
                                n = _FillLRMove(itemSet, next, progress);
                                moves.Add(key, n);
                            }
                            if (!map.ContainsKey(n))
                            {
                                done = false;

                                var npda = new _LRFA();
                                npda.Accept = n;
                                map.Add(n, npda);
                                items += n.Items.Count;
                                if (null != progress)
                                {
                                    progress.Report(new CfgLRProgress(CfgLRStatus.ComputingConfigurations, items));
                                }
                            }

                            map[itemSet].Transitions[next] = map[n];
                        }
                    }
                }
                if (!done)
                {
                    oc = map.Count;
                    if (null != progress)
                    {
                        progress.Report(new CfgLRProgress(CfgLRStatus.ComputingStates, oc));
                    }
                }
            }
            return(lrfa);
        }