/// <summary> /// Outputs an LR1 Item /// </summary> /// <param name="parser"> /// The Parser <see cref="Parser"/> /// </param> /// <param name="lr1Item"> /// The LR1 Item <see cref="LR1Item"/> /// </param> public static void DumpLR1Item(Parser parser, LR1Item lr1Item) { LR0Item item = parser.LR0Items[lr1Item.LR0ItemID]; Console.Write(parser.Grammar.Tokens[parser.Productions[item.Production].Left]); Console.Write(" ->"); int nPosition = 0; for (;;) { if (nPosition == item.Position) { Console.Write(" *"); } if (nPosition >= parser.Productions[item.Production].Right.Length) { break; } int nToken = parser.Productions[item.Production].Right[nPosition]; Console.Write(" " + parser.Grammar.Tokens[nToken]); nPosition++; } if (lr1Item.LookAhead == -1) { Console.WriteLine(", $"); } else { Console.WriteLine(", " + parser.Grammar.Tokens[lr1Item.LookAhead]); } }
public void DumpLR1Item(LR1Item lr1Item) { var item = _parser.LR0Items[lr1Item.LR0ItemID]; _builder.Append(_parser.Grammar.SymbolNames[_parser.Productions[item.Production].Left]); _builder.Append(" ->"); int nPosition = 0; while (true) { 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.SymbolNames[nToken]); nPosition++; } if (lr1Item.LookAhead == -1) { _builder.Append(", $"); } else { _builder.Append(", ").Append(_parser.Grammar.SymbolNames[lr1Item.LookAhead]); } _builder.AppendLine(); }
/// <summary> /// Outputs an LR1 State /// </summary> /// <param name="parser"> /// The Parser <see cref="Parser"/> /// </param> /// <param name="lr1State"> /// A List of LR1 Item IDs <see cref="HashSet<System.Int32>"/> /// </param> public static void DumpLR1State(Parser parser, HashSet <int> lr1State) { foreach (int nLR1Item in lr1State) { LR1Item lr1Item = parser.LR1Items[nLR1Item]; DumpLR1Item(parser, lr1Item); } }
/// <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(HashSet <int> i) { HashSet <int> closed = new HashSet <int>(); List <int> open = new List <int>(); foreach (int itemCopy in i) { open.Add(itemCopy); } while (open.Count > 0) { int nLR1Item = open[0]; open.RemoveAt(0); LR1Item lr1Item = m_lr1Items[nLR1Item]; LR0Item lr0Item = m_lr0Items[lr1Item.LR0ItemID]; closed.Add(nLR1Item); if (lr0Item.Position < m_productions[lr0Item.Production].Right.Length) { int nToken = m_productions[lr0Item.Production].Right[lr0Item.Position]; if (m_nonterminals.Contains(nToken)) { List <int> argFirst = new List <int>(); for (int nIdx = lr0Item.Position + 1; nIdx < m_productions[lr0Item.Production].Right.Length; nIdx++) { argFirst.Add(m_productions[lr0Item.Production].Right[nIdx]); } HashSet <int> first = First(argFirst, lr1Item.LookAhead); int nProduction = 0; foreach (Production production in m_productions) { if (production.Left == nToken) { foreach (int nTokenFirst in first) { LR0Item newLR0Item = new LR0Item { Production = nProduction, Position = 0 }; int nNewLR0ItemID = GetLR0ItemID(newLR0Item); LR1Item newLR1Item = new LR1Item { LR0ItemID = nNewLR0ItemID, LookAhead = nTokenFirst }; int nNewLR1ItemID = GetLR1ItemID(newLR1Item); if (!open.Contains(nNewLR1ItemID) && !closed.Contains(nNewLR1ItemID)) { open.Add(nNewLR1ItemID); } } } nProduction++; } } } } return(closed); }
/// <summary> /// Initializes the propogation table, and initial state of the LALR table /// </summary> void InitLALRTables() { int nLR0State = 0; foreach (HashSet <int> lr0State in m_lr0States) { m_lalrStates.Add(new HashSet <int>()); } foreach (HashSet <int> lr0Kernel in m_lr0Kernels) { HashSet <int> J = new HashSet <int>(); foreach (int jLR0ItemID in lr0Kernel) { LR1Item lr1Item = new LR1Item { LR0ItemID = jLR0ItemID, LookAhead = -1 }; int nLR1ItemID = GetLR1ItemID(lr1Item); J.Add(nLR1ItemID); } HashSet <int> JPrime = LR1Closure(J); foreach (int jpLR1ItemID in JPrime) { LR1Item lr1Item = m_lr1Items[jpLR1ItemID]; LR0Item lr0Item = m_lr0Items[lr1Item.LR0ItemID]; if ((lr1Item.LookAhead != -1) || (nLR0State == 0)) { m_lalrStates[nLR0State].Add(jpLR1ItemID); } if (lr0Item.Position < m_productions[lr0Item.Production].Right.Length) { int nToken = m_productions[lr0Item.Production].Right[lr0Item.Position]; LR0Item lr0Successor = new LR0Item { Production = lr0Item.Production, Position = lr0Item.Position + 1 }; int nLR0Successor = GetLR0ItemID(lr0Successor); int nSuccessorState = m_lrGotos[nLR0State][nToken]; if (lr1Item.LookAhead == -1) { AddPropogation(nLR0State, lr1Item.LR0ItemID, nSuccessorState, nLR0Successor); } else { LR1Item lalrItem = new LR1Item { LR0ItemID = nLR0Successor, LookAhead = lr1Item.LookAhead }; int nLALRItemID = GetLR1ItemID(lalrItem); m_lalrStates[nSuccessorState].Add(nLALRItemID); } } } nLR0State++; } }
/// <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); }
/// <summary> /// Outputs the LALR States for the parser /// </summary> /// <param name="parser"> /// The parser <see cref="Parser"/> /// </param> public static void DumpLALRStates(Parser parser) { int nStateID = 0; foreach (HashSet <int> lalrState in parser.LALRStates) { Console.WriteLine("State " + nStateID + ":"); foreach (int nLR1Item in lalrState) { LR1Item lr1Item = parser.LR1Items[nLR1Item]; DumpLR1Item(parser, lr1Item); } nStateID++; } }
/// <summary> /// Calculates the states in the LALR table /// </summary> void CalculateLookAheads() { bool bChanged; do { bChanged = false; int nState = 0; foreach (Dictionary <int, List <LALRPropogation> > statePropogations in m_lalrPropogations) { bool bStateChanged = false; foreach (int nLR1Item in m_lalrStates[nState]) { LR1Item lr1Item = m_lr1Items[nLR1Item]; if (statePropogations.ContainsKey(lr1Item.LR0ItemID)) { foreach (LALRPropogation lalrPropogation in statePropogations[lr1Item.LR0ItemID]) { int nGoto = lalrPropogation.LR0TargetState; LR1Item item = new LR1Item { LR0ItemID = lalrPropogation.LR0TargetItem, LookAhead = lr1Item.LookAhead }; if (m_lalrStates[nGoto].Add(GetLR1ItemID(item))) { bChanged = true; bStateChanged = true; } } } } if (bStateChanged) { m_lalrStates[nState] = LR1Closure(m_lalrStates[nState]); } nState++; } }while(bChanged); }
/// <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> /// Generates the parse table given the lalr states, and grammar /// </summary> void GenerateParseTable() { m_parseTable = new ParseTable(); m_parseTable.Actions = new Action[m_lalrStates.Count, m_grammar.Tokens.Length + 1]; for (int nStateID = 0; nStateID < m_lalrStates.Count; nStateID++) { HashSet <int> lalrState = m_lalrStates[nStateID]; for (int nToken = -1; nToken < m_grammar.Tokens.Length; nToken++) { List <Action> actions = new List <Action>(); string sToken = "$"; if (nToken >= 0) { sToken = m_grammar.Tokens[nToken]; if (m_lrGotos[nStateID][nToken] >= 0) { actions.Add(new Action { ActionType = ActionType.Shift, ActionParameter = m_lrGotos[nStateID][nToken] }); } } foreach (int nLR1ItemID in lalrState) { LR1Item lr1Item = m_lr1Items[nLR1ItemID]; LR0Item lr0Item = m_lr0Items[lr1Item.LR0ItemID]; if ((lr0Item.Position == m_productions[lr0Item.Production].Right.Length) && lr1Item.LookAhead == nToken) { Action action = new Action { ActionType = ActionType.Reduce, ActionParameter = lr0Item.Production }; if (!ListContainsAction(actions, action)) { actions.Add(action); } } } int nMaxPrecedence = int.MinValue; List <Action> importantActions = new List <Action>(); foreach (Action action in actions) { int nActionPrecedence = int.MinValue; if (action.ActionType == ActionType.Shift) { nActionPrecedence = m_gotoPrecedence[nStateID][nToken]; //nToken will never be -1 } else if (action.ActionType == ActionType.Reduce) { nActionPrecedence = m_productionPrecedence[action.ActionParameter]; } if (nActionPrecedence > nMaxPrecedence) { nMaxPrecedence = nActionPrecedence; importantActions.Clear(); importantActions.Add(action); } else if (nActionPrecedence == nMaxPrecedence) { importantActions.Add(action); } } if (importantActions.Count == 1) { m_parseTable.Actions[nStateID, nToken + 1] = importantActions[0]; } else if (importantActions.Count > 1) { Action shiftAction = null; List <Action> reduceActions = new List <Action>(); foreach (Action action in importantActions) { if (action.ActionType == ActionType.Reduce) { reduceActions.Add(action); } else { shiftAction = action; } } Derivation derv = m_grammar.PrecedenceGroups[-nMaxPrecedence].Derivation; if (derv == Derivation.LeftMost && reduceActions.Count == 1) { m_parseTable.Actions[nStateID, nToken + 1] = reduceActions[0]; } else if (derv == Derivation.RightMost && shiftAction != null) { m_parseTable.Actions[nStateID, nToken + 1] = shiftAction; } else { if (derv == Derivation.None && reduceActions.Count == 1) { Debug.Console.WriteLine("Error, shift-reduce conflict in grammar"); } else { Debug.Console.WriteLine("Error, reduce-reduce conflict in grammar"); } m_parseTable.Actions[nStateID, nToken + 1] = new Action { ActionType = ActionType.Error, ActionParameter = nToken }; } } else { m_parseTable.Actions[nStateID, nToken + 1] = new Action { ActionType = ActionType.Error, ActionParameter = nToken }; } } } }
public bool Equals(LR1Item item) { return((LR0ItemID == item.LR0ItemID) && (LookAhead == item.LookAhead)); }