Пример #1
0
 // Goes recursively, decreasing currentLevel until 0.
 // Enumerator returns the same object for every yield, and it is the same object as its parameter 'path'. 
 // We do it to reuse a single StackPath instance in all iterations
 private IEnumerable<GlrStackSlice> EnumerateTopStackSlices(GlrStackItem current, int currentLevel, GlrStackSlice path) {
   path.Items[currentLevel] = current;
   if (currentLevel == 0) { // we reach the start of the path
     path.PrecedingItems = current.Previous;
     yield return path;
   } else {
     foreach (var prev in current.Previous)
       foreach (var subPath in EnumerateTopStackSlices(prev, currentLevel - 1, path)) {
         yield return path; //pass path from child
       }
   }
 }
Пример #2
0
 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
Пример #3
0
 private IEnumerable<GlrStackSlice> EnumerateTopStackSlices(GlrStackItem current, GlrStackSlice slice) {
   if (slice.Length == 0) {
     // special case, no child elements - empty production; we generate a single path consisting of 0 elements and PrecedingItems with only 'current' element. 
     // Note that PrecedingItems are those items (states) that will be used as bases (popped states)
     // from which we will shift over created non-terminal. In case of empty production the base is the top element itself.
     slice.PrecedingItems = new List<GlrStackItem>();
     slice.PrecedingItems.Add(current);
     return new GlrStackSlice[] {slice};
   } else
     return EnumerateTopStackSlices(current, slice.Length - 1, slice);
 }