Esempio 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 last, 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
                }
            }
Esempio n. 2
0
            // calculated the upper and lower bounds imposed by the remainder of the pattern
            bool DoLowerAndUpperboundChecks(int ip, int it, out int minLen, out int maxLen)
            {
                ListPatternElem e           = (ListPatternElem)pattern[ip];
                int             minRangeLen = e.MinRangeLen;             // min and max range length ...
                int             maxRangeLen = e.MaxRangeLen;             // ... as specified in ListPatternElem
                int             termLen     = (e.HasSearchTerm ? 1 : 0); // take the search term into account if present

                // calculated the minimum required and maximum possible range length,
                // given the rest of the pattern and the remaining part of the target

                int minRequiredForRestOfRanges = 0;
                int maxPossibleForRestOfRanges = 0;

                // calculated the minimum and maximum remaining pattern length (and
                // hence the number of target terms that should still be available)
                for (int i = ip + 1; i < pattern.Length; i++)
                {
                    minRequiredForRestOfRanges += (e = (ListPatternElem)pattern[i]).MinRangeTermLen;
                    maxPossibleForRestOfRanges  = ListPatternElem.SaveAdd(maxPossibleForRestOfRanges, e.MaxRangeTermLen);
                }

                // calculate the number of target terms that are actually available
                int remainingTargetLength = target.Count - it; // 'it' is the index of the first of the remaining target terms
                                                               // calculate the lower bound for the number of target terms to be consumed by this range
                int minRequiredRangeLen = Math.Max(0, remainingTargetLength - termLen - maxPossibleForRestOfRanges);
                // calculate the upper bound for the number of target terms to be consumed by this range
                int maxPossibleRangeLen = remainingTargetLength - termLen - minRequiredForRestOfRanges;

                // the bounds just calculated must be adjusted with the values specified in the range descriptor itself.
                // the lower bound should always at least be equal to minRequiredRangeLen, so take the highest value
                minLen = Math.Max(minRangeLen, minRequiredRangeLen);
                // the upper bound should always at most be equal to maxPossibleRangeLen, so take the lowest value
                maxLen = Math.Min(maxRangeLen, maxPossibleRangeLen);

                return(minLen <= maxLen);  // fail if we ended up with a zero-length range
            }
Esempio n. 3
0
            BaseTerm CopyEx(int newVerNo, bool mustBeNamed)
            {
                if (IsUnified)
                {
                    return(ChainEnd().CopyEx(newVerNo, mustBeNamed));
                }

                // A neater solution would be to use overrides for each term subtype.
                if (this is Variable)
                {
                    Variable v = (Variable)this;

                    if (newVerNo == v.verNo)
                    {
                        return(v.newVar);
                    }

                    v.verNo = newVerNo;

                    return(v.newVar = (mustBeNamed && this is NamedVariable)
                      ? new NamedVariable(((NamedVariable)v).Name)
                      : new Variable());
                }
                else if (this is CatchOpenTerm)
                {
                    CatchOpenTerm c = (CatchOpenTerm)this;

                    return(new CatchOpenTerm(c.Id, c.ExceptionClass, c.MsgVar.CopyEx(newVerNo, mustBeNamed),
                                             c.SeqNo, c.SaveStackSize));
                }
                else
                {
                    if (arity == 0)
                    {
                        return(this);
                    }

                    BaseTerm   t = null;
                    BaseTerm[] a = new BaseTerm[arity];

                    for (int i = 0; i < arity; i++)
                    {
                        if (args[i] != null)                              // may be null for a GapTerm
                        {
                            a[i] = args[i].CopyEx(newVerNo, mustBeNamed); // recursively refresh arguments
                        }
                    }
                    if (this is ListPatternTerm)
                    {
                        t = new ListPatternTerm(a);
                    }
                    else if (this is AltListTerm)
                    {
                        AltListTerm alt = (AltListTerm)this;
                        t = new AltListTerm(alt.LeftBracket, alt.RightBracket, a[0], a[1]);
                    }
                    else if (this is ListTerm)
                    {
                        if (((ListTerm)this).CharCodeString == null)
                        {
                            t = new ListTerm(a[0], a[1]);
                        }
                        else // it's an ISO-style string
                        {
                            t = new ListTerm(((ListTerm)this).CharCodeString);
                        }
                    }
                    else if (this is OperatorTerm)
                    {
                        t = new OperatorTerm(((OperatorTerm)this).od, a);
                    }
                    else if (this is DcgTerm)
                    {
                        t = new DcgTerm(functor, a);
                    }
                    else if (this is WrapperTerm)
                    {
                        t = new WrapperTerm((WrapperTerm)this, a);
                    }
                    else if (this is IntRangeTerm)
                    {
                        t = new IntRangeTerm((IntRangeTerm)this);
                    }
                    else if (this is ListPatternElem)
                    {
                        t = new ListPatternElem(a, ((ListPatternElem)this).downRepFactor, ((ListPatternElem)this).IsNegSearch);
                    }
                    else if (this is CompoundTerm)
                    {
                        t = new CompoundTerm(functor, a);
                    }
                    else
                    {
                        IO.Error("CopyEx(): type '{0}' not handled explicitly", this.GetType());
                    }

                    return(t);
                }
            }
Esempio n. 4
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);
            }
      // try to bind the range specification variable (if present) to the range last.
      // if the minimun or the maximum range length was a variable, then bind it to the actual length just found
      bool TryBindingRangeRelatedVars (ListPatternElem g, int rangeLength, ListTerm RangeList, VarStack varStack)
      {
        if (g.MinLenTerm.IsVar)
          g.MinLenTerm.Unify (new DecimalTerm (rangeLength), varStack);

        if (g.MaxLenTerm.IsVar)
          g.MaxLenTerm.Unify (new DecimalTerm (rangeLength), varStack);

        if (g.RangeBindVar != null)
        {
          if (RangeList == null) RangeList = ListTerm.EMPTYLIST;

          if (!g.RangeBindVar.Unify (RangeList, varStack))
            return false; // alas, the same range var was apparently used & bound earlier in the pattern
        }

        return true;
      }
      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 last, 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
        }
      }