Exemplo n.º 1
0
        /// <summary>
        /// partial, semi-ordered tree matching algorithm.
        ///
        /// iterate over target string, no backtracking
        /// maintain data about matches in series match:
        ///     indexes which are valid branched matches for the current index in target
        ///     record of which leaves in the matcher have been matched
        /// </summary>
        /// <param name="indexInSymbolTarget"></param>
        /// <param name="seriesMatch"></param>
        /// <returns>a mapping from all symbols in seriesMatch back into the target string</returns>
        public bool MatchesForward(
            NativeMultipleHashSets.HashSetSlice includeSymbolsSet,
            int indexInSymbolTarget,
            SymbolSeriesSuffixMatcher seriesMatch,
            SymbolString <float> symbolString,
            int firstParameterCopyIndex,
            NativeArray <float> parameterCopyMemory,
            out byte paramsCopiedToMem,
            TmpNativeStack <BranchEventData> helperStack
            )
        {
            if (!seriesMatch.HasGraphIndexes)
            {
                // this should be done in the parsing/compiling phase. should only have to happen once for the whole system, per matching rule.
                throw new System.Exception("graph indexes should be precomputed");
                //seriesMatch.ComputeGraphIndexes(branchOpenSymbol, branchCloseSymbol);
            }

            // keep count of how many more matches are required at each level of the tree.
            //  starts out as a copy of the child count array. each leaf will be at 0, and will go negative when matched.
            //var remainingMatchesAtIndexes = seriesMatch.childrenCounts.Clone() as int[];
            return(MatchesForwardsAtIndexOrderingInvariant(
                       includeSymbolsSet,
                       indexInSymbolTarget,
                       seriesMatch,
                       symbolString,
                       firstParameterCopyIndex,
                       parameterCopyMemory,
                       out paramsCopiedToMem,
                       helperStack));
        }
Exemplo n.º 2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="indexInSymbolTarget"></param>
        /// <param name="seriesMatch"></param>
        /// <returns>whether the match succeeded or not</returns>
        public bool MatchesBackwards(
            NativeMultipleHashSets.HashSetSlice includedSymbolSet,
            int indexInSymbolTarget,
            SymbolSeriesPrefixMatcher seriesMatch,
            SymbolString <float> symbolString,
            int firstParameterCopyIndex,
            NativeArray <float> parameterCopyMemory,
            out byte paramsCopiedToMem)
        {
            indexInSymbolTarget--;
            int matchingIndex = seriesMatch.graphNodeMemSpace.length - 1;

            paramsCopiedToMem = 0;

            for (; matchingIndex >= 0 && indexInSymbolTarget >= 0;)
            {
                var symbolToMatch = nativeRuleData.prefixMatcherSymbols[matchingIndex + seriesMatch.graphNodeMemSpace.index];
                while (indexInSymbolTarget >= 0)
                {
                    var currentSymbol = symbolString.symbols[indexInSymbolTarget];
                    if (!includedSymbolSet.Contains(currentSymbol) || currentSymbol == branchOpenSymbol)
                    {
                        indexInSymbolTarget--;
                    }
                    else if (currentSymbol == branchCloseSymbol)
                    {
                        indexInSymbolTarget = FindOpeningBranchIndexReadonly(indexInSymbolTarget) - 1;
                    }
                    else if (currentSymbol == symbolToMatch.targetSymbol &&
                             symbolToMatch.parameterLength == symbolString.parameters[indexInSymbolTarget].length)
                    {
                        // copy the parameters in reverse order, so they can be reversed in-place at end
                        //  on success
                        var paramIndexing = symbolString.parameters[indexInSymbolTarget];
                        for (int i = paramIndexing.length - 1; i >= 0; i--)
                        {
                            parameterCopyMemory[paramsCopiedToMem + firstParameterCopyIndex] = symbolString.parameters[paramIndexing, i];
                            paramsCopiedToMem++;
                        }

                        indexInSymbolTarget--;
                        matchingIndex--;
                        break;
                    }
                    else
                    {
                        return(false);
                    }
                }
            }
            if (matchingIndex == -1)
            {
                ReverseRange(parameterCopyMemory, firstParameterCopyIndex, paramsCopiedToMem);
                return(true);
            }
            return(false);
        }
