コード例 #1
0
        private void Predict(ail.net.parser.EarleyParser.Chart xi_chart)
        {
            // PREDICTOR:
            //  if [A -> ... • B ..., j] is in S(i), add [B -> • a(lpha), i] to S(i) for all rules B -> a(lpha)
            // no args assertion!!!
            if (xi_chart != (object)null)
            {
                for (int i = xi_chart.PredictedK; i < xi_chart.PredictorItems.Count; i++, xi_chart.PredictedK++)
                {
                    ail.net.parser.EarleyParser.Item item = (ail.net.parser.EarleyParser.Item)xi_chart.PredictorItems[i];

                    ail.net.parser.GrammarSymbol symbol = (ail.net.parser.GrammarSymbol)item.CoreItem.Rule.Rhs[item.CoreItem.Dot]; // item.CoreItem.Dot is inside rhs.count

                    if (symbol.IsNonTerminal() && !PredictedNonTerminals[symbol.Id])
                    {
                        foreach (ail.net.parser.EarleyParser.CoreItem core_item in (ArrayList)PredictTable[symbol.Id])
                        {
                            AddItem(core_item,
                                    xi_chart,
                                    xi_chart,
                                    null,
                                    ail.net.parser.EarleyParser.EFlags.ePredictor,
                                    GetErrorCost(item),
                                    Charts.Count == 1); // only check for initial chart, because items were introduced
                                                        // by pseudo-prediction in BuildInitialSet
                        }

                        PredictedNonTerminals[symbol.Id] = true; // marked as predicted
                    }
                }
            }
        }
コード例 #2
0
        public StringBuilder DecorateTreeVisitor(int xi_level, ail.net.parser.AstNode xi_ast_node)
        {
            ail.net.framework.Assert.NonNullReference(xi_ast_node, "xi_ast_node");

            StringBuilder result = new StringBuilder();

            for (ail.net.parser.AstNode node = xi_ast_node; node != (object)null; node = node.Brother)
            {
                ail.net.parser.GrammarSymbol symbol = (ail.net.parser.GrammarSymbol)GrammarPool.Instance.Pool[(int)node.Token.Type];

                if (symbol != (object)null)
                {
                    for (int i = 0; i < xi_level; i++)
                    {
                        result.Append("    ");
                    }

                    result.Append(symbol.Name);
                    result.Append(Environment.NewLine);
                }

                if (node.Child != (object)null)
                {
                    result.Append(DecorateTreeVisitor(xi_level + 1, node.Child));
                }
            }

            return(result);
        }
コード例 #3
0
        private ail.net.parser.EarleyParser.Chart Scan(ail.net.parser.EarleyParser.Chart xi_chart)
        {
            // SCANNER:
            //  if [A -> ... • a ..., j] is in S(i) and a = x(i)+1, add [A -> ... a • ..., j] to S(i+1)
            // no args assertion!!!
            ail.net.parser.EarleyParser.Chart result = null;

            if (xi_chart != (object)null)
            {
                for (int i = 0; i < xi_chart.ScannerItems.Count; i++)
                {
                    ail.net.parser.EarleyParser.Item item = (ail.net.parser.EarleyParser.Item)xi_chart.ScannerItems[i];

                    ail.net.parser.GrammarSymbol symbol = (ail.net.parser.GrammarSymbol)item.CoreItem.Rule.Rhs[item.CoreItem.Dot]; // item.CoreItem.Dot is inside rhs.count

                    if (symbol.Id == Lexer.Token.Type)
                    {
                        if (result == (object)null)
                        {
                            result = AddChart();
                        }

                        AddItem((ail.net.parser.EarleyParser.CoreItem)CoreItemTable[item.CoreItem.Id + 1],
                                item.OriginalChart,
                                result,
                                item,
                                ail.net.parser.EarleyParser.EFlags.eScanner,
                                GetErrorCost(item),
                                true);
                    }
                }
            }

            return(result);
        }
