//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);
        }
Example #2
0
        }         //method

        #endregion

        #region Creating parser states
        private void CreateParserStates()
        {
            Data.States.Clear();
            _stateHash = new ParserStateTable();
            //Create initial state
            //there is always just one initial production Root' -> Root + LF, and we're interested in LR item at 0 index
            LR0ItemList itemList = new LR0ItemList();

            itemList.Add(Data.AugmentedRoot.Productions[0].LR0Items[0]);
            Data.InitialState = FindOrCreateState(itemList); //it is actually create
            Data.InitialState.Items[0].NewLookaheads.Add(Grammar.Eof.Key);
            //create final state - we need to create it explicitly to assign to _data.FinalState property
            // final state is based on the same initial production, but different LRItem - the one with dot AFTER the root nonterminal.
            // it is item at index 1.
            itemList = new LR0ItemList();
            itemList.Add(Data.AugmentedRoot.Productions[0].LR0Items[1]);
            Data.FinalState = FindOrCreateState(itemList);

            // Iterate through states (while new ones are created) and create shift transitions and new states
            for (int index = 0; index < Data.States.Count; index++)
            {
                ParserState state = Data.States[index];
                AddClosureItems(state);
                //Get keys of all possible shifts
                ShiftTable shiftTable = GetStateShifts(state);
                //Each key in shifts dict is an input element
                // Value is LR0ItemList of shifted LR0Items for this input element.
                foreach (string input in shiftTable.Keys)
                {
                    LR0ItemList shiftedCoreItems = shiftTable[input];
                    ParserState newState         = FindOrCreateState(shiftedCoreItems);
                    state.Actions[input] = new ActionRecord(input, ParserActionType.Shift, newState, null);
                    //link original LRItems in original state to derived LRItems in newState
                    foreach (LR0Item coreItem in shiftedCoreItems)
                    {
                        LRItem fromItem = FindItem(state, coreItem.Production, coreItem.Position - 1);
                        LRItem toItem   = FindItem(newState, coreItem.Production, coreItem.Position);
                        if (!fromItem.PropagateTargets.Contains(toItem))
                        {
                            fromItem.PropagateTargets.Add(toItem);
                        }
                    } //foreach coreItem
                }     //foreach input
            }         //for index
        }             //method
        private void CreateParserStates()
        {
            Data.States.Clear();
            _stateHash = new ParserStateTable();
            CreateInitialAndFinalStates();

            string augmRootKey = Data.AugmentedRoot.Key;

            // Iterate through states (while new ones are created) and create shift transitions and new states
            for (int index = 0; index < Data.States.Count; index++)
            {
                ParserState state = Data.States[index];
                AddClosureItems(state);
                //Get keys of all possible shifts
                ShiftTable shiftTable = GetStateShifts(state);
                //Each key in shifts dict is an input element
                // Value is LR0ItemList of shifted LR0Items for this input element.
                foreach (string input in shiftTable.Keys)
                {
                    LR0ItemList shiftedCoreItems = shiftTable[input];
                    ParserState newState         = FindOrCreateState(shiftedCoreItems);
                    state.Actions[input] = new ActionRecord(input, ParserActionType.Shift, newState, null);
                    //link original LRItems in original state to derived LRItems in newState
                    foreach (LR0Item coreItem in shiftedCoreItems)
                    {
                        LRItem fromItem = FindItem(state, coreItem.Production, coreItem.Position - 1);
                        LRItem toItem   = FindItem(newState, coreItem.Production, coreItem.Position);
                        if (!fromItem.PropagateTargets.Contains(toItem))
                        {
                            fromItem.PropagateTargets.Add(toItem);
                        }
                    } //foreach coreItem
                }     //foreach input
            }         //for index
            Data.FinalState = Data.InitialState.Actions[Data.AugmentedRoot.Key].NewState;
        }             //method
Example #4
0
 public ParserState(string name, LRItem item)
 {
     Name = name;
     Items.Add(item);
 }