//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 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
public ParserState(string name, LRItem item) { Name = name; Items.Add(item); }