/// <summary> /// Closes this item to a set of items /// </summary> /// <param name="closure">The list to close</param> /// <param name="map">The current helper map</param> public override void CloseTo(List <Item> closure, Dictionary <Rule, Dictionary <int, List <Item> > > map) { // the item was of the form [Var -> alpha .] (reduction) // nothing to do if (Action == LRActionCode.Reduce) { return; } // Get the next symbol in the item Symbol next = GetNextSymbol(); // Here the item is of the form [Var -> alpha . next beta] // If the next symbol is not a variable : do nothing // If the next symbol is a variable : Variable nextVar = next as Variable; if (nextVar == null) { return; } // Firsts is a copy of the Firsts set for beta (next choice) // Firsts will contains symbols that may follow Next // Firsts will therefore be the lookahead for child items TerminalSet firsts = new TerminalSet(GetNextChoice().Firsts); // If beta is nullifiable (contains ε) : if (firsts.Contains(Epsilon.Instance)) { // Remove ε firsts.Remove(Epsilon.Instance); // Add the item's lookaheads firsts.AddRange(lookaheads); } // For each rule that has Next as a head variable : foreach (Rule rule in nextVar.Rules) { if (!map.ContainsKey(rule)) { map.Add(rule, new Dictionary <int, List <Item> >()); } Dictionary <int, List <Item> > sub = map[rule]; if (sub.ContainsKey(0)) { List <Item> previouses = sub[0]; ItemLALR1 previous = previouses[0] as ItemLALR1; previous.Lookaheads.AddRange(firsts); } else { List <Item> items = new List <Item>(); sub.Add(0, items); ItemLALR1 New = new ItemLALR1(rule, 0, firsts); closure.Add(New); items.Add(New); } } }
/// <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> /// 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> /// Determines whether the specified <see cref="Hime.SDK.Grammars.LR.Item"/> is equal to the current <see cref="Hime.SDK.Grammars.LR.Item"/>. /// </summary> /// <param name='item'> /// The <see cref="Hime.SDK.Grammars.LR.Item"/> to compare with the current <see cref="Hime.SDK.Grammars.LR.Item"/>. /// </param> /// <returns> /// <c>true</c> if the specified <see cref="Hime.SDK.Grammars.LR.Item"/> is equal to the current /// <see cref="Hime.SDK.Grammars.LR.Item"/>; otherwise, <c>false</c>. /// </returns> public override bool ItemEquals(Item item) { ItemLALR1 tested = (ItemLALR1)item; if (!BaseEquals(tested)) { return(false); } if (lookaheads.Count != tested.lookaheads.Count) { return(false); } foreach (Terminal terminal in lookaheads) { if (!tested.lookaheads.Contains(terminal)) { return(false); } } return(true); }