Exemple #1
0
        // Interaction Interface: Return whether or not a given sentence matches given pattern: If a match is found a PatternInstance will be returned other wise null
        // Notice that patterns provide EXACT matches, this gives designers flexibility in defining general or specific matches per need/context; For subpatterns the length cannot be decided though so an option if given
        // <Debug> Pending thorough logic check
        // @sentence: input sentence must be well formed: no auxiliary blanks, no punctuation (only words are allowed for now).
        public PatternInstance IsMatchPattern(string sentence, Pattern pattern, bool bExactMatch = true)
        {
            // Prepare return value
            PatternInstance instance = new PatternInstance();

            instance.Type = pattern;

            // Split sentence into words
            string[] words = sentence.Split(new char[] { ' ' });    // <Debug><Improvement> Current we are not dealing with sentences that might contain commas (and we should deal with it here),
            // or multiple sentences types in one piece (and this one should be handled and seperated by higher level input engine because a pattern is designed to handle one setence only (with commas)).

            int currentWord = 0;    // ID of the word we are matching against

            // Stage 1: Iterate through pattern elements: if all elements match then it is likely a good match
            foreach (PatternElement element in pattern.Elements)
            {
                // Make sure we still have more words to match against, otherwise input string is too short for this pattern
                if (words.Length <= currentWord)
                {
                    return(null);
                }

                // Predefine so later it won't cause local variable name conflict
                Phrase          phrase;
                bool            result;
                PatternInstance temp;
                WordAttribute   attribute;
                string          tempString;
                int             overlap;
                // Match element type and vlaue
                switch (element.Type)
                {
                case PatternElementType.SpecificWord:
                    // Prepare two strings
                    tempString = words[currentWord];
                    for (int i = currentWord + 1; i < words.Length; i++)
                    {
                        tempString = tempString + ' ' + words[i];
                    }
                    overlap = GetStringOverlapLowerCase(tempString, element.Key);

                    // If the following words don't match and it's not optional then this pattern doesn't match
                    if (overlap == -1 && element.bOptional == false)
                    {
                        return(null);
                    }
                    else
                    {
                        // Generate Pattern Element Instance and Proceed to next word
                        instance.ComponentElements.Add(new PatternElementInstance(PatternElementType.SpecificWord, tempString.Substring(0, overlap)));
                        currentWord += GetNumOfWords(element.Key);
                    }
                    break;

                case PatternElementType.VarietyWord:
                    result = Vocabulary.IsWordVaryingFormOrSynonym(words[currentWord], element.Key);
                    if (result == false && element.bOptional == false)
                    {
                        return(null);
                    }
                    else
                    {
                        // Generate Pattern Element Instance and Proceed to next word
                        instance.ComponentElements.Add(new PatternElementInstance(PatternElementType.VarietyWord, words[currentWord]));
                        currentWord++;
                    }
                    break;

                case PatternElementType.WordAttribute:
                    // <Debug> This is currently incomplete implementation, i.e. + for multiple constriants (e.g. for verbs)
                    attribute = (WordAttribute)Enum.Parse(typeof(WordAttribute), element.Key);
                    // foundWord = Vocabulary.ProbeWord(words[currentWord], attribute); // Notice for WordAttribute we are not matching against word, but phrase
                    tempString = words[currentWord];
                    for (int i = currentWord + 1; i < words.Length; i++)
                    {
                        tempString = tempString + ' ' + words[i];
                    }
                    phrase = Vocabulary.GetPhrase(tempString, attribute);
                    if (phrase == null && element.bOptional == false)
                    {
                        return(null);
                    }
                    else
                    {
                        // Generate Pattern Element Instance and Proceed to next word
                        instance.ComponentElements.Add(new PatternElementInstance(PatternElementType.WordAttribute, phrase.Key));
                        currentWord += phrase.WordCount;
                    }
                    break;

                case PatternElementType.SubPattern:
                    tempString = words[currentWord];
                    for (int i = currentWord + 1; i < words.Length; i++)
                    {
                        tempString = tempString + ' ' + words[i];
                    }
                    temp = IsMatchPattern(tempString, element.SubPattern, false);       // Do not do an exact match in this case
                    if (temp == null && element.bOptional == false)
                    {
                        return(null);
                    }
                    else
                    {
                        // Generate Pattern Element Instance and Proceed to next word
                        instance.ComponentElements.Add(new PatternElementInstance(PatternElementType.SubPattern, temp));
                        currentWord += temp.WordCount;
                    }
                    break;

                case PatternElementType.Choice:
                    // Return the first matched selection
                    bool bLoopBreak = false;
                    foreach (PatternElement choiceElement in element.Choices)
                    {
                        // break loop, not just the switch
                        if (bLoopBreak)
                        {
                            break;
                        }

                        // Match CHOICE element type and vlaue
                        // Notice that CHOICE elements are always optional, but at least one must be selected
                        switch (choiceElement.Type)
                        {
                        case PatternElementType.SpecificWord:
                            // Prepare two strings
                            tempString = words[currentWord];
                            for (int i = currentWord + 1; i < words.Length; i++)
                            {
                                tempString = tempString + ' ' + words[i];
                            }
                            overlap = GetStringOverlapLowerCase(tempString, choiceElement.Key);

                            // If next word doesn't match then continue; If match then no more loop
                            if (overlap == -1)
                            {
                                continue;
                            }
                            else
                            {
                                // Generate Pattern Element Instance and Proceed to next word
                                instance.ComponentElements.Add(new PatternElementInstance(PatternElementType.SpecificWord, tempString.Substring(0, overlap)));
                                currentWord += GetNumOfWords(choiceElement.Key);
                                bLoopBreak   = true;
                            }
                            break;

                        case PatternElementType.VarietyWord:
                            // If word doesn't match then continue; If match then no more loop
                            result = Vocabulary.IsWordVaryingFormOrSynonym(words[currentWord], choiceElement.Key);
                            if (result == false)
                            {
                                continue;
                            }
                            else
                            {
                                // Generate Pattern Element Instance and Proceed to next word
                                instance.ComponentElements.Add(new PatternElementInstance(PatternElementType.VarietyWord, words[currentWord]));
                                currentWord++;
                                bLoopBreak = true;
                            }
                            break;

                        case PatternElementType.WordAttribute:
                            attribute = (WordAttribute)Enum.Parse(typeof(WordAttribute), choiceElement.Key);
                            // foundWord = Vocabulary.ProbeWord(words[currentWord], attribute); // Notice for WordAttribute we are not matching against word, but phrase
                            tempString = words[currentWord];
                            for (int i = currentWord + 1; i < words.Length; i++)
                            {
                                tempString = tempString + ' ' + words[i];
                            }
                            phrase = Vocabulary.GetPhrase(tempString, attribute);
                            // If trailing string doesn't match then continue; If match then no more loop
                            if (phrase == null && choiceElement.bOptional == false)
                            {
                                continue;
                            }
                            else
                            {
                                // Generate Pattern Element Instance and Proceed to next word
                                instance.ComponentElements.Add(new PatternElementInstance(PatternElementType.WordAttribute, phrase.Key));
                                currentWord += phrase.WordCount;
                                bLoopBreak   = true;
                            }
                            break;

                        case PatternElementType.SubPattern:
                            tempString = words[currentWord];
                            for (int i = currentWord + 1; i < words.Length; i++)
                            {
                                tempString = tempString + ' ' + words[i];
                            }
                            // If trailing string doesn't match then continue; If match then no more loop
                            temp = IsMatchPattern(tempString, choiceElement.SubPattern);
                            if (temp == null)
                            {
                                continue;
                            }
                            else
                            {
                                // Generate Pattern Element Instance and Proceed to next word
                                instance.ComponentElements.Add(new PatternElementInstance(PatternElementType.SubPattern, temp));
                                currentWord += temp.WordCount;
                                bLoopBreak   = true;
                            }
                            break;

                        default:
                            break;
                        }
                    }
                    // If no match was found then this pattern doesn't match, otherwise continue
                    if (bLoopBreak == false)
                    {
                        return(null);
                    }
                    break;

                default:
                    break;
                }
            }

            // Stage 2: If we are doing an exact match then make sure there is no auxiliary words
            if (bExactMatch == true && words.Length != currentWord)
            {
                return(null);
            }

            return(instance);
        }