Exemple #1
0
 public bool CoreEquals(Lr1ItemSet <T> other)
 {
     // Must be the same number of items
     if (Items.Count == other.Items.Count)
     {
         // Every item must have the same production rule the dot at the same place
         return(Items.All(f => other.Any(o => o.ProductionRule == f.ProductionRule && f.DotLocation == o.DotLocation)));
     }
     return(false);
 }
Exemple #2
0
        internal IParser <T> CreateParser()
        {
            // First order of business is to create the canonical list of LR1 states, or at least we are going to go through
            // them as we merge the sets together.
            // This starts with augmenting the grammar with an accept symbol, then we derive the
            // grammar from that
            IProductionRule <T> start = grammar.Start;

            // Get the first and follow sets for all nonterminal symbols
            ISet <NonTerminal <T> > nullable = CalculateNullable();
            TerminalSet <T>         first    = CalculateFirst(nullable);

            // So, we are going to calculate the LR1 closure for the start symbol, which should
            // be the augmented accept state of the grammar.
            // The closure is all states which are accessible by the dot at the left hand side of the
            // item.
            List <Lr1ItemSet <T> > itemSets = new List <Lr1ItemSet <T> >
            {
                Closure(new List <Lr1Item <T> >
                {
                    new Lr1Item <T>(start, 0, new HashSet <Terminal <T> > {
                        grammar.EndOfInputTerminal
                    })
                }, first, nullable)
            };
            List <GotoSetTransition> gotoSetTransitions = new List <GotoSetTransition>();

            // Repeat until nothing gets added any more
            // This is neccessary since we are merging sets as we go, which changes things around.
            bool added;

            do
            {
                added = false;

                for (int i = 0; i < itemSets.Count; ++i)
                {
                    Lr1ItemSet <T> itemSet = itemSets[i];

                    foreach (ISymbol <T> symbol in grammar.AllSymbols)
                    {
                        // Calculate the itemset for by goto for each symbol in the grammar
                        Lr1ItemSet <T> gotoSet = Goto(itemSet, symbol);

                        // If there is anything found in the set
                        if (gotoSet.Any())
                        {
                            // Do a closure on the goto set and see if it's already present in the sets of items that we have
                            // if that is not the case add it to the item set
                            gotoSet = Closure(gotoSet, first, nullable);

                            Lr1ItemSet <T> oldGotoSet = itemSets.Find(f => f.CoreEquals(gotoSet));

                            if (oldGotoSet == null)
                            {
                                // Add goto set to itemsets
                                itemSets.Add(gotoSet);

                                // Add a transition
                                gotoSetTransitions.Add(new GotoSetTransition
                                {
                                    From     = itemSet,
                                    OnSymbol = symbol,
                                    To       = gotoSet
                                });
                                added = true;
                            }
                            else
                            {
                                // Already found the set
                                // Merge the lookaheads for all rules
                                oldGotoSet.MergeLookaheads(gotoSet);

                                // Add a transition if it already isn't there
                                GotoSetTransition nt = new GotoSetTransition
                                {
                                    From     = itemSet,
                                    OnSymbol = symbol,
                                    To       = oldGotoSet
                                };

                                if (!gotoSetTransitions.Any(a => (a.From == nt.From) && (a.OnSymbol == nt.OnSymbol) && (a.To == nt.To)))
                                {
                                    gotoSetTransitions.Add(nt);
                                }
                            }
                        }
                    }
                }
            } while (added);

            LRParseTable <T> parseTable = CreateParseTable(itemSets, gotoSetTransitions);

            // Create a new parser using that parse table and some additional information that needs
            // to be available for the runtime parsing to work.
            return(new LRParser <T>(
                       parseTable,
                       (grammar.ErrorToken as Terminal <T>).TokenNumber,
                       grammar.EndOfInputTerminal.TokenNumber,
                       grammar.AllSymbols.OfType <Terminal <T> >().Select(f => f.DebugName).ToArray()
                       ));
        }