Пример #1
0
        public CfgLL1ParseTable ToLLkParseTable()
        {
            // Here we populate the outer dictionary with one non-terminal for each key
            // we populate each inner dictionary with the result terminals and associated
            // rules of the predict tables except in the case where the predict table
            // contains null. In that case, we use the follows to get the terminals and
            // the rule associated with the null predict in order to compute the inner
            // dictionary. The conflict resolution tables are created as needed. Basically
            // they are nested parse tables for additional lookahead resolution.
            // The parser can use these to further resolve conflicts.
            var predict = FillPredict();
            var follows = FillFollows();
            var result  = new CfgLL1ParseTable();

            foreach (var nt in _EnumNonTerminals())
            {
                var d = new Dictionary <string, CfgLL1ParseTableEntry>();
                foreach (var f in predict[nt])
                {
                    if (null != f.Symbol)
                    {
                        CfgLL1ParseTableEntry or;
                        if (d.TryGetValue(f.Symbol, out or))
                        {
                            if (null != or.ConflictTable)
                            {
                            }
                            else if (null != or.Rule)
                            {
                                var pt = new CfgLL1ParseTable();
                                var dd = new Dictionary <string, CfgRule>();

                                throw new CfgException(
                                          string.Format(
                                              "FIRST FIRST conflict between {0} and {1} on {2}",
                                              or.Rule,
                                              f.Rule,
                                              f.Symbol));
                            }
                        }
                        else
                        {
                            or.ConflictTable = null;
                            or.Rule          = f.Rule;
                            d.Add(f.Symbol, or);
                        }
                    }
                    else
                    {
                        var ff = follows[nt];
                        foreach (var fe in ff)
                        {
                            CfgLL1ParseTableEntry or;
                            if (d.TryGetValue(fe, out or))
                            {
                                // we can override conflict handling with the followsConflict
                                // attribute. If specified (first/last/error - error is default) it will choose
                                // the first or last rule respectively.
                                var fc = AttributeSets.GetAttribute(nt, "followsConflict", "error") as string;
                                if ("error" == fc)
                                {
                                    throw new CfgException(
                                              string.Format(
                                                  "FIRST FOLLOWS conflict between {0} and {1} on {2}",
                                                  or.Rule,
                                                  f.Rule,
                                                  fe));
                                }
                                else if ("last" == fc)
                                {
                                    d[fe] = new CfgLL1ParseTableEntry(f.Rule);
                                }
                            }
                            else
                            {
                                d.Add(fe, new CfgLL1ParseTableEntry(f.Rule));
                            }
                        }
                    }
                }

                result.Add(nt, d);
            }
            return(result);
        }
Пример #2
0
        public CfgLL1ParseTable ToLL1ParseTable()
        {
            // Here we populate the outer dictionary with one non-terminal for each key
            // we populate each inner dictionary with the result terminals and associated
            // rules of the predict tables except in the case where the predict table
            // contains null. In that case, we use the follows to get the terminals and
            // the rule associated with the null predict in order to compute the inner
            // dictionary. The conflict resolution tables are always empty for LL(1)
            var predict = FillPredict();
            var follows = FillFollows();
            var exmsgs  = new List <CfgMessage>();
            var result  = new CfgLL1ParseTable();

            foreach (var nt in _EnumNonTerminals())
            {
                var d = new Dictionary <string, CfgLL1ParseTableEntry>();
                foreach (var f in predict[nt])
                {
                    if (null != f.Symbol)
                    {
                        CfgLL1ParseTableEntry re;
                        re.ConflictTable = null;
                        re.Rule          = f.Rule;
                        CfgLL1ParseTableEntry or;
                        if (d.TryGetValue(f.Symbol, out or))
                        {
                            exmsgs.Add(new CfgMessage(CfgErrorLevel.Error, 1,
                                                      string.Format(
                                                          "FIRST FIRST conflict between {0} and {1} on {2}",
                                                          or.Rule,
                                                          f.Rule,
                                                          f.Symbol)));
                        }
                        else
                        {
                            d.Add(f.Symbol, re);
                        }
                    }
                    else
                    {
                        var ff = follows[nt];
                        foreach (var fe in ff)
                        {
                            CfgLL1ParseTableEntry or;
                            if (d.TryGetValue(fe, out or))
                            {
                                // we can override conflict handling with the followsConflict
                                // attribute. If specified (first/last/error - error is default) it will choose
                                // the first or last rule respectively.
                                var fc = AttributeSets.GetAttribute(nt, "followsConflict", "error") as string;
                                if ("error" == fc)
                                {
                                    exmsgs.Add(new CfgMessage(CfgErrorLevel.Error, 2,
                                                              string.Format(
                                                                  "FIRST FOLLOWS conflict between {0} and {1} on {2}",
                                                                  or.Rule,
                                                                  f.Rule,
                                                                  fe)));
                                }
                                else if ("last" == fc)
                                {
                                    d[fe] = new CfgLL1ParseTableEntry(f.Rule);
                                }
                            }
                            else
                            {
                                d.Add(fe, new CfgLL1ParseTableEntry(f.Rule));
                            }
                        }
                    }
                }

                result.Add(nt, d);
            }
            CfgException.ThrowIfErrors(exmsgs);
            return(result);
        }