/// <summary>
        /// Yields each of the possible matches of the regex from this point onwards as a CharSetString.
        /// </summary>
        /// <param name="charIdx">
        /// The current index of the match in the string
        /// </param>
        /// <param name="currentConstraints">
        /// The prior constraints on any matches
        /// </param>
        public override IEnumerable<CharSetString> GeneratePossibleMatches(int charIdx, CharSetString currentConstraints)
        {
            if (CurrentMatch != null)
              {
            throw new InvalidOperationException("There is already a match in progress");
              }
              foreach (var choice in Choices)
              {
            var first = choice.First();
            foreach (var choiceMatchGen in first.GeneratePossibleMatches(charIdx, currentConstraints))
            {
              // choiceMatch may be modified later on (see RegexBackReference), so we promote it
              // to a RevertibleCharSetString
              var choiceMatch = new RevertibleCharSetString(choiceMatchGen);

              CurrentMatch = choiceMatch;
              foreach (var remainderMatch in
            Next.GeneratePossibleMatches(
              charIdx + choiceMatch.Length,
              currentConstraints))
              {
            yield return choiceMatch.Concat(remainderMatch);
              }
              CurrentMatch = null;
            }
              }
        }
 public IEnumerable<CharSetString> GeneratePossibleMatches(int charIdx, CharSetString currentConstraints)
 {
     if (charIdx == currentConstraints.Length)
       {
     yield return CharSetString.EmptyString();
       }
 }
        public override IEnumerable<CharSetString> GeneratePossibleMatches(int charIdx, CharSetString currentConstraints)
        {
            // Is the groupMatch applicable here?
              //
              // The constraints here retrospectively modify the earlier match -- any matching string
              // must match both here and before, i.e.
              // a regex like "(.)\1" applied to ".A" must become "AA"
              //
              // We bookmark the previous match, so that we can put things back how we found them
              // after iterating over this possible path.

              var previousGroupMatch = Group.CurrentMatch;
              previousGroupMatch.Bookmark();

              var i = 0;
              foreach (var groupMatchChar in previousGroupMatch)
              {
            if (charIdx + i >= currentConstraints.Length)
            {
              goto noMatch;
            }
            try
            {
              groupMatchChar.Intersect(currentConstraints[charIdx + i]);
            }
            catch (CharSet.EmptyIntersectionException)
            {
              goto noMatch;
            }
            i++;
              }

              foreach (var remainderMatch in
            Next.GeneratePossibleMatches(
              charIdx + previousGroupMatch.Length,
              currentConstraints))
              {
            // The value returned here is valid only briefly: we will reuse the
            // same strings in the next element.
            // See comments on RegexNonTerminalAtom.GeneratePossibleMatches
            yield return previousGroupMatch.Concat(remainderMatch);
              }

              noMatch:
              previousGroupMatch.RevertToBookmark();
        }
        /// <summary>
        /// Yields each of the possible matches of the regex from this point onwards as a CharSetString.
        /// </summary>
        /// <param name="charIdx">
        /// The current index of the match in the string
        /// </param>
        /// <param name="currentConstraints">
        /// The prior constraints on any matches
        /// </param>
        public override IEnumerable<CharSetString> GeneratePossibleMatches(int charIdx, CharSetString currentConstraints)
        {
            if (MinReps == 0)
              {
            foreach (var nextMatch in Next.GeneratePossibleMatches(charIdx, currentConstraints))
            {
              yield return nextMatch;
            }
              }

              Inner.Next = new RegexEmptyMatchTerminalAtom();
              var currentInnerMatches = new List<CharSetString> { CharSetString.EmptyString() };

              for (int innerMatchCount = 1; innerMatchCount <= (MaxReps ?? Int32.MaxValue); innerMatchCount++)
              {
            var newInnerMatches = new List<CharSetString>();
            foreach (var currentInnerMatch in currentInnerMatches)
            {
              // TODO: could group the currentInnerMatches by length here, to save re-computing
              // the following repeatedly for the same arguments in some cases
              foreach (var nextInnerMatch in Inner.GeneratePossibleMatches(
            charIdx + currentInnerMatch.Length,
            currentConstraints))
              {
            var newInnerMatch = currentInnerMatch.Concat(nextInnerMatch);
            newInnerMatches.Add(newInnerMatch);

            if (innerMatchCount >= MinReps)
            {
              foreach (var nextMatch in Next.GeneratePossibleMatches(
                charIdx + newInnerMatch.Length, currentConstraints))
              {
                yield return newInnerMatch.Concat(nextMatch);
              }
            }
              }
            }
            currentInnerMatches = newInnerMatches;

            if (!currentInnerMatches.Any())
            {
              break;
            }
              }
        }
        /// <summary>
        /// Yields each of the possible matches of the regex from this point onwards as a CharSetString.
        /// </summary>
        /// <param name="charIdx">
        /// The current index of the match in the string
        /// </param>
        /// <param name="currentConstraints">
        /// The prior constraints on any matches
        /// </param>
        public override IEnumerable<CharSetString> GeneratePossibleMatches(int charIdx, CharSetString currentConstraints)
        {
            if (charIdx >= currentConstraints.Length)
              {
            yield break; // no match
              }
              var thisCharSet = currentConstraints[charIdx].Clone();
              try
              {
            thisCharSet.Intersect(CharSet);
              }
              catch (CharSet.EmptyIntersectionException)
              {
            yield break; // no match
              }

              foreach (var remainderMatch in Next.GeneratePossibleMatches(charIdx + 1, currentConstraints))
              {
            yield return CharSetString.Cons(thisCharSet, remainderMatch);
              }
        }
        /// <param name="clues">
        ///  The clues as a 3xN grid
        /// </param>
        public HexRegexCrossword(Regex[,] clues)
        {
            if (3 != clues.GetUpperBound(0) + 1 || 0 != clues.GetLowerBound(0)
              || 0 != clues.GetLowerBound(1))
              {
            throw new ArgumentException("The clue array must be 3 X rowCount");
              }
              Clues = clues;

              RowCount = clues.GetUpperBound(1) + 1;
              SideLength = (RowCount + 1)/2;
              GridRows = new CharSetString[3, RowCount];
              // Build up a grid of cells by Q/R.
              // The max coord will be < +/- sideLength
              // Since coords may be negative, this array is offset by +sideLength
              _cellsByQROffsetBySideLength = new CharSet[2 * SideLength, 2 * SideLength];

              for (int axis = 0; axis < 3; axis++)
              {
            for (int idx = -(SideLength - 1); idx <= (SideLength - 1); idx++)
            {
              var row = new List<CharSet>();
              for (int offset = 0;; offset++)
              {
            var qr = AxisIdxOffsetToQR(axis, idx, offset);
            var cell = GetCellByQR(qr);
            if (cell == null) // qr is out of range
            {
              break;
            }
            row.Add(cell);
              }
              GridRows[axis, idx + (SideLength - 1)] = new CharSetString(row);
            }
              }
        }
 /// <summary>
 /// Enumerates the possible matches for this regex component at the given starting index and
 /// under the given constraints.
 ///
 /// Careful: the returned CharSetStrings are only valid when they are first returned from the
 /// iterator. Parts of the string are shared between successive return values. You must copy
 /// or consume the output while the iteration is proceeding.
 ///
 /// See RegexBackReference for more on this.
 /// </summary>
 /// <param name="charIdx"></param>
 /// <param name="currentConstraints"></param>
 /// <returns></returns>
 public abstract IEnumerable<CharSetString> GeneratePossibleMatches(int charIdx, CharSetString currentConstraints);
示例#8
0
        /// <summary>
        /// Given a string of possible characters, attempts to constrain the possibilities
        /// to only strings which match this regex.
        /// 
        /// Returns true if any changes were made.
        /// </summary>
        public bool AddConstraints(CharSetString currentConstraints)
        {
            var first = Atoms.First();

              var possibilitiesSeen = CharSetString.EmptySetsStringOfLength(currentConstraints.Length);
              foreach (var possibility in first.GeneratePossibleMatches(0, currentConstraints))
              {
            possibilitiesSeen.Union(possibility);
              }

              return currentConstraints.Intersect(possibilitiesSeen);
        }
 public IEnumerable<CharSetString> GeneratePossibleMatches(int charIdx, CharSetString currentConstraints)
 {
     return new[] { CharSetString.EmptyString() };
 }