public BuilderItem(int action, LR1Item lr1Item) { Action = action; LR1Item = lr1Item; }
/// <summary> /// Calculates the states in the LALR table /// </summary> void CalculateLookAheads() { bool bChanged; do { bChanged = false; int nState = 0; foreach (var statePropogations in _lalrPropogations) { bool bStateChanged = false; foreach (int nLR1Item in _lalrStates[nState]) { var lr1Item = _lr1Items[nLR1Item]; if (statePropogations.ContainsKey(lr1Item.LR0ItemID)) { foreach (var lalrPropogation in statePropogations[lr1Item.LR0ItemID]) { int nGoto = lalrPropogation.LR0TargetState; var item = new LR1Item(lalrPropogation.LR0TargetItem, lr1Item.LookAhead); if (_lalrStates[nGoto].Add(GetLR1ItemID(item))) { bChanged = true; bStateChanged = true; } } } } if (bStateChanged) { _lalrStates[nState] = LR1Closure(_lalrStates[nState]); } nState++; } } while (bChanged); }
/// <summary> /// Initializes the propogation table, and initial state of the LALR table /// </summary> int InitLALRTables() { int nLR0State = 0; for (var i = 0; i < _lr0States.Count; i++ ) { _lalrStates.Add(new HashSet<int>()); } foreach (var lr0Kernel in _lr0Kernels) { var j = new HashSet<int>(); foreach (int jLR0ItemID in lr0Kernel) { var lr1Item = new LR1Item(jLR0ItemID, -1); int nLR1ItemID = GetLR1ItemID(lr1Item); j.Add(nLR1ItemID); } var jPrime = LR1Closure(j); foreach (int jpLR1ItemID in jPrime) { var lr1Item = _lr1Items[jpLR1ItemID]; var lr0Item = _lr0Items[lr1Item.LR0ItemID]; if ((lr1Item.LookAhead != -1) || (nLR0State == 0)) { _lalrStates[nLR0State].Add(jpLR1ItemID); } if (lr0Item.Position < _productions[lr0Item.Production].Right.Length) { int nToken = _productions[lr0Item.Production].Right[lr0Item.Position]; var lr0Successor = new LR0Item(lr0Item.Production, lr0Item.Position + 1); int nLR0Successor = GetLR0ItemID(lr0Successor); int nSuccessorState = _lrGotos[nLR0State][nToken]; if (lr1Item.LookAhead == -1) { AddPropogation(nLR0State, lr1Item.LR0ItemID, nSuccessorState, nLR0Successor); } else { var lalrItem = new LR1Item( nLR0Successor, lr1Item.LookAhead); int nLALRItemID = GetLR1ItemID(lalrItem); _lalrStates[nSuccessorState].Add(nLALRItemID); } } } nLR0State++; } return _lalrStates.Count; }
/// <summary> /// takes a set of LR1 Items (LR0 items with lookaheads) and produces all of those LR1 items reachable by substitution /// </summary> HashSet<int> LR1Closure(IEnumerable<int> items) { var closed = new HashSet<int>(); var open = items.ToList(); while (open.Count > 0) { int nLR1Item = open[0]; open.RemoveAt(0); LR1Item lr1Item = _lr1Items[nLR1Item]; LR0Item lr0Item = _lr0Items[lr1Item.LR0ItemID]; closed.Add(nLR1Item); if (lr0Item.Position < _productions[lr0Item.Production].Right.Length) { int nToken = _productions[lr0Item.Production].Right[lr0Item.Position]; if (_nonterminals.Contains(nToken)) { var argFirst = new List<int>(); for (int nIdx = lr0Item.Position + 1; nIdx < _productions[lr0Item.Production].Right.Length; nIdx++) { argFirst.Add(_productions[lr0Item.Production].Right[nIdx]); } var first = First(argFirst, lr1Item.LookAhead); int nProduction = 0; foreach (var production in _productions) { if (production.Left == nToken) { foreach (int nTokenFirst in first) { var newLR0Item = new LR0Item(nProduction, 0); int nNewLR0ItemID = GetLR0ItemID(newLR0Item); var newLR1Item = new LR1Item(nNewLR0ItemID, nTokenFirst); int nNewLR1ItemID = GetLR1ItemID(newLR1Item); if (!open.Contains(nNewLR1ItemID) && !closed.Contains(nNewLR1ItemID)) { open.Add(nNewLR1ItemID); } } } nProduction++; } } } } return closed; }
/// <summary> /// Gets the ID for a particular LR1 Item /// </summary> int GetLR1ItemID(LR1Item item) { int nItemID = 0; foreach (LR1Item oItem in _lr1Items) { if (oItem.Equals(item)) { return nItemID; } nItemID++; } _lr1Items.Add(item); return nItemID; }
public void DumpLR1Item(LR1Item lr1Item) { var item = _parser.LR0Items[lr1Item.LR0ItemID]; _builder.Append(_parser.Grammar.TokenCategories[_parser.Productions[item.Production].Left]); _builder.Append(" ->"); int nPosition = 0; for (; ; ) { if (nPosition == item.Position) { _builder.Append(" *"); } if (nPosition >= _parser.Productions[item.Production].Right.Length) { break; } int nToken = _parser.Productions[item.Production].Right[nPosition]; _builder.Append(" ").Append(_parser.Grammar.TokenCategories[nToken]); nPosition++; } if (lr1Item.LookAhead == -1) { _builder.Append(", $"); } else { _builder.Append(", ").Append(_parser.Grammar.TokenCategories[lr1Item.LookAhead]); } _builder.AppendLine(); }