private void computeClosure(HashSet <LR0Item> stateItems) { int stateIndex = 0; List <LR0Item> toConsider = stateItems.ToList(); while (stateIndex < toConsider.Count) { LR0Item item = toConsider[stateIndex]; stateIndex++; if (!item.DposAtEnd()) { string sym = item.Rhs[item.Dpos]; if (productionDict.ContainsKey(sym)) //nonterminal { foreach (string p in productionDict[sym].productions) { LR0Item item2 = new LR0Item(sym, getProductionAsList(p), 0); if (!stateItems.Contains(item2)) { stateItems.Add(item2); toConsider.Add(item2); } } } } } }
public override bool Equals(object obj) { if (obj == null) { return(false); } LR0Item o = obj as LR0Item; if (o == null || o.Lhs != this.Lhs || o.Dpos != this.Dpos || o.Rhs.Count != this.Rhs.Count) { return(false); } for (int i = 0; i < this.Rhs.Count; i++) { if (o.Rhs[i] != this.Rhs[i]) { return(false); } } return(true); }
public LRItem FindByCore(LR0Item core) { foreach (LRItem item in this) { if (item.Core == core) { return(item); } } return(null); }
private LRItem TryFindItem(ParserState state, LR0Item core) { foreach (LRItem item in state.Items) { if (item.Core == core) { return(item); } } return(null); }//method
private static int ById(LR0Item x, LR0Item y) { if (x.ID < y.ID) { return(-1); } if (x.ID == y.ID) { return(0); } return(1); }
private static int CompareLR0Items(LR0Item x, LR0Item y) { if (x.ID < y.ID) { return(-1); } if (x.ID == y.ID) { return(0); } return(1); }
public bool IsAccepted(LR0State state) { if (state.Items.Count == 1) { var accItem = new LR0Item(augmentedGrammar.StartingSymbol, grammar.StartingSymbol + "."); if (accItem.Equals(state.Items[0])) { return(true); } } return(false); }
//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]; BnfTerm currTerm = item.Core.Current; if (currTerm == null || !(currTerm is NonTerminal)) { continue; } //1. Add normal closure items NtData currInfo = (NtData)currTerm.ParserData; foreach (Production prod in currInfo.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 Calculating Tail Firsts private void CalculateTailFirsts() { foreach (NonTerminal nt in _grammar.NonTerminals) { foreach (Production prod in nt.Productions) { StringSet accumulatedFirsts = new StringSet(); bool allNullable = true; //We are going backwards in LR0Items list for (int i = prod.LR0Items.Count - 1; i >= 0; i--) { LR0Item item = prod.LR0Items[i]; if (i >= prod.LR0Items.Count - 2) { //Last and before last items have empty tails item.TailIsNullable = true; item.TailFirsts.Clear(); continue; } BnfTerm nextTerm = prod.RValues[i + 1]; //Element after-after-dot; remember we're going in reverse direction //if (ntElem == null) continue; //it is not NonTerminal NonTerminal nextNt = nextTerm as NonTerminal; bool notNullable = nextTerm is Terminal || nextNt != null && !nextNt.Nullable; if (notNullable) //next term is not nullable (a terminal or non-nullable NonTerminal) //term is not nullable, so we clear all old firsts and add this term { accumulatedFirsts.Clear(); allNullable = false; item.TailIsNullable = false; if (nextTerm is Terminal) { item.TailFirsts.Add(nextTerm.Key);//term is terminal so add its key accumulatedFirsts.Add(nextTerm.Key); } else if (nextNt != null) //it is NonTerminal { item.TailFirsts.AddRange(nextNt.Firsts); //nonterminal accumulatedFirsts.AddRange(nextNt.Firsts); } continue; } //if we are here, then ntElem is a nullable NonTerminal. We add accumulatedFirsts.AddRange(nextNt.Firsts); item.TailFirsts.AddRange(accumulatedFirsts); item.TailIsNullable = allNullable; } //for i } //foreach prod } //foreach nt } //method
private Production CreateProduction(NonTerminal lvalue, BnfTermList operands) { Production prod = new Production(lvalue); //create RValues list skipping Empty terminal and collecting grammar hints foreach (BnfTerm operand in operands) { if (operand == Grammar.Empty) { continue; } //Collect hints as we go - they will be added to the next non-hint element GrammarHint hint = operand as GrammarHint; if (hint != null) { hint.Position = prod.RValues.Count; prod.Hints.Add(hint); continue; } //Check if it is a Terminal or Error element Terminal t = operand as Terminal; if (t != null) { prod.Flags |= ProductionFlags.HasTerminals; if (t.Category == TokenCategory.Error) { prod.Flags |= ProductionFlags.IsError; } } //Add the operand info and LR0 Item _itemID++; LR0Item item = new LR0Item(prod, prod.RValues.Count, _itemID); prod.LR0Items.Add(item); prod.RValues.Add(operand); }//foreach operand //set the flags if (lvalue == Data.AugmentedRoot) { prod.Flags |= ProductionFlags.IsInitial; } if (prod.RValues.Count == 0) { prod.Flags |= ProductionFlags.IsEmpty; } //Add final LRItem _itemID++; prod.LR0Items.Add(new LR0Item(prod, prod.RValues.Count, _itemID)); return(prod); }
public SLR_1_(Dictionary <string, Production> prodDict, List <Production> prods, HashSet <string> nulls, Dictionary <string, HashSet <string> > follow, List <Token> t, ref List <Dictionary <string, Tuple <string, int, string> > > LRTable, ref TreeNode productionTreeRoot, ref State startState, bool computeTree) { productions = prods; productionDict = prodDict; nullables = nulls; Follows = follow; tokens = t; //create Start State states = new List <State>(); startState = new State(0); LR0Item start = new LR0Item("S'", new List <string> { "program" }, 0); LRTable = new List <Dictionary <string, Tuple <string, int, string> > >(); Dictionary <HashSet <LR0Item>, State> seen = new Dictionary <HashSet <LR0Item>, State>(new EQ()); Stack <State> todo = new Stack <State>(); startState.Items.Add(start); computeClosure(startState.Items); states.Add(startState); seen.Add(startState.Items, startState); todo.Push(startState); while (todo.Count > 0) { State Q = todo.Pop(); Dictionary <string, HashSet <LR0Item> > transitions = computeTransitions(Q); addStates(Q, transitions, seen, todo); } //printSeenMap(seen); computeSLRTable(ref LRTable); //printLRTable(LRTable); //printTokens(t); //LRdot dot = new LRdot(startState, grammarFile); if (computeTree) { SLR_Parse(LRTable, ref productionTreeRoot); } }
public GLR(Dictionary <string, Production> prodDict, string firstProduction, Dictionary <string, HashSet <string> > follow, List <Token> t, ref List <Dictionary <string, List <Tuple <string, int, string> > > > parseTable, ref TreeNode productionTreeRoot, ref State startState, bool computeTree) { productionDict = prodDict; Follows = follow; tokens = t; //create Start State states = new List <State>(); startState = new State(0); LR0Item start = new LR0Item("S'", new List <string> { firstProduction }, 0); parseTable = new List <Dictionary <string, List <Tuple <string, int, string> > > >(); seen = new Dictionary <HashSet <LR0Item>, State>(new EQ()); Stack <State> todo = new Stack <State>(); startState.Items.Add(start); computeClosure(startState.Items); states.Add(startState); seen.Add(startState.Items, startState); todo.Push(startState); while (todo.Count > 0) { State Q = todo.Pop(); Dictionary <string, HashSet <LR0Item> > transitions = computeTransitions(Q); addStates(Q, transitions, seen, todo); } printSeenMap(seen); computeGLRTable(ref parseTable); printGLRTable(parseTable); printTokens(t); LRdot dot = new LRdot(startState, "gFile.dot"); if (computeTree) { GLR_Parse(parseTable, ref productionTreeRoot); } }
}//method private ShiftTable GetStateShifts(ParserState state) { ShiftTable shifts = new ShiftTable(); LR0ItemList list; foreach (LRItem item in state.Items) { BnfTerm term = item.Core.Current; if (term == null) { continue; } LR0Item shiftedItem = item.Core.Production.LR0Items[item.Core.Position + 1]; if (!shifts.TryGetValue(term.Key, out list)) { shifts[term.Key] = list = new LR0ItemList(); } list.Add(shiftedItem); } //foreach return(shifts); } //method
public void DumpLR0Item(LR0Item item) { _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(" " + _parser.Grammar.TokenCategories[nToken]); nPosition++; } }
public int ReduceTo(LR0State state) { var item = state.Items[0]; var lhsItem = item.lhs; var rhsItem = item.rhs.Substring(0, item.rhs.Length - 1); var newItem = new LR0Item(lhsItem, rhsItem); var index = 0; foreach (var originalItem in grammar.ProductionList) { if (originalItem.Equals(newItem)) { return(index); } index++; } return(-1); }
private Dictionary <string, HashSet <LR0Item> > computeTransitions(State State) { //make copy of transitions dictionary in State Dictionary <string, HashSet <LR0Item> > transitions = new Dictionary <string, HashSet <LR0Item> >(); //add new transitions if not in dict foreach (LR0Item item in State.Items) { if (!item.DposAtEnd()) { string sym = item.Rhs[item.Dpos]; if (!transitions.ContainsKey(sym)) { transitions.Add(sym, new HashSet <LR0Item>()); } LR0Item newItem = new LR0Item(item.Lhs, item.Rhs, item.Dpos + 1); //Console.WriteLine("adding production rhsLen:" + newItem.Rhs.Count + " " + newItem.ToString()); transitions[sym].Add(newItem); } } //return copy as new Dict return(transitions); }
//LR(0) stuff private void LR_Grammar_Proc() { //create Start State setTerminals(); startState = new State(); LR0Item start = new LR0Item("S'", new List <string> { "S" }, 0); Dictionary <HashSet <LR0Item>, State> seen = new Dictionary <HashSet <LR0Item>, State>(new EQ()); Stack <State> todo = new Stack <State>(); startState.Items.Add(start); computeClosure(startState.Items); seen.Add(startState.Items, startState); todo.Push(startState); while (todo.Count > 0) { State Q = todo.Pop(); Dictionary <string, HashSet <LR0Item> > transitions = computeTransitions(Q); addStates(Q, transitions, seen, todo); } }
//LR(0) stuff private void LR_Grammar_Proc() { //create Start State states = new List <State>(); startState = new State(); LR0Item start = new LR0Item("S'", new List <string> { "S" }, 0); Dictionary <HashSet <LR0Item>, State> seen = new Dictionary <HashSet <LR0Item>, State>(new EQ()); Stack <State> todo = new Stack <State>(); startState.Items.Add(start); computeClosure(startState.Items); states.Add(startState); seen.Add(startState.Items, startState); todo.Push(startState); while (todo.Count > 0) { State Q = todo.Pop(); Dictionary <string, HashSet <LR0Item> > transitions = computeTransitions(Q); addStates(Q, transitions, seen, todo); } computeSLRTable(); printSeenMap(seen); printLRTable(); LRdot dot = new LRdot(startState, grammarFile); if (this.inputFile != null) { SLR_Parse(); } }
/// <summary> /// takes a set of LR0 Items and Produces all of the LR0 Items that are reachable by substitution /// </summary> HashSet<int> LR0Closure(IEnumerable<int> items) { var closed = new HashSet<int>(); var open = items.ToList(); while (open.Count > 0) { int nItem = open[0]; open.RemoveAt(0); LR0Item item = _lr0Items[nItem]; closed.Add(nItem); int nProduction = 0; foreach (var production in _productions) { if ((item.Position < _productions[item.Production].Right.Length) && (production.Left == _productions[item.Production].Right[item.Position])) { var newItem = new LR0Item(nProduction, 0); int nNewItemID = GetLR0ItemID(newItem); if (!open.Contains(nNewItemID) && !closed.Contains(nNewItemID)) { open.Add(nNewItemID); } } nProduction++; } } return closed; }
private Production CreateProduction(NonTerminal lvalue, BnfTermList operands) { Production prod = new Production(lvalue); GrammarHintList hints = null; //create RValues list skipping Empty terminal and collecting grammar hints foreach (BnfTerm operand in operands) { if (operand == Grammar.CurrentGrammar.Empty) continue; //Collect hints as we go - they will be added to the next non-hint element GrammarHint hint = operand as GrammarHint; if (hint != null) { if (hints == null) hints = new GrammarHintList(); hints.Add(hint); continue; } //Check if it is a Terminal or Error element Terminal t = operand as Terminal; if (t != null) { prod.Flags |= ProductionFlags.HasTerminals; if (t.Category == TokenCategory.Error) prod.Flags |= ProductionFlags.IsError; } //Add the operand info and LR0 Item LR0Item item = new LR0Item(_lastItemId++, prod, prod.RValues.Count, hints); prod.LR0Items.Add(item); prod.RValues.Add(operand); hints = null; }//foreach operand //set the flags if (prod.RValues.Count == 0) prod.Flags |= ProductionFlags.IsEmpty; //Add final LRItem prod.LR0Items.Add(new LR0Item(_lastItemId++, prod, prod.RValues.Count, hints)); return prod; }
public LRItem(ParserState state, LR0Item core) { State = state; Core = core; _hashCode = unchecked (state.GetHashCode() + core.GetHashCode()); }
/// <summary> /// takes an LR0 state, and a tokenID, and produces the next state given the token and productions of the grammar /// </summary> int GotoLR0(int nState, int nTokenID, ref bool bAdded, ref int nPrecedence) { var gotoLR0 = new HashSet<int>(); var state = _lr0States[nState]; foreach (int nItem in state) { LR0Item item = _lr0Items[nItem]; if (item.Position < _productions[item.Production].Right.Length && (_productions[item.Production].Right[item.Position] == nTokenID)) { var newItem = new LR0Item(item.Production, item.Position + 1); int nNewItemID = GetLR0ItemID(newItem); gotoLR0.Add(nNewItemID); int nProductionPrecedence = _productionPrecedence[item.Production]; if (nPrecedence < nProductionPrecedence) { nPrecedence = nProductionPrecedence; } } } return gotoLR0.Count == 0 ? -1 : GetLR0StateID(LR0Closure(gotoLR0), ref bAdded); }
public LRItem(ParserState state, LR0Item core) { State = state; Core = core; }
/// <summary> /// Gets the ID for a particular LR0 Item /// </summary> int GetLR0ItemID(LR0Item item) { int nItemID = 0; foreach (LR0Item oItem in _lr0Items) { if (oItem.Equals(item)) { return nItemID; } nItemID++; } _lr0Items.Add(item); return nItemID; }
/// <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; }
private static int CompareLR0Items(LR0Item x, LR0Item y) { if (x.ID < y.ID) return -1; if (x.ID == y.ID) return 0; return 1; }
/// <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; }