/// <summary> /// Initializes this state /// </summary> /// <param name="kernel">The state's kernel</param> /// <param name="items">The state's items</param> public State(StateKernel kernel, List <Item> items) { this.kernel = kernel; this.items = items; children = new Dictionary <Symbol, State>(new Symbol.EqualityComparer()); openingContexts = new Dictionary <Terminal, List <int> >(); }
/// <summary> /// Builds the propagation table /// </summary> /// <remarks> /// The propagation table is a couple of list where /// items in the first list propagate to items in the second list at the same index /// </remarks> private void BuildPropagationTable() { for (int i = 0; i != kernels.Count; i++) { StateKernel kernelLALR1 = kernels[i]; State stateLR0 = graphLR0.States[i]; // For each LALR(1) item in the kernel // Only the kernel needs to be examined as the other items will be discovered and treated // with the dummy closures foreach (ItemLALR1 itemLALR1 in kernelLALR1.Items) { // If ItemLALR1 is of the form [A -> alpha .] // => The closure will only contain the item itself // => Cannot be used to generate or propagate lookaheads if (itemLALR1.Action == LRActionCode.Reduce) { continue; } // Item here is of the form [A -> alpha . beta] // Create the corresponding dummy item : [A -> alpha . beta, dummy] // This item is used to detect lookahead propagation ItemLR1 dummyItem = new ItemLR1(itemLALR1.BaseRule, itemLALR1.DotPosition, Dummy.Instance); StateKernel dummyKernel = new StateKernel(); dummyKernel.AddItem(dummyItem); State dummySet = dummyKernel.GetClosure(); // For each item in the closure of the dummy item foreach (ItemLR1 item in dummySet.Items) { // If the item action is a reduction // => OnSymbol for this item will be created by the LALR(1) closure // => Do nothing if (item.Action == LRActionCode.Reduce) { continue; } // Get the child item in the child LALR(1) kernel State childLR0 = stateLR0.GetChildBy(item.GetNextSymbol()); StateKernel childKernel = kernels[childLR0.ID]; ItemLALR1 childLALR1 = (ItemLALR1)GetEquivalentInSet(childKernel, item.GetChild()); // If the lookaheads of the item in the dummy set contains the dummy terminal if (item.Lookahead == Dummy.Instance) { // => Propagation from the parent item to the child propagOrigins.Add(itemLALR1); propagTargets.Add(childLALR1); } else { // => Spontaneous generation of lookaheads childLALR1.Lookaheads.Add(item.Lookahead); } } } } }
/// <summary> /// Gets the item equivalent to the specified one in the kernel /// </summary> /// <param name="kernel">A kernel</param> /// <param name="equivalent">An item</param> /// <returns>The equivalent item</returns> private static Item GetEquivalentInSet(StateKernel kernel, Item equivalent) { foreach (Item item in kernel.Items) { if (item.BaseEquals(equivalent)) { return(item); } } return(null); }
/// <summary> /// Determines whether the given state (as a kernel) is already in this graph /// </summary> /// <param name="kernel">A kernel</param> /// <returns>The corresponding state, or null if none is found</returns> public State ContainsState(StateKernel kernel) { foreach (State potential in states) { if (potential.Kernel.Equals(kernel)) { return(potential); } } return(null); }
/// <summary> /// Determines whether the specified <see cref="Hime.SDK.Grammars.LR.StateKernel"/> is equal to /// the current <see cref="Hime.SDK.Grammars.LR.StateKernel"/>. /// </summary> /// <param name='kernel'> /// The <see cref="Hime.SDK.Grammars.LR.StateKernel"/> to compare with the current <see cref="Hime.SDK.Grammars.LR.StateKernel"/>. /// </param> /// <returns> /// <c>true</c> if the specified <see cref="Hime.SDK.Grammars.LR.StateKernel"/> is equal to the /// current <see cref="Hime.SDK.Grammars.LR.StateKernel"/>; otherwise, <c>false</c>. /// </returns> public bool Equals(StateKernel kernel) { if (items.Count != kernel.items.Count) { return(false); } if (dictItems.Count != kernel.dictItems.Count) { return(false); } foreach (Rule rule in dictItems.Keys) { if (!kernel.dictItems.ContainsKey(rule)) { return(false); } Dictionary <int, List <Item> > left = dictItems[rule]; Dictionary <int, List <Item> > right = kernel.dictItems[rule]; if (left.Count != right.Count) { return(false); } foreach (int position in left.Keys) { if (!right.ContainsKey(position)) { return(false); } List <Item> l1 = left[position]; List <Item> l2 = right[position]; if (l1.Count != l2.Count) { return(false); } foreach (Item item in l1) { if (!l2.Contains(item)) { return(false); } } } } return(true); }
/// <summary> /// Builds the kernels /// </summary> private void BuildKernels() { for (int i = 0; i != graphLR0.States.Count; i++) { State stateLR0 = graphLR0.States[i]; StateKernel kernelLALR1 = new StateKernel(); foreach (Item itemLR0 in stateLR0.Kernel.Items) { ItemLALR1 itemLALR1 = new ItemLALR1(itemLR0); if (i == 0) { itemLALR1.Lookaheads.Add(Epsilon.Instance); } kernelLALR1.AddItem(itemLALR1); } kernels.Add(kernelLALR1); } }
/// <summary> /// Gets the LR(1) graph /// </summary> /// <returns>The corresponding LR(1) graph</returns> private Graph GetGraphLR1() { // Create the first set Variable axiom = grammar.GetVariable(Grammar.GENERATED_AXIOM); ItemLR1 item = new ItemLR1(axiom.Rules[0], 0, Epsilon.Instance); StateKernel kernel = new StateKernel(); kernel.AddItem(item); State state0 = kernel.GetClosure(); Graph result = new Graph(state0); // Construct the graph foreach (State state in result.States) { state.BuildReductions(new StateReductionsLR1()); } return(result); }
/// <summary> /// Builds the given parent graph /// </summary> /// <param name="graph">The parent graph</param> public void BuildGraph(Graph graph) { // Shift dictionnary for the current set Dictionary <Symbol, StateKernel> shifts = new Dictionary <Symbol, StateKernel>(); // Build the children kernels from the shift actions foreach (Item item in items) { // Ignore reduce actions if (item.Action == LRActionCode.Reduce) { continue; } Symbol next = item.GetNextSymbol(); if (shifts.ContainsKey(next)) { shifts[next].AddItem(item.GetChild()); } else { StateKernel nextKernel = new StateKernel(); nextKernel.AddItem(item.GetChild()); shifts.Add(next, nextKernel); } } // Close the children and add them to the graph foreach (Symbol next in shifts.Keys) { StateKernel nextKernel = shifts[next]; State child = graph.ContainsState(nextKernel); if (child == null) { child = nextKernel.GetClosure(); graph.Add(child); } children.Add(next, child); } // Build the context data foreach (Item item in items) { if (item.BaseRule.Context != 0 && item.DotPosition == 0 && item.Action == LRActionCode.Shift) { // this is the opening of a context List <Terminal> openingTerminals = new List <Terminal>(); Symbol first = item.GetNextSymbol(); if (first is Terminal) { openingTerminals.Add(first as Terminal); } else { openingTerminals.AddRange((first as Variable).Firsts); } foreach (Terminal terminal in openingTerminals) { List <int> contexts; if (openingContexts.ContainsKey(terminal)) { contexts = openingContexts[terminal]; } else { contexts = new List <int>(); openingContexts.Add(terminal, contexts); } if (!contexts.Contains(item.BaseRule.Context)) { contexts.Add(item.BaseRule.Context); } } } } }