// Match must start at the beginning private PNode reduceSentenceFragmentStartingAtBeginning(PNode source, out bool didReduce) { // Create a matcher // While there are still "matchers in progress" // Feed each PNode in the source to each matcher in progress. // If the matcher indicats it is done then // Ask for it's list of best matches. // Add that list to the complete list of best matches. // Remove the completed matcher from the list of matchers in progress. // Otherwise, // Add the list of child matchers it returns to the list of matchers in progress List <PatternMatcher> matches = getSuccessfulMatchesStartingAtPNode(source); // Get the matches List <PatternMatcher> bestMatches = getStrongestMatchesFromMatchList(matches); // Select the winners // Deal with ambiguity (too many matches) if (bestMatches.Count > 1 || bestMatches.Count == 1 && bestMatches[0].MatchedPhrases.Count > 1) { didReduce = false; // Make an ambiguity callback and throw an exception to bail out of this mess. if (OnAmbiguity != null) { OnAmbiguity(this, source, bestMatches); throw new RuntimeProseLanguageException("Sentence is ambiguous.", source); } else { throw new RuntimeProseLanguageException("Sentence is ambiguous.", source); } } else if (bestMatches.Count == 0) { // We couldn't reduce anything didReduce = false; return(source); } // Apply the phrase PatternMatcher bestMatcher = bestMatches[0]; Phrase bestPhrase = bestMatcher.MatchedPhrases[0]; didReduce = true; // Do any automatic casting necessary to make the arguments match the pattern. bestMatcher.autoCastArguments(); if (BeforeReduction != null) { BeforeReduction(this, source); } // REDUCE! PNode reducedSource = bestPhrase.evaluate(source, bestMatcher); if (AfterReduction != null) { AfterReduction(this, reducedSource); } return(reducedSource); }