コード例 #4
0
        private void PopulatePredictTable()
        {
            ail.net.framework.Assert.Condition(Grammar.Rules.Count > 0, "ail.net.parser.EarleyParser.PopulatePredictTable: Grammar.Rules.Count > 0");

            PredictTableAttr = new Hashtable();

            foreach (ail.net.parser.GrammarSymbol symbol in GrammarPool.Instance.Pool.Values)
            {
                if (symbol.IsNonTerminal())
                {
                    ArrayList list = new ArrayList();

                    PredictTable[symbol.Id] = list;

                    for (int i = 0; i < CoreItemTable.Count; i++)
                    {
                        ail.net.parser.GrammarRule   rule     = ((ail.net.parser.EarleyParser.CoreItem)CoreItemTable[i]).Rule;
                        ail.net.parser.GrammarSymbol l_symbol = (ail.net.parser.GrammarSymbol)rule.Lhs[0];
                        int dot = ((ail.net.parser.EarleyParser.CoreItem)CoreItemTable[i]).Dot;

                        if (l_symbol.Id == symbol.Id && dot == 0)
                        {
                            list.Add(CoreItemTable[i]);
                        }
                    }
                }
            }

            PredictedNonTerminalsAttr         = new bool[Lexer.Token.GetTokenSize()];
            PredictedNonTerminalsZeroizerAttr = new bool[Lexer.Token.GetTokenSize()];
        }
コード例 #5
0
        public ail.net.parser.GrammarSymbol AddSymbol(int xi_symbol_id, ail.net.parser.GrammarSymbol.EType xi_type, string xi_name)
        {
            ail.net.parser.GrammarSymbol result = (ail.net.parser.GrammarSymbol)PoolAttr[xi_symbol_id];

            if (result == (object)null)
            {
                result = new ail.net.parser.GrammarSymbol();

                result.Id   = xi_symbol_id;
                result.Type = xi_type;
                result.Name = xi_name;

                PoolAttr[xi_symbol_id] = result;

                if (result.IsNonTerminal())
                {
                    NonTerminalCountAttr++;
                }
                else if (result.IsTerminal())
                {
                    TerminalCountAttr++;
                }
            }

            ail.net.framework.Assert.NonNullReference(result, "result");

            result.AddRef();

            return(result);
        }
コード例 #6
0
 public ail.net.parser.GrammarSymbol this [int xi_symbol_id]
 {
     get
     {
         ail.net.parser.GrammarSymbol result = (ail.net.parser.GrammarSymbol)PoolAttr[xi_symbol_id];
         ail.net.framework.Assert.NonNullReference(result, "result");
         return(result);
     }
 }
コード例 #7
0
        public void BuildNullabilitySet()
        {
            // The set of nullable non-terminals can be computed by the following algorithm:
            //  (a) Set "nullable" equal to the set of non-terminals appearing on the left side
            //      of productions of the form N -> e
            //  (b) Until doing so adds no new non-terminals to "nullable", examine each production
            //      in the grammar adding to "nullable" all left-hand-sides of productions whose
            //      right-hand-side consist entirely of symbols in "nullable"
            // a
            foreach (ail.net.parser.GrammarRule rule in RulesAttr)
            {
                if (rule.IsEmptyRule())
                {
                    ((ail.net.parser.GrammarSymbol)rule.Lhs[0]).Nullable = true;
                }
            }

            // b
            for (;;)
            {
                bool changed = false;

                foreach (ail.net.parser.GrammarRule rule in RulesAttr)
                {
                    ail.net.parser.GrammarSymbol l_symbol = (ail.net.parser.GrammarSymbol)rule.Lhs[0];

                    if (!l_symbol.Nullable)
                    {
                        bool nullable = true;

                        foreach (ail.net.parser.GrammarSymbol rhs_symbol in rule.Rhs)
                        {
                            if (!rhs_symbol.Nullable)
                            {
                                nullable = false;
                                break;
                            }
                        }

                        if (nullable)
                        {
                            l_symbol.Nullable = true;
                            changed           = true;
                        }
                    }
                }

                if (!changed)
                {
                    break;
                }
            }
        }
