public override IList <IList <string> > ToDisjunctions(EbnfDocument parent, Cfg cfg)
        {
            var _listId = cfg.GetUniqueId("implicitlist");
            IDictionary <string, object> attrs = new Dictionary <string, object>();

            attrs.Add("collapse", true);
            cfg.AttributeSets.Add(_listId, attrs);
            var expr = new EbnfOrExpression(new EbnfOrExpression(new EbnfConcatExpression(Expression, new EbnfRefExpression(_listId)), Expression), null);

            foreach (var nt in expr.ToDisjunctions(parent, cfg))
            {
                CfgRule r = new CfgRule();
                r.Left = _listId;
                foreach (var s in nt)
                {
                    if (1 < r.Right.Count && null == s)
                    {
                        continue;
                    }
                    r.Right.Add(s);
                }
                if (!cfg.Rules.Contains(r))
                {
                    cfg.Rules.Add(r);
                }
            }
            return(new List <IList <string> >(new IList <string>[] { new List <string>(new string[] { _listId }) }));
        }
Exemple #2
0
        public IList <CfgMessage> EliminateFirstFirstConflicts()
        {
            var result = new List <CfgMessage>();

            foreach (var nt in new List <string>(_EnumNonTerminals()))
            {
                var rules  = FillNonTerminalRules(nt);
                var rights = new List <IList <string> >();
                foreach (var rule in rules)
                {
                    rights.Add(rule.Right);
                }
                while (true)
                {
                    var pfx = rights.GetLongestCommonPrefix();
                    if (pfx.IsNullOrEmpty())
                    {
                        break;
                    }
                    // obv first first conflict
                    var nnt = GetTransformId(nt);

                    var suffixes = new List <IList <string> >();
                    foreach (var rule in rules)
                    {
                        if (rule.Right.StartsWith(pfx))
                        {
                            rights.Remove(rule.Right);
                            suffixes.Add(new List <string>(rule.Right.SubRange(pfx.Count)));
                            result.Add(new CfgMessage(CfgErrorLevel.Message, -1, string.Format("Removing rule {0} because it is part of a first-first conflict.", rule)));
                            Rules.Remove(rule);
                        }
                    }

                    var newRule = new CfgRule(nt);
                    newRule.Right.AddRange(pfx);
                    newRule.Right.Add(nnt);
                    result.Add(new CfgMessage(CfgErrorLevel.Message, -1, string.Format("Adding rule {0} to resolve first-first conflict.", newRule)));
                    if (!Rules.Contains(newRule))
                    {
                        Rules.Add(newRule);
                    }
                    foreach (var suffix in suffixes)
                    {
                        newRule = new CfgRule(nnt);
                        newRule.Right.AddRange(suffix);
                        result.Add(new CfgMessage(CfgErrorLevel.Message, -1, string.Format("Adding rule {0} to resolve first-first conflict.", newRule)));
                        if (!Rules.Contains(newRule))
                        {
                            Rules.Add(newRule);
                        }
                    }
                    var attrs = new Dictionary <string, object>();
                    attrs.Add("collapse", true);
                    AttributeSets.Add(nnt, attrs);
                }
            }
            return(result);
        }
Exemple #3
0
        public IList <CfgMessage> EliminateLeftRecursion()
        {
            var result = new List <CfgMessage>();
            var ic     = Rules.Count;

            for (var i = 0; i < ic; ++i)
            {
                var rule = Rules[i];
                if (rule.IsDirectlyLeftRecursive)
                {
                    result.Add(new CfgMessage(CfgErrorLevel.Message, -1, string.Format("Removing rule {0} because it is directly left recursive.", rule)));
                    Rules.Remove(rule);
                    var newId = GetTransformId(rule.Left);

                    var col = new List <string>();
                    var c   = rule.Right.Count;
                    for (var j = 1; j < c; ++j)
                    {
                        col.Add(rule.Right[j]);
                    }
                    col.Add(newId);
                    var d = new Dictionary <string, object>();
                    AttributeSets.Add(newId, d);
                    d.Add("collapse", true);
                    var newRule = new CfgRule(newId);
                    newRule.Right.AddRange(col);
                    result.Add(new CfgMessage(CfgErrorLevel.Message, -1, string.Format("Adding rule {1} to replace rule {0}", rule, newRule)));
                    if (!Rules.Contains(newRule))
                    {
                        Rules.Add(newRule);
                    }
                    var rr = new CfgRule(newId);
                    result.Add(new CfgMessage(CfgErrorLevel.Message, -1, string.Format("Adding rule {1} to replace rule {0}", rule, rr)));
                    if (!Rules.Contains(rr))
                    {
                        Rules.Add(rr);
                    }
                    foreach (var r in Rules)
                    {
                        if (Equals(r.Left, rule.Left))
                        {
                            if (!r.IsDirectlyLeftRecursive)
                            {
                                r.Right.Add(newId);
                            }
                        }
                    }
                }
            }
            return(result);
        }