Exemplo n.º 3
0
        /// <summary>
        /// check for a match, enforcing the same ordering in the target match as defined in the matching pattern.
        /// </summary>
        /// <param name="originIndexInTarget"></param>
        /// <param name="seriesMatch"></param>
        /// <param name="consumedTargetIndexes"></param>
        /// <returns></returns>
        private bool MatchesForwardsAtIndexOrderingInvariant(
            NativeMultipleHashSets.HashSetSlice includeSymbolSet,
            int originIndexInTarget,
            SymbolSeriesSuffixMatcher seriesMatch,
            SymbolString <float> symbolString,
            int firstParameterCopyIndex,
            NativeArray <float> parameterCopyMemory,
            out byte paramsCopiedToMem,
            TmpNativeStack <BranchEventData> helperStack
            )
        {
            helperStack.Reset();
            var targetParentIndexStack = helperStack;// new TmpNativeStack<BranchEventData>(5);// new Stack<BranchEventData>();

            int currentParentIndexInTarget  = originIndexInTarget;
            var targetIndexesToMatchIndexes = new NativeHashMap <int, int>(seriesMatch.graphNodeMemSpace.length, Allocator.Temp);// new Dictionary<int, int>();

            paramsCopiedToMem = 0;

            var indexInMatchDFSState = seriesMatch.GetImmutableDepthFirstIterationState(nativeRuleData);

            targetIndexesToMatchIndexes.Add(originIndexInTarget, indexInMatchDFSState.currentIndex);
            if (!indexInMatchDFSState.Next(out indexInMatchDFSState))
            {
                return(true);
                // if the match is empty, automatically matches.
                //return targetIndexesToMatchIndexes;
            }


            for (int indexInTarget = originIndexInTarget + 1; indexInTarget < symbolString.Length; indexInTarget++)
            {
                var targetSymbol = symbolString[indexInTarget];

                if (!includeSymbolSet.Contains(targetSymbol))
                {
                    continue;
                }
                if (targetSymbol == branchOpenSymbol)
                {
                    targetParentIndexStack.Push(new BranchEventData
                    {
                        currentParentIndex      = currentParentIndexInTarget,
                        openBranchSymbolIndex   = indexInTarget,
                        paramsCopiedAtThisPoint = paramsCopiedToMem
                    });
                }
                else if (targetSymbol == branchCloseSymbol)
                {
                    // will encounter a close symbol in one of two cases:
                    //  1. the branch in target has exactly matched the branch in the matcher, and we should just step down
                    //  2. the branch in target has terminated early, meaning we must step down the branch chain and also
                    //      reverse the matcher DFS back to a common ancenstor
                    if (targetParentIndexStack.Count <= 0)
                    {
                        // if we encounter the end of the branch which contains the origin index before full match, fail.
                        return(false);
                    }
                    var lastBranch = targetParentIndexStack.Pop();
                    currentParentIndexInTarget = lastBranch.currentParentIndex;
                    //paramsCopiedToMem = lastBranch.paramsCopiedAtThisPoint;

                    var parentInMatch       = targetIndexesToMatchIndexes[currentParentIndexInTarget];
                    var parentOfSearchState = indexInMatchDFSState.GetParentIndex();
                    if (parentInMatch != parentOfSearchState)
                    {
                        // if the parents dont match, that means that the algo will be stepping backwards to the last branch sybmol.
                        paramsCopiedToMem = lastBranch.paramsCopiedAtThisPoint;
                    }
                }
                else
                {
                    // reverse the DFS in matcher, back to the last point which shares a parent with the current parent
                    // this acts to ensure the entry to the match has a shared parent, if at all possible.
                    //   the reversal is necessary when a branching structure failed to match in the last step
                    var parentInMatch = targetIndexesToMatchIndexes[currentParentIndexInTarget];
                    if (indexInMatchDFSState.FindPreviousWithParent(out var reversedMatchIndex, parentInMatch))
                    {
                        indexInMatchDFSState = reversedMatchIndex;
                    }

                    var indexInMatch = indexInMatchDFSState.currentIndex;
                    var currentTargetMatchesMatcher = TargetSymbolMatchesAndParentMatches(
                        seriesMatch,
                        targetIndexesToMatchIndexes,
                        currentParentIndexInTarget,
                        indexInTarget,
                        indexInMatch,
                        symbolString);
                    if (currentTargetMatchesMatcher)
                    {
                        targetIndexesToMatchIndexes.Add(indexInTarget, indexInMatch);

                        var paramsToCopy = symbolString.parameters[indexInTarget];
                        for (int paramIndex = 0; paramIndex < paramsToCopy.length; paramIndex++)
                        {
                            parameterCopyMemory[firstParameterCopyIndex + paramsCopiedToMem] = symbolString.parameters[paramsToCopy, paramIndex];
                            paramsCopiedToMem++;
                        }

                        currentParentIndexInTarget = indexInTarget; // series continuation includes implicit parenting
                        if (!indexInMatchDFSState.Next(out indexInMatchDFSState))
                        {
                            return(true);
                        }
                    }
                    else
                    {
                        // symbol in target isn't a valid match, so no further symbols in the current target branching structure can match.
                        // rewind back to the previous branching symbol, and skip this whole structure.
                        // Or if we're not in a nested structure, fail.
                        if (targetParentIndexStack.Count <= 0)
                        {
                            return(false);
                        }

                        var lastBranch = targetParentIndexStack.Pop();
                        currentParentIndexInTarget = lastBranch.currentParentIndex;
                        //paramsCopiedToMem = lastBranch.paramsCopiedAtThisPoint;
                        indexInTarget = FindClosingBranchIndexReadonly(lastBranch.openBranchSymbolIndex);


                        var parentInMatch1      = targetIndexesToMatchIndexes[currentParentIndexInTarget];
                        var parentOfSearchState = indexInMatchDFSState.GetParentIndex();
                        if (parentInMatch1 != parentOfSearchState)
                        {
                            // if the parents dont match, that means that the algo will be stepping backwards to the last branch sybmol on the next update.
                            paramsCopiedToMem = lastBranch.paramsCopiedAtThisPoint;
                        }
                    }
                }
            }
            return(false);
        }