/// <summary> /// Construct a new <see cref="Sentence"/> from a string, using the specified <see cref="Glossary"/>. /// </summary> /// <param name="inputString">The raw string input by the player.</param> /// <param name="glossary">The <see cref="Glossary"/> to use when parsing the input string.</param> /// <param name="errorMessage">Describes any issue that occurred when parsing, else null if parsed successfully.</param> /// <returns>A new, interpretable <see cref="Sentence"/>, or null if parsing failed.</returns> /// <exception cref="ArgumentNullException">Thrown if any parameter is null.</exception> public static Sentence Parse(string inputString, Glossary glossary, out string errorMessage) { // PREPARATION -- Argument checking, property/field instantiation. if (inputString == null) { throw new ArgumentNullException(nameof(inputString)); } if (glossary == null) { throw new ArgumentNullException(nameof(glossary)); } // TOKENIZATION -- Split input string into a list of strings, while removing invalid characters and unnecessary words. List <Token> tokenList = Tokenize(inputString, glossary, out errorMessage); if (errorMessage != null) { return(null); } // PARSING -- Construct a sentence out of tokens by converting them to meaningful nodes and organizing them syntactically. List <Node> nodeList = glossary.ConvertToNodes(tokenList); CollectNounModifiers(nodeList); CollectNouns(nodeList); // FINISH -- Return new sentence return(new Sentence(nodeList)); }
/// <summary> /// Converts a player input string into a list of <see cref="Token"/> objects. /// </summary> /// <param name="inputString">The string input by the player.</param> /// <param name="glossary">The <see cref="Glossary"/> used to normalize and validate the input.</param> /// <param name="errorMessage">Null if no error occurs, otherwise a string that describes the problem.</param> /// <returns>A list of <see cref="Token"/> objects, or null if an error occured.</returns> private static List <Token> Tokenize(string inputString, Glossary glossary, out string errorMessage) { // trim and split string by whitespace string[] wordList = inputString.Trim().Split((char[])null, StringSplitOptions.RemoveEmptyEntries); // Check for empty / whitespace input if (wordList.Length == 0) { errorMessage = "Speak up, please."; return(null); } // create tokens List <Token> tokenList = new List <Token>(); foreach (string origWord in wordList) { // copy and normalize word string n = glossary.Normalize(string.Copy(origWord)); // remove invalid chars StringBuilder strBuilder = new StringBuilder(n); for (int j = strBuilder.Length - 1; j >= 0; j--) { if (glossary.IsInvalidChar(strBuilder[j])) { strBuilder.Remove(j, 1); } } string newWord = strBuilder.ToString(); // Make tokens, but not of empty or invalid words if (!(newWord == String.Empty || glossary.IsInvalidWord(newWord))) { tokenList.Add(new Token(origWord, newWord)); } } // Check if entire input contained invalid chars / words / whitespace if (tokenList.Count == 0) { errorMessage = "I'm pretty sure that isn't a sentence."; return(null); } // Input passed validation errorMessage = null; return(tokenList); }