} //method #endregion #region Creating parser states private void CreateInitialAndFinalStates() { //there is always just one initial production "Root' -> .Root", 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); #region comment about FinalState //Create final state - because of the way states construction works, it doesn't create the final state automatically. // We need to create it explicitly and assign it to _data.FinalState property // The final executed reduction is "Root' -> Root.". This jump is executed as follows: // 1. parser creates Root' node // 2. Parser pops the state from stack - that would be initial state // 3. Finally, parser tries to find the transition in state.Actions table by the key of [Root'] element. // We must create the final state, and create the entry in transition table // The 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. #endregion itemList.Clear(); itemList.Add(Data.AugmentedRoot.Productions[0].LR0Items[1]); Data.FinalState = FindOrCreateState(itemList); //it is actually create //Create shift transition from initial to final state Data.InitialState.Actions[Data.AugmentedRoot.Key] = new ActionRecord(Data.AugmentedRoot.Key, ParserActionType.Shift, Data.FinalState, null); }
private void CreateInitialAndFinalStates() { LR0ItemList itemList = new LR0ItemList(); itemList.Add(_data.AugmentedRoot.Productions[0].LR0Items[0]); _data.InitialState = FindOrCreateState(itemList); _data.InitialState.Items[0].NewLookaheads.Add(Grammar.Eof.Key); itemList.Clear(); itemList.Add(_data.AugmentedRoot.Productions[0].LR0Items[1]); _data.FinalState = FindOrCreateState(itemList); _data.InitialState.Actions[_data.AugmentedRoot.Key] = new ActionRecord(_data.AugmentedRoot.Key, ParserActionType.Shift, _data.FinalState, null); }
public Production(bool isInitial, NonTerminal lvalue, BnfTermList rvalues) { LValue = lvalue; foreach (GrammarTerm rv in rvalues) { if (rv != Grammar.Empty) { RValues.Add(rv); } } foreach (GrammarTerm term in RValues) { Terminal terminal = term as Terminal; if (terminal == null) { continue; } HasTerminals = true; if (terminal.Category == TokenCategory.Error) { IsError = true; } } for (int p = 0; p <= RValues.Count; p++) { LR0Items.Add(new LR0Item(this, p)); } }
//Parser states are distinguished by the subset of kernel LR0 items. // So when we derive new LR0-item list by shift operation, // we need to find out if we have already a state with the same LR0Item list. // We do it by looking up in a state hash by a key - [LR0 item list key]. // Each list's key is a concatenation of items' IDs separated by ','. // Before producing the key for a list, the list must be sorted; // thus we garantee one-to-one correspondence between LR0Item sets and keys. // And of course, we count only kernel items (with dot NOT in the first position). #endregion public static string ComputeLR0ItemSetKey(LR0ItemSet items) { if (items.Count == 0) { return(""); } //Copy non-initial items to separate list, and then sort it LR0ItemList itemList = new LR0ItemList(); foreach (var item in items) { itemList.Add(item); } //quick shortcut if (itemList.Count == 1) { return(itemList[0].ID.ToString()); } itemList.Sort(CompareLR0Items); //Sort by ID //now build the key StringBuilder sb = new StringBuilder(255); foreach (LR0Item item in itemList) { sb.Append(item.ID); sb.Append(","); }//foreach return(sb.ToString()); }
public readonly LR0ItemList LR0Items = new LR0ItemList(); //LR0 items based on this production public Production(bool isInitial, NonTerminal lvalue, BnfTermList rvalues) { LValue = lvalue; //copy RValues skipping Empty pseudo-terminal foreach (BnfTerm rv in rvalues) { if (rv != Grammar.Empty) { RValues.Add(rv); } } //Calculate flags foreach (BnfTerm term in RValues) { Terminal terminal = term as Terminal; if (terminal == null) { continue; } HasTerminals = true; if (terminal.Category == TokenCategory.Error) { IsError = true; } }//foreach //Note that we add an extra LR0Item with p = RValues.Count for (int p = 0; p <= RValues.Count; p++) { LR0Items.Add(new LR0Item(this, p)); } }//constructor
} //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
public static string ComputeLR0ItemSetKey(LR0ItemSet items) { if (items.Count == 0) return ""; //Copy non-initial items to separate list, and then sort it LR0ItemList itemList = new LR0ItemList(); foreach (var item in items) itemList.Add(item); //quick shortcut if (itemList.Count == 1) return itemList[0].ID.ToString(); itemList.Sort(CompareLR0Items); //Sort by ID //now build the key StringBuilder sb = new StringBuilder(255); foreach (LR0Item item in itemList) { sb.Append(item.ID); sb.Append(","); }//foreach return sb.ToString(); }