/// <summary>
    /// Count the number of words in this list that matches in the phrase
    /// </summary>
    /// <param name="lexer">The words to match</param>
    /// <param name="count">The number of words that match [out]</param>
    /// <returns>Score for the match: 0 if no match</returns>
    internal double matchMembers(Lexer lexer, out int count)
    {
        var cnt = 0  ; // The number of words that match
          var score=0.0; // The score to match

          // for each of the remaining words
          while (!lexer.EOF)
          {
         lexer.Preprocess();
         var word =lexer.Symbol();

         // See if it matches a modifier
         double score1 = matchMembers(word);

         // check for a minimum score
         if (score1 <= 0.0) break;

         // Update the tracking info
         cnt++;
         score += score1;
          }

          // return the results
          count = cnt;
          return score;
    }
   /// <summary>
   /// Finds a verb phrase that matches
   /// </summary>
   /// <param name="lex"></param>
   /// <param name="stateEndVerbPhrase"></param>
   /// <returns></returns>
   WordList findVerbPhrase(Lexer lex)
   {
      // First, make a list of all verb phrases
      var candidates = new List<WordList>();
      foreach (var item in verbs)
      {
         candidates.Add(item.Key);
      }

      // The words of the verb phrase
      var verbWords = new List<string>();
      var prevState = lex.Save();
      LexState stateEndVerbPhrase=prevState;

      // Next, get words from the lexer as long they match a phrase
      lex.Preprocess();
      while (!lex.EOF)
      {
         var word = lex.Symbol();
         lex.Preprocess();
         
         // See if the word matches any candidate
         var newCandidates = new List<WordList>();
         var numVerbWords = verbWords . Count;
         foreach (var candidate in candidates)
         {
            // Skip "shorter" phrases
            if (numVerbWords >= candidate.words.Length)
                continue;
            // Get the word for this far in
            var item = candidate.words[numVerbWords];

            // Is there a match?
            // Check for exact, but caseless match; or a partial
            if (item.Equals(word, StringComparison.CurrentCultureIgnoreCase)
               || ((word. Length < item.Length)
                     && item.Substring(0, word.Length).Equals(word, StringComparison.CurrentCultureIgnoreCase)))
            {
               // keep it
               newCandidates.Add(candidate);
            }
         }
         // Did anyone match?
         if (newCandidates . Count < 1)
            break;
         // Save the word and the matches
         candidates = newCandidates;
         verbWords.Add(word);
         stateEndVerbPhrase = lex.Save();
      }


      // Check to see if any matched
      if (candidates.Count < 1 || verbWords.Count < 1)
      {
         lex.Restore(prevState);
         return null;
      }

      // Jump back tot he end of the verb phrase
      lex.Restore(stateEndVerbPhrase);

      /// The words for the verb phrase
      WordList verbWordList = new WordList(verbWords.ToArray());

      // Rank the matched phrases, finding the best one
      var bestScore = 0.0;
      WordList bestCandidate = null;
      foreach (var candidate in candidates)
      {
         // Assign a score to the candidate.
         var score = candidate.score(verbWordList);
         // Is it a better match?
         if (score > bestScore)
         {
            // Keep it
            bestScore = score;
            bestCandidate=candidate;
         }
      }

      // Return the best matched phrase
      return bestCandidate;
   }