コード例 #8
0
        private void Complete(ail.net.parser.EarleyParser.Chart xi_chart)
        {
            // COMPLETER:
            //  if [A -> ... •, j] is in S(i), add [B -> ... A • ..., k] to S(i) for all items [B -> ... • A ..., k] in S(j)
            // no args assertion!!!
            if (xi_chart != (object)null)
            {
                for (int i = xi_chart.CompletedK; i < xi_chart.CompleterItems.Count; i++, xi_chart.CompletedK++)
                {
                    ail.net.parser.EarleyParser.Item completer_item = (ail.net.parser.EarleyParser.Item)xi_chart.CompleterItems[i];

                    ail.net.parser.GrammarSymbol l_symbol = (ail.net.parser.GrammarSymbol)completer_item.CoreItem.Rule.Lhs[0];

                    ail.net.parser.EarleyParser.Chart chart = completer_item.OriginalChart;

                    for (int k = 0; k < chart.PredictorItems.Count; k++)
                    {
                        ail.net.parser.EarleyParser.Item preditor_item = (ail.net.parser.EarleyParser.Item)chart.PredictorItems[k];

                        ail.net.parser.GrammarSymbol r_symbol = (ail.net.parser.GrammarSymbol)preditor_item.CoreItem.Rule.Rhs[preditor_item.CoreItem.Dot]; // preditor_item.CoreItem.Dot is inside rhs.count

                        if (r_symbol.Id == l_symbol.Id)
                        {
                            ail.net.parser.EarleyParser.Item item = AddItem((ail.net.parser.EarleyParser.CoreItem)CoreItemTable[preditor_item.CoreItem.Id + 1],
                                                                            preditor_item.OriginalChart,
                                                                            xi_chart,
                                                                            preditor_item,
                                                                            ail.net.parser.EarleyParser.EFlags.eCompleter,
                                                                            GetErrorCost(preditor_item),
                                                                            true);
                            SetRptr(item, completer_item);

                            // if dot is before non-terminal and that non-terminal is nullable
                            // also add item with dot after that non-terminal
                            while (item.CoreItem.Dot < item.CoreItem.Rule.Rhs.Count &&
                                   ((ail.net.parser.GrammarSymbol)item.CoreItem.Rule.Rhs[item.CoreItem.Dot]).Nullable)
                            {
                                item = AddItem((ail.net.parser.EarleyParser.CoreItem)CoreItemTable[item.CoreItem.Id + 1],
                                               item.OriginalChart,
                                               xi_chart,
                                               item,
                                               ail.net.parser.EarleyParser.EFlags.eCompleter,
                                               GetErrorCost(item),
                                               true);
                                SetRptr(item, completer_item);
                            }
                        }
                    }
                }
            }
        }
コード例 #9
0
        public ail.net.parser.GrammarSymbol AddRhsSymbol(int xi_symbol_id, ail.net.parser.GrammarSymbol.EType xi_type, string xi_name)
        {
            ail.net.parser.GrammarSymbol result = GrammarPool.Instance.AddSymbol(xi_symbol_id, xi_type, xi_name);

            RhsAttr.Add(result);

            if (result.IsNonTerminal())
            {
                RhsNonTerminalCountAttr++;
            }
            else if (result.IsTerminal())
            {
                RhsTerminalCountAttr++;
            }

            return(result);
        }
コード例 #10
0
        private bool IsRecognizedItem(ail.net.parser.EarleyParser.Item xi_item)
        {
            ail.net.framework.Assert.NonNullReference(xi_item, "xi_item");

            bool result = false;

            if (xi_item.CoreItem.Rule.Lhs.Count > 0 && xi_item.OriginalChart != (object)null)
            {
                ail.net.parser.GrammarSymbol lhs_symbol = (ail.net.parser.GrammarSymbol)xi_item.CoreItem.Rule.Lhs[0];

                result = xi_item.CoreItem.Dot == xi_item.CoreItem.Rule.Rhs.Count && // dot at the end
                         lhs_symbol.Id == Grammar.StartSymbolId &&
                         xi_item.OriginalChart.Id == 0;
            }

            return(result);
        }
コード例 #11
0
            public int Compare(object xi_s1, object xi_s2)
            {
                ail.net.parser.GrammarSymbol s1 = (ail.net.parser.GrammarSymbol)xi_s1;
                ail.net.parser.GrammarSymbol s2 = (ail.net.parser.GrammarSymbol)xi_s2;

                int result = s1.NameAttr == s2.NameAttr ? 1 : 0;

                if ((int)s1.NameAttr[0] < (int)s2.NameAttr[0])
                {
                    result = -1;
                }
                else if ((int)s1.NameAttr[0] > (int)s2.NameAttr[0])
                {
                    result = 1;
                }

                return(result);
            }
