Exemplo n.º 1
0
            private AltLoopStatus TryOneAlternative(int ip, VarStack varStack, ListPatternElem e, int k,
                                                    int marker, ListTerm RangeList, int i, BaseTerm t, ref bool negSearchSucceeded, BaseTerm searchTerm)
            {
                bool unified = searchTerm.Unify(t, varStack);

                if (e.IsNegSearch) // none of the terms in the inner loop may match. ~(a | b | c) = ~a & ~b & ~c
                {
                    if (unified)   // ... no point in investigating the other alternatives if one does
                    {
                        negSearchSucceeded = false;

                        return(AltLoopStatus.Break); // don't try the other alternatives
                    }

                    return(AltLoopStatus.TryNextDown); // non of the downranges matches may lead to a success
                }
                else
                {
                    if (unified &&                                                    // we found a match. Unify, and
                        TryBindingAltListVarToMatch(e.AltListBindVar, t, varStack) && // bind the AltListBindVar to the match
                        TryBindingRangeRelatedVars(e, i, RangeList, varStack))        // bind the range to the range variables
                    {
                        if (ip == pattern.Length - 1)                                 // this was the last pattern element
                        {
                            if (k == target.Count - 1)                                // both pattern and target exhausted
                            {
                                return(AltLoopStatus.MatchFound);
                            }
                        }
                        else if (UnifyTailEx(ip + 1, k + 1, varStack)) // now deal with the rest
                        {
                            return(AltLoopStatus.MatchFound);
                        }
                    }

                    // if we arrive here, it was not possible to ...
                    // (1) ... unify the range's SearchTerm with the target element, or
                    // (2) ... unify the range variable with the range list, or
                    // (3) ... successfully process the rest of the pattern and target
                    // Now unbind and try matching with the next target element
                    BaseTerm.UnbindToMarker(varStack, marker);

                    return(AltLoopStatus.TryNextDown); // try the next downrange match
                }
            }
Exemplo n.º 2
0
            // each call processes one element of pattern[]
            bool UnifyTailEx(int ip, int it, VarStack varStack)
            {
                ListPatternElem e            = (ListPatternElem)pattern[ip];
                Variable        rangeSpecVar = (Variable)e.RangeBindVar;
                NodeIterator    subtreeIterator;
                int             k;
                int             marker;
                ListTerm        RangeList = null;
                BaseTerm        tail      = null;
                int             minLen; // minimum required range length (number of range elements)
                int             maxLen; // maximum possible ...

                if (!DoLowerAndUpperboundChecks(ip, it, out minLen, out maxLen))
                {
                    return(false);
                }

                // scan the minimal number of range elements. Add them to the range list,
                // i.e. the last variable (if present) preceding the '{ , }'
                for (int i = 0; i < minLen; i++)
                {
                    if ((k = it + i) >= target.Count)
                    {
                        return(false);
                    }

                    AppendToRangeList(ref RangeList, rangeSpecVar, target[k], ref tail);
                }

                marker = varStack.Count; // register the point to which we must possibly undo unifications

                if (e.HasSearchTerm)
                {
                    // scan the elements up to the maximum range length, and the element immediately thereafter
                    for (int i = minLen; i <= maxLen; i++)
                    {
                        BaseTerm t = null;
                        k = it + i;

                        if (k == target.Count)
                        {
                            return(false);
                        }

                        bool negSearchSucceeded = true;         // iff none of the alternative term matches the target term

                        for (int j = 4; j < e.Args.Length; j++) // scan all AltSearchTerm alternatives (separated by '|')
                        {
                            BaseTerm      searchTerm    = e.AltSearchTerms[j];
                            DownRepFactor downRepFactor = null; // e.downRepFactor [j];
                            t = target[k];
                            AltLoopStatus status = AltLoopStatus.TryNextAlt;

                            if (downRepFactor == null)
                            {
                                status =
                                    TryOneAlternative(ip, varStack, e, k, marker, RangeList, i, t, ref negSearchSucceeded, searchTerm);

                                if (status == AltLoopStatus.MatchFound)
                                {
                                    return(true);
                                }
                            }
                            else // traverse the downRepFactor tree, which in principle may yield more than one match
                            {
                                subtreeIterator = new NodeIterator(t, searchTerm, downRepFactor.minLenTerm,
                                                                   downRepFactor.maxLenTerm, false, downRepFactor.bindVar, varStack);

                                foreach (BaseTerm match in subtreeIterator) // try -- if necessary -- each tree match with the current search term
                                {
                                    status =
                                        TryOneAlternative(ip, varStack, e, k, marker, RangeList, i, match, ref negSearchSucceeded, searchTerm);

                                    if (status == AltLoopStatus.MatchFound)
                                    {
                                        return(true);
                                    }

                                    if (status == AltLoopStatus.Break)
                                    {
                                        break;
                                    }
                                }
                            }

                            if (status == AltLoopStatus.Break)
                            {
                                break;
                            }
                        }

                        // at this point sufficient alternatives have been tried
                        if (e.IsNegSearch && negSearchSucceeded)                               // none of the terms matched => ok if binding succeeds
                        {
                            if (!TryBindingAltListVarToMatch(e.AltListBindVar, t, varStack) || // bind the AltListBindVar to the match
                                !TryBindingRangeRelatedVars(e, i, RangeList, varStack))        // bind the range to the range variables
                            {
                                return(false);                                                 // binding failed
                            }
                            if (ip == pattern.Length - 1)                                      // this was the last pattern element
                            {
                                if (k == target.Count - 1)                                     // both pattern and target exhausted
                                {
                                    return(true);
                                }
                            }
                            else if (UnifyTailEx(ip + 1, k + 1, varStack)) // now deal with the rest
                            {
                                return(true);
                            }
                        }
                        else if (i < maxLen) // append the rejected term to the range list and go try the next term
                        {
                            AppendToRangeList(ref RangeList, rangeSpecVar, t, ref tail);
                        }
                    }
                }
                else // a range without a subsequent search term (so followed by another range or end of pattern)
                {
                    for (int i = minLen; i <= maxLen; i++)
                    {
                        k = it + i;

                        if (k == target.Count)                                             // ok, target[k] does not exist, end of target hit
                        {
                            return(TryBindingRangeRelatedVars(e, i, RangeList, varStack)); // i is actual range length
                        }
                        // k is ok
                        if (i < maxLen)
                        {
                            AppendToRangeList(ref RangeList, rangeSpecVar, target[k], ref tail);
                        }

                        // now deal with the rest
                        if (TryBindingRangeRelatedVars(e, i, RangeList, varStack) &&
                            UnifyTailEx(ip + 1, k, varStack))
                        {
                            return(true);
                        }
                    }
                }

                // If we arrive here, no matching term was found in or immediately after the permitted range.
                // Therefore, undo any unifications made locally in this method and return with failure.
                if (marker != 0)
                {
                    BaseTerm.UnbindToMarker(varStack, marker);
                }

                return(false);
            }