Exemple #4
0
        /// <summary>
        /// Computes the FOLLOWS sets for the grammar
        /// </summary>
        /// <param name="firsts">The precomputed firsts sets. These will be computed if this is null.</param>
        /// <param name="result">The result to fill. If null, a new dictionary will be created.</param>
        /// <returns>The result, filled with FOLLOWS sets grouped by non-terminal</returns>
        public IDictionary <string, ICollection <string> > FillFollows(IDictionary <string, ICollection <string> > firsts = null, IDictionary <string, ICollection <string> > result = null)
        {
            if (null == result)
            {
                result = new Dictionary <string, ICollection <string> >();
            }
            var done = false;

            if (null == firsts)
            {
                firsts = FillFirsts();
            }
            var ss = StartSymbol;
            // augment the grammar S' -> S #EOS
            CfgRule start = new CfgRule(GetTransformId(ss), ss, "#EOS");

            foreach (var rule in new CfgRule[] { start }.Concat(Rules))
            {
                if (rule.IsNil)
                {
                    ICollection <string> col;
                    if (!result.TryGetValue(rule.Left, out col))
                    {
                        col = new HashSet <string>();
                        result.Add(rule.Left, col);
                    }
                    if (!col.Contains(rule.Left))
                    {
                        col.Add(rule.Left);
                    }
                }
                else
                {
                    var ic = rule.Right.Count;
                    for (var i = 1; i < ic; ++i)
                    {
                        var prev = rule.Right[i - 1];
                        var sym  = rule.Right[i];
                        if (IsNonTerminal(prev))
                        {
                            ICollection <string> col;
                            if (!result.TryGetValue(prev, out col))
                            {
                                col = new HashSet <string>();
                                result.Add(prev, col);
                            }
                            foreach (var s in firsts[sym])
                            {
                                // we'll need the following symbol's follows
                                if (null == s)
                                {
                                    if (!col.Contains(sym))
                                    {
                                        col.Add(sym);
                                    }
                                }
                                else if (!col.Contains(s))
                                {
                                    col.Add(s);
                                }
                            }
                        }
                    }
                    var last = rule.Right[ic - 1];
                    if (IsNonTerminal(last))
                    {
                        ICollection <string> col;
                        if (!result.TryGetValue(last, out col))
                        {
                            col = new HashSet <string>();
                            result.Add(last, col);
                        }
                        if (!col.Contains(rule.Left))
                        {
                            col.Add(rule.Left);
                        }
                    }
                }
            }
            done = false;
            const int LIMIT = 10000;
            var       il    = 0;

            while (!done)
            {
                done = true;
                foreach (var kvp in result)
                {
                    foreach (var s in new List <string>(kvp.Value))
                    {
                        if (IsNonTerminal(s))
                        {
                            kvp.Value.Remove(s);
                            ICollection <string> col;
                            if (result.TryGetValue(s, out col))
                            {
                                foreach (var sss in col)
                                {
                                    if (!kvp.Value.Contains(sss))
                                    {
                                        if (sss != s)
                                        {
                                            kvp.Value.Add(sss);
                                            done = false;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                ++il;
                if (LIMIT < il)
                {
                    throw new CfgException("Loop detected in follows computation - follows limit exceeded.", 16);
                }
            }
            return(result);
        }