コード例 #12
0
            public int Compare(object xi_s1, object xi_s2)
            {
                ail.net.parser.GrammarSymbol s1 = (ail.net.parser.GrammarSymbol)xi_s1;
                ail.net.parser.GrammarSymbol s2 = (ail.net.parser.GrammarSymbol)xi_s2;

                int result = 0;

                if (s1.IdAttr < s2.IdAttr)
                {
                    result = -1;
                }
                else if (s1.IdAttr > s2.IdAttr)
                {
                    result = 1;
                }

                return(result);
            }
コード例 #13
0
            public int Compare(object xi_i1, object xi_i2)
            {
                ail.net.parser.GrammarSymbol i1 = (ail.net.parser.GrammarSymbol)xi_i1;
                ail.net.parser.GrammarSymbol i2 = (ail.net.parser.GrammarSymbol)xi_i2;

                int result = 0;

                if (i1.Id < i2.Id)
                {
                    result = -1;
                }
                else if (i1.Id > i2.Id)
                {
                    result = 1;
                }

                return(result);
            }
コード例 #14
0
        public void RemoveSymbol(int xi_symbol_id)
        {
            ail.net.parser.GrammarSymbol symbol = (ail.net.parser.GrammarSymbol)PoolAttr[xi_symbol_id];

            if (symbol != (object)null && symbol.Release() == 0)
            {
                if (symbol.IsNonTerminal())
                {
                    NonTerminalCountAttr--;
                }
                else if (symbol.IsTerminal())
                {
                    TerminalCountAttr--;
                }

                PoolAttr.Remove(symbol.Id);
            }
        }
コード例 #15
0
        public ArrayList BuildEFFirstKSet(ArrayList xi_symbols, int xi_k)
        {
            // Let's X belongs to N U T. EFFk(X a(lpha)) = EFFk(X) (+)k FIRSTk(a(lpha)).
            ail.net.framework.Assert.NonNullReference(xi_symbols, "xi_symbols");

            ArrayList result = null;

            ail.net.parser.GrammarSymbol x = (ail.net.parser.GrammarSymbol)xi_symbols[0];

            ArrayList alpha = new ArrayList(xi_symbols.Count - 1); // reserve

            for (int i = 1; i < xi_symbols.Count; i++)             // the first is 'x'
            {
                alpha.Add(xi_symbols[i]);
            }

            ArrayList x_eff       = ((ail.net.parser.GrammarSymbol)ail.net.parser.GrammarPool.Instance.Pool[x.Id]).EFFirstSet;
            ArrayList alpha_first = BuildFirstKSet(alpha);

            result = OperatorInfixK(x_eff, alpha_first, xi_k);

            return(result);
        }
