Пример #1
0
 /// <summary>
 /// Queries the vocabulary according to the specified criteria and returns a random match.
 /// </summary>
 /// <param name="rng">The random number generator to randomize the match with.</param>
 /// <param name="query">The search criteria to use.</param>
 /// <returns></returns>
 public string Query(RNG rng, Query query)
 {
     Dictionary wordList;
     return !_wordLists.TryGetValue(query.Name, out wordList) 
         ? "MISSINGDIC" 
         : wordList.Query(rng, query);
 }
Пример #2
0
        private static bool DoQuery(Interpreter interpreter, SourceReader reader, State state)
        {
            var first = reader.ReadToken();
            reader.SkipSpace();

            var namesub = reader.Read(TokenType.Text, "list name").Split(new[] { '.' }, 2).ToArray();
            var q = new Query(namesub[0].Value.Trim(), namesub.Length == 2 ? namesub[1].Value : "", "", reader.Take(TokenType.Dollar), null, null);

            Token<TokenType> token = null;

            // Class filter list. Not initialized unless class filters actually exist.
            List<Tuple<bool, string>> cfList = null;

            while (true)
            {
                if (reader.Take(TokenType.Hyphen))
                {
                    // Initialize the filter list.
                    (cfList ?? (cfList = new List<Tuple<bool, string>>())).Clear();

                    do
                    {
                        bool notin = reader.Take(TokenType.Exclamation);
                        if (notin && q.Exclusive)
                            throw new ProcessusException(reader.Source, reader.PrevToken, "Cannot use the '!' modifier on exclusive class filters.");
                        cfList.Add(Tuple.Create(!notin, reader.Read(TokenType.Text, "class identifier").Value.Trim()));
                    } while (reader.Take(TokenType.Pipe));
                    q.ClassFilters.Add(cfList.ToArray());
                }
                else if (reader.Take(TokenType.Question))
                {
                    token = reader.Read(TokenType.Regex, "regex");
                    q.RegexFilters.Add(Tuple.Create(true, Util.ParseRegex(token.Value)));
                }
                else if (reader.Take(TokenType.Without))
                {
                    token = reader.Read(TokenType.Regex, "regex");
                    q.RegexFilters.Add(Tuple.Create(false, Util.ParseRegex(token.Value)));
                }
                else if (reader.Take(TokenType.DoubleColon))
                {
                    token = reader.Read(TokenType.Text, "carrier name");
                    q.Carrier = token.Value.Trim();
                    if (!reader.Take(TokenType.RightAngle))
                    {
                        throw new ProcessusException(reader.Source, token, "Expected '>' after carrier. (The carrier should be your last query argument!)");
                    }
                    break;
                }
                else if (reader.Take(TokenType.RightAngle))
                {
                    break;
                }
                else if (!reader.SkipSpace())
                {
                    var t = !reader.End ? reader.ReadToken() : null;
                    throw new ProcessusException(reader.Source, t, t == null ? "Unexpected end-of-file in query." : "Unexpected token '" + t.Value + "' in query.");
                }
            }

            interpreter.Print(interpreter.Engine.Vocabulary.Query(interpreter.RNG, q));

            return false;
        }
Пример #3
0
        internal string Query(RNG rng, Query query)
        {
            var index = String.IsNullOrEmpty(query.Subtype) ? 0 : GetSubtypeIndex(query.Subtype);
            if (index == -1)
            {
                return "BAD_SUBTYPE";
            }

            IEnumerable<DictionaryEntry> pool = _words;

            pool = query.Exclusive
                ? pool.Where(e => e.Classes.Any() && e.Classes.All(c => query.ClassFilters.Any(set => set.Any(t => t.Item2 == c))))
                : pool.Where(e => query.ClassFilters.All(set => set.Any(t => t.Item1 == (e.Classes.Contains(t.Item2)))));

            pool = query.RegexFilters.Aggregate(pool, (current, regex) => current.Where(e => regex.Item1 == regex.Item2.IsMatch(e.Values[index])));

            if (!pool.Any())
            {
                return "NOT_FOUND";
            }

            int number = String.IsNullOrEmpty(query.Carrier) ? rng.Next(pool.Sum(e => e.Weight)) + 1
                : rng.PeekAt(query.Carrier.Hash(), pool.Sum(e => e.Weight));

            foreach (var e in pool)
            {
                if (number <= e.Weight) return e.Values[index];
                number -= e.Weight;
            }

            return "NOT_FOUND";
        }