private LRItem TryFindItem(ParserState state, LR0Item core)
 {
     foreach (LRItem item in state.Items)
     {
         if (item.Core == core)
         {
             return(item);
         }
     }
     return(null);
 }//method
 private static int ById(LR0Item x, LR0Item y)
 {
     if (x.ID < y.ID)
     {
         return(-1);
     }
     if (x.ID == y.ID)
     {
         return(0);
     }
     return(1);
 }
        //Creates closure items with "spontaneously generated" lookaheads
        private bool AddClosureItems(ParserState state)
        {
            bool result = false;

            //note that we change collection while we iterate thru it, so we have to use "for i" loop
            for (int i = 0; i < state.Items.Count; i++)
            {
                LRItem      item   = state.Items[i];
                NonTerminal nextNT = item.Core.NextElement as NonTerminal;
                if (nextNT == null)
                {
                    continue;
                }
                //1. Add normal closure items
                foreach (Production prod in nextNT.Productions)
                {
                    LR0Item core    = prod.LR0Items[0]; //item at zero index is the one that starts with dot
                    LRItem  newItem = TryFindItem(state, core);
                    if (newItem == null)
                    {
                        newItem = new LRItem(state, core);
                        state.Items.Add(newItem);
                        result = true;
                    }
                    #region Comments on lookaheads processing
                    // The general idea of generating ("spontaneously") the lookaheads is the following:
                    // Let's the original item be in the form
                    //   [A -> alpha . B beta , lset]
                    //     where <B> is a non-terminal and <lset> is a set of lookaheads,
                    //      <beta> is some string (B's tail in our terminology)
                    // Then the closure item on non-teminal B is an item
                    //   [B -> x, firsts(beta + lset)]
                    //      (the lookahead set is expression after the comma).
                    // To generate lookaheads on a closure item, we simply take "firsts"
                    //   from the tail <beta> of the NonTerminal <B>.
                    //   Normally if tail <beta> is nullable we would add ("propagate")
                    //   the <lset> lookaheads from <A> to <B>.
                    //   We dont' do it right here - we simply add a propagation link.
                    //   We propagate all lookaheads later in a separate process.
                    #endregion
                    newItem.NewLookaheads.AddRange(item.Core.TailFirsts);
                    if (item.Core.TailIsNullable && !item.PropagateTargets.Contains(newItem))
                    {
                        item.PropagateTargets.Add(newItem);
                    }
                } //foreach prod
            }     //for i (LRItem)
            return(result);
        }
        }                     //method

        #endregion

        #region Calculating Tail Firsts
        private void CalculateTailFirsts()
        {
            foreach (Production prod in Data.Productions)
            {
                StringSet accumulatedFirsts = new StringSet();
                bool      allNullable       = true;
                //We are going backwards in LR0Items list
                for (int i = prod.LR0Items.Count - 1; i >= 0; i--)
                {
                    LR0Item item = prod.LR0Items[i];
                    if (i >= prod.LR0Items.Count - 2)
                    {
                        //Last and before last items have empty tails
                        item.TailIsNullable = true;
                        item.TailFirsts.Clear();
                        continue;
                    }
                    BnfTerm     term   = prod.RValues[item.Position + 1]; //Element after-after-dot
                    NonTerminal ntElem = term as NonTerminal;
                    if (ntElem == null || !ntElem.Nullable)               //term is a terminal or non-nullable NonTerminal
                    //term is not nullable, so we clear all old firsts and add this term
                    {
                        accumulatedFirsts.Clear();
                        allNullable         = false;
                        item.TailIsNullable = false;
                        if (ntElem == null)
                        {
                            item.TailFirsts.Add(term.Key);//term is terminal so add its key
                            accumulatedFirsts.Add(term.Key);
                        }
                        else
                        {
                            item.TailFirsts.AddRange(ntElem.Firsts); //nonterminal
                            accumulatedFirsts.AddRange(ntElem.Firsts);
                        }
                        continue;
                    }
                    //if we are here, then ntElem is a nullable NonTerminal. We add
                    accumulatedFirsts.AddRange(ntElem.Firsts);
                    item.TailFirsts.AddRange(accumulatedFirsts);
                    item.TailIsNullable = allNullable;
                } //for i
            }     //foreach prod
        }         //method
        }//method

        private ShiftTable GetStateShifts(ParserState state)
        {
            ShiftTable  shifts = new ShiftTable();
            LR0ItemList list;

            foreach (LRItem item in state.Items)
            {
                BnfTerm term = item.Core.NextElement;
                if (term == null)
                {
                    continue;
                }
                LR0Item shiftedItem = item.Core.Production.LR0Items[item.Core.Position + 1];
                if (!shifts.TryGetValue(term.Key, out list))
                {
                    shifts[term.Key] = list = new LR0ItemList();
                }
                list.Add(shiftedItem);
            } //foreach
            return(shifts);
        }     //method
示例#6
0
 public LRItem(ParserState state, LR0Item core)
 {
     State = state;
     Core  = core;
 }