public void ExecuteReduces(GlrStep step, GlrStackItem stackTop) { var inputTerm = step.Input.Term; GlrParserAction actionInfo; if (!stackTop.State.GlrActions.TryGetValue(inputTerm, out actionInfo)) { step.Discarded.Add(stackTop); return; } // if this top is elligible for shift on input, add it to step.ShiftBases if (actionInfo.Shifts.Count > 0) step.ShiftBases.Add(stackTop); foreach (var reduceItem in actionInfo.Reduces) { if (!reduceItem.Lookaheads.Contains(inputTerm)) continue; //execute reduce var prod = reduceItem.Core.Production; var prodLen = prod.RValues.Count; var sliceBuffer = new GlrStackSlice(prodLen); foreach (var slice in EnumerateTopStackSlices(stackTop, sliceBuffer)) { // the slice contains top stack elements, we can now try to reduce var newNode = prod.ExecuteReduce(slice.Items.Select(el => el.ParseNode)); //Shift over newNode from all stack elements preceding reduced segment foreach (var prev in sliceBuffer.PrecedingItems) { GlrParserAction actionFromPrev; if (!prev.State.GlrActions.TryGetValue(newNode.Term, out actionFromPrev) || actionFromPrev.Shifts.Count == 0) // TODO: possible it never happens in LALR, investigate! continue; // no shifts over newNode; // find next state after shifting node var stateAfterShift = actionFromPrev.Shifts[0].ShiftedItem.State; // do not check here if this state is compatible with input; if not it will be discarded inside the ExeduceReduces call that follows var itemAfterShift = new GlrStackItem(stateAfterShift, newNode, prev); ExecuteReduces(step, itemAfterShift); }// foreach prev }//foreach path }//foreach reduce }//method
}//method public void ExecuteShift(GlrStep step) { //execute shifts on ShiftBases over input. Merge stack elements with the same state - see merging suffixes in Parsing Techniques foreach (var shiftFrom in step.ShiftBases) { GlrParserAction action; if (!shiftFrom.State.GlrActions.TryGetValue(step.Input.Term, out action)) continue; // if (action.Shifts.Count == 0) continue; // that never happens, step.ShiftBases has only items that have shifts over input var nextState = action.Shifts[0].ShiftedItem.State; GlrStackItem nextItem; if (step.Shifts.TryGetValue(nextState, out nextItem)) nextItem.Previous.Add(shiftFrom); //add back link to existing stack elem with the same state else // create new stack element step.Shifts[nextState] = new GlrStackItem(nextState, step.Input, shiftFrom); } }