コード例 #16
0
        private void BuildAstLevel(ail.net.parser.EarleyParser.Item xi_item, ail.net.parser.AstNode xi_root_node)
        {
            ail.net.framework.Assert.NonNullReference(xi_item, "xi_item");
            ail.net.framework.Assert.NonNullReference(xi_root_node, "xi_root_node");

            // populate a rhs stack with items of the current level
            Stack rhs_stack = new Stack();

            PopulateRhsStack(rhs_stack, xi_item);

            // processing all nodes(items) of the level
            while (rhs_stack.Count > 0)
            {
                ail.net.parser.EarleyParser.Item curr_item = (ail.net.parser.EarleyParser.Item)rhs_stack.Pop();

                ail.net.parser.GrammarSymbol symbol = (ail.net.parser.GrammarSymbol)curr_item.CoreItem.Rule.Rhs[curr_item.CoreItem.Dot - 1]; // 'dot-1', because we pushed  items with 'dot' > 0

                if (symbol.IsTerminal())
                {
                    // handle terminal
                    Semantics.HandleTerminal(xi_root_node, curr_item.MasterChart.Token);
                }
                else if (symbol.IsNonTerminal())
                {
                    // handle non-terminal
                    if (curr_item.Rptrs.Count <= 1)
                    {
                        // r-ptr has exactly one element
                        ail.net.framework.Assert.Condition(curr_item.Rptrs.Count == 1,
                                                           "ail.net.parser.EarleyParser.BuildAstLevel: curr_item.Rptrs.Count == 1");

                        ail.net.parser.EarleyParser.Item r_ptr_item = (ail.net.parser.EarleyParser.Item)curr_item.Rptrs[0];

                        ail.net.parser.AstNode new_node = Semantics.HandleNonTerminalBefore(xi_root_node, r_ptr_item);

                        if (new_node != (object)null)
                        {
                            r_ptr_item.Flags |= (uint)ail.net.parser.EarleyParser.EFlags.eMarked;

                            BuildAstLevel(r_ptr_item, new_node);

                            r_ptr_item.Flags &= ~(uint)ail.net.parser.EarleyParser.EFlags.eMarked;
                        }

                        Semantics.HandleNonTerminalAfter(xi_root_node, r_ptr_item);
                    }
                    else
                    {
                        // r-ptr has more than one elements, ambiguity
                        foreach (ail.net.parser.EarleyParser.Item r_ptr_item in curr_item.Rptrs.Values)
                        {
                            if ((r_ptr_item.Flags & (uint)ail.net.parser.EarleyParser.EFlags.eMarked) == 0)
                            {
                                ail.net.parser.AstNode new_node = Semantics.HandleNonTerminalBefore(xi_root_node, r_ptr_item);

                                if (new_node != (object)null)
                                {
                                    r_ptr_item.Flags |= (uint)ail.net.parser.EarleyParser.EFlags.eMarked;

                                    BuildAstLevel(r_ptr_item, new_node);

                                    r_ptr_item.Flags &= ~(uint)ail.net.parser.EarleyParser.EFlags.eMarked;

                                    Semantics.HandleNonTerminalAfter(xi_root_node, r_ptr_item);

                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
コード例 #17
0
        public void BuildFirstKSet(int xi_k)
        {
            // builds FIRSTk and EFFk sets for the given grammar
            // Sudkump p. 498
            //  1. for each a belongs to T do F'(a) = {a}
            //  2. for each A belongs to N do F(A) = {e(psilon)} if A is nullable or empty otherwise
            //  3. repeat
            //      3.1 for each A belongs to N do F'(A) = F(A)
            //      3.2 for each rule A -> w = u1u2...un with n > 0 do
            //              F(A) = F(A) U TRUNKk(F'(u1)F'(u2)...F'(un))
            //          until F(A) = F'(A) for all A belongs to N
            //  4. FIRSTk(A) = F(A)
            // FIRST set is list of lists for every non-terminal in grammar, size of "lists" is K
            //    ( )
            //     | \
            //     |   ---
            //     |      |
            // (0,1..K) (0,1..K)
            //
            // Opredelim mnozhestvo EFFk(x), sostoyashee iz vseh elementov mnozhestva FIRSTk(x),
            // pri vivode kotorih neterminal na levom konce x (esli on est') ne zamenyaetsya na pustuu zepochku
            //
            // The epsilon-free first k derived symbols, EFFk(), are found by computing FIRST as above,
            // but tagging all symbols which are derived using epsilon productions of the form,
            // as non-epsilon free, and keeping only the epsilon-free derived terminals.
            //?? ail.net.framework.Assert.Condition(xi_k > 0, "ail.net.parser.Grammar.BuildFirstSet: xi_k > 0");

            // 1. for each a belongs to T do F'(a) = {a}
            // 2. for each A belongs to N do F(A) = {e(psilon)} if A is nullable or empty otherwise
            foreach (ail.net.parser.GrammarSymbol symbol in ail.net.parser.GrammarPool.Instance.Pool.Values)
            {
                if (symbol.IsTerminal())
                {
                    ArrayList e = new ArrayList();
                    e.Add(symbol.Id);
                    symbol.FirstSet.Add(e);

                    e = new ArrayList();
                    e.Add(symbol.Id);
                    symbol.EFFirstSet.Add(e);
                }
                else
                {
                    if (symbol.Nullable)
                    {
                        ArrayList e = new ArrayList();
                        e.Add((int)ail.net.parser.Token.EType.eEpsilon);
                        symbol.FirstSet.Add(e);
                    }
                }
            }

            // 3. repeat
            for (;;)
            {
                bool changed = false; // fixed point

                foreach (ail.net.parser.GrammarRule rule in Rules)
                {
                    // non-terminal work with
                    ail.net.parser.GrammarSymbol non_terminal = (ail.net.parser.GrammarSymbol)rule.Lhs[0];

                    int count = non_terminal.FirstSet.Count;

                    // check if we have any empty sets
                    bool has_empty_sets = false;

                    foreach (ail.net.parser.GrammarSymbol symbol in rule.Rhs)
                    {
                        if (symbol.FirstSet.Count == 0)
                        {
                            has_empty_sets = true;
                            break;
                        }
                    }

                    if (has_empty_sets)
                    {
                        // concatanation of the empty set with any set yields the empty set
                        continue;
                    }

                    // 3.2 for each rule A -> w = u1u2...un with n > 0 do
                    //          F(A) = F(A) U TRUNKk(F'(u1)F'(u2)...F'(un))
                    //     until F(A) = F'(A) for all A belongs to N
                    ArrayList entry     = new ArrayList();
                    ArrayList eff_entry = new ArrayList();

                    for (int i = rule.Rhs.Count - 1; i >= 0; i--) // as operator (+) is associative
                    {                                             // it can be applied from back to the front
                        // (+) ... (+)
                        entry = OperatorInfixK(((ail.net.parser.GrammarSymbol)rule.Rhs[i]).FirstSet, entry, xi_k);

                        if (!rule.IsEmptyRule())
                        {
                            eff_entry = OperatorInfixK(((ail.net.parser.GrammarSymbol)rule.Rhs[i]).EFFirstSet, eff_entry, xi_k);
                        }
                    }

                    // check existence
                    if (entry != null && entry.Count > 0)
                    {
                        foreach (ArrayList subset in entry)
                        {
                            if (!HasEntry(non_terminal.FirstSet, subset))
                            {
                                non_terminal.FirstSet.Add(subset);
                            }
                        }
                    }

                    if (eff_entry != (object)null && eff_entry.Count > 0)
                    {
                        foreach (ArrayList subset in eff_entry)
                        {
                            if (!HasEntry(non_terminal.EFFirstSet, subset))
                            {
                                non_terminal.EFFirstSet.Add(subset);
                            }
                        }
                    }

                    changed = changed ? changed : count != non_terminal.FirstSet.Count;
                }

                if (!changed)
                {
                    break;
                }
            }
        }
コード例 #18
0
        public void BuildFollowSet()
        {
            // go through the rules and for each rule we look at each non-terminal on the righthand
            // side. For example, we may have a rule X -> ... ABC ..., and let A be a non-terminal.
            // Calculate FIRST(BC...) and add all elements from this set, except 'e' to FOLLOW(A). If
            // 'e' is in FIRST(BC...), then we add all elements from FOLLOW(X) to FOLLOW(A). The
            // process is repeated until there are no more changes to the table for FOLLOW.
            //
            // The computation of Follow(A) depends of the First sets defined earlier. If B -> a(lpha)Ab(eta)
            // then Follow(A) must contains First(b(eta)). If 'e' belongs to First(b(eta)) (i.e., b(eta) is nullable),
            // or if b(eta) is empty, then Follow(A) must also contain Follow(B).
            ail.net.parser.GrammarSymbol symbol = (ail.net.parser.GrammarSymbol)ail.net.parser.GrammarPool.Instance.Pool[StartSymbolIdAttr];

            symbol.FollowSet.Add((int)ail.net.parser.Token.EType.eEpsilon);

            bool changed;

            for (;;)
            {
                changed = false;

                foreach (ail.net.parser.GrammarRule rule in RulesAttr)
                {
                    ail.net.parser.GrammarSymbol l_symbol = (ail.net.parser.GrammarSymbol)rule.Lhs[0];

                    for (int k = 0, m = rule.Rhs.Count; k < m; k++)
                    {
                        ail.net.parser.GrammarSymbol r_symbol = (ail.net.parser.GrammarSymbol)rule.Rhs[k];

                        if (r_symbol.IsNonTerminal())
                        {
                            int count = r_symbol.FollowSet.Count;

                            ArrayList first_set = new ArrayList();

                            if (k < m - 1)
                            {
                                first_set.Add(rule.Rhs[k + 1]); // temporary storage
                                first_set = BuildFirstSet(first_set);
                            }

                            for (int i = 0, n = first_set.Count; i < n; i++)
                            {
                                if ((int)first_set[i] != (int)ail.net.parser.Token.EType.eEpsilon && !r_symbol.FollowSet.Contains(first_set[i]))
                                {
                                    r_symbol.FollowSet.Add(first_set[i]);
                                }
                            }

                            if (k == m - 1 || first_set.Contains(ail.net.parser.Token.EType.eEpsilon))
                            {
                                for (int i = 0, n = l_symbol.FollowSet.Count; i < n; i++)
                                {
                                    if (!r_symbol.FollowSet.Contains(l_symbol.FollowSet[i]))
                                    {
                                        r_symbol.FollowSet.Add(l_symbol.FollowSet[i]);
                                    }
                                }
                            }

                            changed = changed ? changed : count != r_symbol.FollowSet.Count;
                        }
                    }
                }

                if (!changed)
                {
                    break;
                }
            }
        }
コード例 #19
0
        public void BuildFollowKSet(int xi_k)
        {
            // Sudkump p. 501
            //  1. FL(S) = {e(psilon)}
            //  2. for each A belongs to N-{S} do FL(A) = empty
            //  3. repeat
            //      3.1 for each A belongs to N do FL'(A) = FL(A)
            //      3.2 for each rule A -> w = u1u2...un with w != T* do
            //          3.2.1 L = FL'(A)
            //          3.2.2 if un belongs to N then FL(un) = FL(un) U L
            //          3.2.3 for i = n-1 to 1 do
            //                  3.2.3.1 L = TRUNCk(FIRSTk(ui+1)L)
            //                  3.2.3.2 if ui belongs to N then FL(ui) = FL(ui) U L
            //                end for
            //          end for
            //     until FL(A) = FL'(A) for every A belongs to N
            //  4. FOLLOWk(A) = FL(A)
            // FOLLOW set is list of lists for every non-terminal in grammar, size of "lists" is K
            //    ( )
            //     | \
            //     |   ---
            //     |      |
            // (0,1..K) (0,1..K)
            ail.net.framework.Assert.Condition(xi_k > 0, "ail.net.parser.Grammar.BuildFirstSet: xi_k > 0");

            // collect all non-terminals to deal with
            Hashtable nonterminals = new Hashtable();

            foreach (ail.net.parser.GrammarSymbol symbol in ail.net.parser.GrammarPool.Instance.Pool.Values)
            {
                if (symbol.IsNonTerminal())
                {
                    nonterminals[symbol.Id] = symbol;
                }
            }

            // 1. FL(S) = {e(psilon)}
            ArrayList fl = ((ail.net.parser.GrammarSymbol)nonterminals[StartSymbolId]).FollowSet; // trigger initialization

            ArrayList fl_e = new ArrayList();                                                     // follow set element

            fl_e.Add((int)ail.net.parser.Token.EType.eEpsilon);

            fl.Add(fl_e);

            // 2. for each A belongs to N-{S} do FL(A) = empty
            foreach (ail.net.parser.GrammarSymbol symbol in nonterminals.Values)
            {
                ArrayList dummy = symbol.FollowSet; // trigger initialization
            }

            // 3. repeat
            for (;;)
            {
                bool changed = false;

                // 3.2 for each rule A -> w = u1u2...un with w != T* do
                foreach (ail.net.parser.GrammarRule rule in RulesAttr)
                {
                    // w != T*
                    if (rule.RhsNonTerminalCount > 0)
                    {
                        // 3.2.1 L = FL'(A)
                        ail.net.parser.GrammarSymbol a = (ail.net.parser.GrammarSymbol)rule.Lhs[0];

                        ArrayList l = a.FollowSet;

                        // 3.2.2 if un belongs to N then FL(un) = FL(un) U L
                        ail.net.parser.GrammarSymbol un = (ail.net.parser.GrammarSymbol)rule.Rhs[rule.Rhs.Count - 1];

                        if (un.IsNonTerminal())
                        {
                            fl = ((ail.net.parser.GrammarSymbol)nonterminals[un.Id]).FollowSet;

                            foreach (ArrayList e in l)
                            {
                                if (!HasEntry(fl, e))
                                {
                                    fl.Add(e);
                                    changed = true;
                                }
                            }
                        }

                        //  3.2.3 for i = n-1 to 1 do
                        //      3.2.3.1 L = TRUNCk(FIRSTk(ui+1)L)
                        //      3.2.3.2 if ui belongs to N then FL(ui) = FL(ui) U L
                        //  end for
                        for (int i = rule.Rhs.Count - 2; i >= 0; i--)
                        {
                            l = OperatorInfixK(((ail.net.parser.GrammarSymbol)rule.Rhs[i + 1]).FirstSet, l, xi_k);

                            if (((ail.net.parser.GrammarSymbol)rule.Rhs[i]).IsNonTerminal())
                            {
                                fl = ((ail.net.parser.GrammarSymbol)nonterminals[((ail.net.parser.GrammarSymbol)rule.Rhs[i]).Id]).FollowSet;

                                foreach (ArrayList e in l)
                                {
                                    if (!HasEntry(fl, e))
                                    {
                                        fl.Add(e);
                                        changed = true;
                                    }
                                }
                            }
                        }
                    }
                }

                if (!changed)
                {
                    break;
                }
            }
        }
コード例 #20
0
        public void BuildFirstSet()
        {
            // Set First(x) equal to {x} for all terminals.
            // Set First(x) to {e} for all nullable non-terminals and to {} for all other non-terminals.
            foreach (ail.net.parser.GrammarSymbol symbol in ail.net.parser.GrammarPool.Instance.Pool.Values)
            {
                if (symbol.IsTerminal())
                {
                    symbol.FirstSet.Add(symbol.Id);
                }
                else
                {
                    if (symbol.Nullable)
                    {
                        symbol.FirstSet.Add((int)ail.net.parser.Token.EType.eEpsilon);
                    }
                }
            }

            // Repeat the following process until no further changes occur:
            //  For each production
            //  N -> x1 x2 ... xk
            //    (a) Add (First(x1)-{e}) to First(N)
            //    (b) If e belongs to First(x1) then add (First(x1)-{e}) to First(N)
            //    (c) If e belongs to First(x1) and e belongs to First(x2) then also add (First(x2)-{e})
            //        to First(N)
            //    (d) If e belongs to First(x1) and e belongs to First(x2) and e belongs to First(x3)
            //        then also add (First(x3)-{e}) to First(N)
            //    (e) Continue in the same manner for x4, ... , xk
            //
            // either:
            //     repeat
            //         for each production X -> Y1Y2 ... Yn do
            //             if Y1 not nullable then
            //                 add FIRST(Y1) to FIRST(X)
            //             else if Y1 ... Yi-1 are all nullable (or if i = n) then
            //                 add FIRST(Y1) U ... U FIRST(Yi) to FIRST(X)
            //             end if
            //         end for
            //     until FIRST not changed in this iteration
            for (;;)
            {
                bool changed = false;

                foreach (ail.net.parser.GrammarRule rule in RulesAttr)
                {
                    ail.net.parser.GrammarSymbol non_terminal = (ail.net.parser.GrammarSymbol)rule.Lhs[0];

                    int count = non_terminal.FirstSet.Count;

                    foreach (ail.net.parser.GrammarSymbol r_symbol in rule.Rhs)
                    {
                        bool has_epsilon = false;

                        for (int i = 0, n = r_symbol.FirstSet.Count; i < n; i++)
                        {
                            int r_symbol_id = (int)r_symbol.FirstSet[i];

                            if (r_symbol_id != (int)ail.net.parser.Token.EType.eEpsilon)
                            {
                                if (!non_terminal.FirstSet.Contains(r_symbol_id))
                                {
                                    non_terminal.FirstSet.Add(r_symbol_id);
                                }
                            }
                            else
                            {
                                has_epsilon = true; // should be only one
                            }
                        }

                        if (!has_epsilon)
                        {
                            break;
                        }
                    }

                    changed = changed ? changed : count != non_terminal.FirstSet.Count;
                }

                if (!changed)
                {
                    break;
                }
            }
        }