public Tuple <StackElement <SYMBOL_ENUM, TREE_NODE>, IEnumerable <StackElement <SYMBOL_ENUM, TREE_NODE> > > TakeLast(int count) { StackElement <SYMBOL_ENUM, TREE_NODE> leaf = currentStackLeaf; IEnumerable <StackElement <SYMBOL_ENUM, TREE_NODE> > tail = takeLast(ref leaf, count).ToList(); return(Tuple.Create(leaf, tail)); }
private StackElement <SYMBOL_ENUM, TREE_NODE> addToStack(Command <SYMBOL_ENUM, TREE_NODE> command, AttachPoint <SYMBOL_ENUM, TREE_NODE> attachPoint, SYMBOL_ENUM symbol, int markWith, string text, Option <object> userObject, bool recovered) { // if stack is empty and we are adding start symbol (meaning full, successful parse) if (attachPoint.Stack == null && symbol.Equals(StartSymbol) && IsEndOfInput) { return(stackMaster.Add(command.IsShift, attachPoint, new StackElement <SYMBOL_ENUM, TREE_NODE>() { Symbol = StartSymbol, MarkedWith = markWith, UserObject = userObject, NodeIndex = actionTable.StartNodeIndex, IsRecovered = recovered, RecorderLink = new CommandRecorder <SYMBOL_ENUM, TREE_NODE>(command, messages) })); } else { int target_id; IEnumerable <NfaCell <SYMBOL_ENUM, TREE_NODE> > recovery_items; // compute where we will go with the symbol in DFA if (actionTable.TryGetTarget(anchoredDfaNode(attachPoint.Stack), symbol, out target_id, out recovery_items)) { StackElement <SYMBOL_ENUM, TREE_NODE> added = stackMaster.Add(command.IsShift, attachPoint, new StackElement <SYMBOL_ENUM, TREE_NODE>() { Symbol = symbol, MarkedWith = markWith, TextInfo = text, UserObject = userObject, Coordinates = Coordinates, NodeIndex = target_id, IsRecovered = recovered, RecorderLink = new CommandRecorder <SYMBOL_ENUM, TREE_NODE>(command, messages) }); added.RecoveryItems = recovery_items; return(added); } else { if (options.Trace) { System.IO.File.WriteAllLines("parser_history.dump", ParseLog.Select(it => it.ToString() + Environment.NewLine)); } throw new Exception("Internal parser error on symbol: " + this.symbolsRep.Get(symbol) + " at node: " + anchoredDfaNode(attachPoint.Stack) + " with stack: " + stackToString(attachPoint.Stack)); } } }
protected int anchoredDfaNode(StackElement <SYMBOL_ENUM, TREE_NODE> stackAnchor) { if (stackAnchor == null) { return(actionTable.StartNodeIndex); } else { return(stackAnchor.NodeIndex); } }
public bool RemoveStack() { if (currentStackLeaf != null) { currentStackLeaf.RemoveTail(); } currentStackLeaf = null; return(stackLeaves.Count > 0); }
internal void RemoveTail() { if (PreviousElement == null || ChildrenCount > 0) { return; } StackElement <SYMBOL_ENUM, TREE_NODE> prev = PreviousElement; TryDetach(); prev.RemoveTail(); }
private IEnumerable <StackElement <SYMBOL_ENUM, TREE_NODE> > removeLastWhile(ref StackElement <SYMBOL_ENUM, TREE_NODE> leaf, Func <StackElement <SYMBOL_ENUM, TREE_NODE>, bool> predicate) { if (leaf == null || !predicate(leaf)) { return(emptyStack); } else { var last = leaf; leaf = leaf.PreviousElement; last.TryDetach(); return(removeLastWhile(ref leaf, predicate).Concat(last)); } }
// in current form, Add assumes there will be added something because of shift, and then because of reduce // i.e. it won't handle correctly two reduces in a row (for the same stack -- currentLeaf) public StackElement <SYMBOL_ENUM, TREE_NODE> Add(bool inputAdvance, AttachPoint <SYMBOL_ENUM, TREE_NODE> attachPoint, StackElement <SYMBOL_ENUM, TREE_NODE> stackElement) { attachPoint.FixNulls(inputAdvance, currentStackLeaf); if (attachPoint.Recorder != null) { attachPoint.Recorder.RecorderLink.Add(stackElement.RecorderLink); } // do not change real input index, because we might fork // however, after this we cannot really do anything with input now, do we? stackElement.InputIndex = input.Offset + (inputAdvance ? 1 : 0); stackElement.Id = ++stackElementIdCounter; if (attachPoint.Stack == null) { if (currentStackForkId.HasValue) { stackElement.ForkId = currentStackForkId.Value; } else { stackElement.ForkId = ++totalForkCounter; } } else { attachPoint.Stack.Add(stackElement); if (attachPoint.Stack.ChildrenCount == 1) { // it could be Add after reduce (removing), // so we don't want to get id from middle of stack, instead we use current id stackElement.ForkId = currentStackForkId.Value; currentStackForkId = null; // mark current stack id as used (because we can have fork after that) } else { stackElement.ForkId = ++totalForkCounter; } } // store new stack stackLeaves.Enqueue(stackElement); return(stackElement); }
public void LoopOverStacks() { if (stackLeaves.Count == 0) { currentStackLeaf = null; input.Offset = 0; currentStackForkId = 0; } else { currentStackLeaf = stackLeaves.Dequeue(); input.Offset = currentStackLeaf.InputIndex; currentStackForkId = currentStackLeaf.ForkId; } }
private string stackToString(StackElement <SYMBOL_ENUM, TREE_NODE> stackAnchor) { if (stackAnchor == null) { return("[0]"); } else { return("[" + stackAnchor.ForkId + "] " + String.Join(" ", stackAnchor.Iterate().TakeTail(historyHorizon).Select(it => (it.IsRecoverable ? "@" : "") + (it.IsRecovered ? "!" : "") + symbolsRep.Get(it.Symbol) + (it.ValueContent != null ? "=" + it.ValueContent : "") + "(" + it.NodeIndex + ")"))); } }
public void FixNulls(bool inputAdvance, StackElement <SYMBOL_ENUM, TREE_NODE> currentStackLeaf) { // Stack can be null for reduce move as well, but if it is for reduce we cannot "fix" null // because we are reducing stack to zero, so we cannot attach to anything if (Stack == null && inputAdvance) // comes from shift move { Stack = currentStackLeaf; } // since recorder increases in all cases (shift, reduce) we can always fix the null // btw. null is the effect the parser stack tail was empty // (because we reduced by empty rule or because we just started parsing) if (Recorder == null) { Recorder = currentStackLeaf; } }
private IEnumerable <StackElement <SYMBOL_ENUM, TREE_NODE> > takeLast(ref StackElement <SYMBOL_ENUM, TREE_NODE> leaf, int count) { if (count == 0) { return(emptyStack); } else if (leaf == null) { throw new ArgumentException("PARSER INTERNAL ERROR: Stack is not that long: " + Stack.Count() + " vs. " + count); } else { StackElement <SYMBOL_ENUM, TREE_NODE> last = leaf; leaf = leaf.PreviousElement; return(takeLast(ref leaf, count - 1).Concat(last)); } }
private bool makeReduction(ActionRecoveryEnum findAction, NfaCell <SYMBOL_ENUM, TREE_NODE> reduceItem, AttachPoint <SYMBOL_ENUM, TREE_NODE> attachPoint, IEnumerable <StackElement <SYMBOL_ENUM, TREE_NODE> > stackTail) { // if taboo symbol was used, ignore this reduction if (reduceItem.ProductionTabooSymbols != null && reduceItem.ProductionTabooSymbols.SyncZip(stackTail.Select(it => it.MarkedWith)).Any(it => it.Item1.Contains(it.Item2))) { if (options.Trace) { parseLog.Last.Value.Reduced.Add(ParseHistory.Reduce + " rejected (taboo filter)"); } return(false); } string trace = null; if (options.Trace) { trace = ParseHistory.Reduce + " " + symbolsRep.Get(reduceItem.LhsSymbol); } // no recovery from reduce (reduce cannot be recovered by itself, only by prior recovery point) StackElement <SYMBOL_ENUM, TREE_NODE> added = addToStack(Command.Reduced(reduceItem), attachPoint: attachPoint, symbol: reduceItem.LhsSymbol, markWith: reduceItem.ProductionMark, text: String.Join(textInfoSep, stackTail.Select(it => it.TextInfo)), userObject: new Option <object>(), recovered: findAction == ActionRecoveryEnum.Recovered); if (options.Trace) { parseLog.Last.Value.Reduced.Add(trace + "[" + added.ForkId + "]"); } return(true); }
private void makeShift(ActionRecoveryEnum findAction) { if (options.Trace) { parseLog.Last.Value.Shifted = ParseHistory.Shift; } // do not advance input here, because we can fork after that ITokenMatch <SYMBOL_ENUM> input_head = stackMaster.InputHead; StackElement <SYMBOL_ENUM, TREE_NODE> added = addToStack(Command.Shifted <SYMBOL_ENUM, TREE_NODE>(), attachPoint: new AttachPoint <SYMBOL_ENUM, TREE_NODE>(lastOfStackOrNull, //this makes it compatible with anchor of reduction lastOfStackOrNull), symbol: input_head.Token, markWith: Productions.NoMark, text: input_head.Text, userObject: new Option <object>(input_head.Value), recovered: findAction == ActionRecoveryEnum.Recovered); if (options.Trace) { parseLog.Last.Value.Shifted += "[" + added.ForkId + "]"; } }
public AttachPoint(StackElement <SYMBOL_ENUM, TREE_NODE> stack, StackElement <SYMBOL_ENUM, TREE_NODE> recorder) { this.Stack = stack; this.Recorder = recorder; }
internal void Add(StackElement <SYMBOL_ENUM, TREE_NODE> child) { ++ChildrenCount; child.PreviousElement = this; }