public int GetHashCode(SingleState <SYMBOL_ENUM, TREE_NODE> obj) { return(obj.LhsSymbol.GetHashCode() ^ obj.RhsSeenCount // this is the number already ^ obj.RhsUnseenSymbols.SequenceHashCode() ^ (obj.Production.UserAction == null ? 0 : obj.Production.UserAction.GetHashCode())); }
public static SingleState <SYMBOL_ENUM, TREE_NODE> CreateShiftStateFrom(int nodeId, int stateId, SingleState <SYMBOL_ENUM, TREE_NODE> source) { var result = new SingleState <SYMBOL_ENUM, TREE_NODE>(Tuple.Create(nodeId, stateId), source.RhsSeenCount + 1, source.Production); result.shiftParents.Add(source); return(result); }
public bool Equals(SingleState <SYMBOL_ENUM, TREE_NODE> x, SingleState <SYMBOL_ENUM, TREE_NODE> y) { if (Object.ReferenceEquals(x, y)) { return(true); } if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) { return(false); } // this is classic take -- just compare production and stage of it, that's all if (x.Production == y.Production && x.RhsSeenCount == y.RhsSeenCount) { return(true); } // this is custom compare (it is NOT a replacement!) -- it focuses on comparing the execution of the user action // please note, that the active parameters of the user action plays crucial role here if ((x.LhsSymbol.Equals(y.LhsSymbol) // this condition can be dropped __WHEN__ parser recovery no longer relies on that data (the number of seen symbols) && x.RhsSeenCount == y.RhsSeenCount // only unseen symbols really matters, because what we've already saw is a history and does not influence present state && x.RhsUnseenSymbols.SequenceEqual(y.RhsUnseenSymbols) // user action EXECUTION has to be identical && NaiveLanguageTools.Parser.UserActionInfo.ExecutionEquals(x.Production.UserAction, x.RhsSeenCount, y.Production.UserAction, y.RhsSeenCount))) { return(true); } return(false); }
private void addClosures(SingleState <SYMBOL_ENUM, TREE_NODE> sourceState, Productions <SYMBOL_ENUM, TREE_NODE> productions, int lookaheadWidth) { if (!sourceState.HasIncomingSymbol) { return; } // find productions for that symbol foreach (Production <SYMBOL_ENUM, TREE_NODE> prod in productions.FilterByLhs(sourceState.IncomingSymbol)) { SingleState <SYMBOL_ENUM, TREE_NODE> existing; // getting "impostor" object just for sake of FAST comparison (no memory allocations) if (items.TryGetValue(SingleState <SYMBOL_ENUM, TREE_NODE> .CreateClosureComparisonStateFrom(prod), out existing)) // [@STATE_EQ] { // switching closure links to existing state existing.AddClosureParent(sourceState); } else { // creating real state object var state = SingleState <SYMBOL_ENUM, TREE_NODE> .CreateClosureStateFrom(InternalId, items.Count, sourceState, prod); items.Add(state); addClosures(state, productions, lookaheadWidth); // recursive call } } }
public static SingleState <SYMBOL_ENUM, TREE_NODE> CreateClosureStateFrom(int nodeId, int stateId, SingleState <SYMBOL_ENUM, TREE_NODE> source, Production <SYMBOL_ENUM, TREE_NODE> production) { var result = new SingleState <SYMBOL_ENUM, TREE_NODE>(Tuple.Create(nodeId, stateId), 0, production); result.closureParents.Add(source); return(result); }
public bool Merge(SingleState <SYMBOL_ENUM, TREE_NODE> incoming, Func <int> timeStamp) { // here do not merge closure, because closures are inter-node links // and the incoming state will be deleted -- thus all inter-node links // would be invalid (in sense of grammar) shiftParents.AddRange(incoming.shiftParents); if (!AfterLookaheads.Add(incoming.AfterLookaheads)) { return(false); } lookaheadsStamp = timeStamp(); return(true); }
public void AddClosureParent(SingleState <SYMBOL_ENUM, TREE_NODE> state) { this.closureParents.Add(state); }