예제 #1
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);
        }
예제 #2
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
                    }
                }
            }
        }
예제 #3
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);
        }
예제 #4
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);
            }
        }
예제 #5
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;
                                }
                            }
                        }
                    }
                }
            }
        }
예제 #6
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;
                }
            }
        }
예제 #7
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;
                }
            }
        }