List <PatternMatcher> while_MATCHING_PROSE_matchNextObject(PNode node) { ProseObject obj = node.value; // Return this list of spawned matchers. List <PatternMatcher> babyMatchers = new List <PatternMatcher>(); // Possibly we can make this prose block longer (in addition to other options where we may leave it) bool canExtendThisProseBlock = false; // If we want extend our prose block by adding a right parenthetical, remember to pop the left off the stack. bool shouldPopParentheticalStack = false; // If we stay in this prose block, record if we are entering text or leaving text bool shouldToggleInText = false; // Should we exit to a different mode? bool shouldLeaveMatchingProse = false; MatcherState switchToThisState; // Check for parentheticals // No need to check for () because it's eliminated before we're ever called. if (obj == runtime.LeftCurlyBracket) { canExtendThisProseBlock = true; // Do this in extend //parentheticalStack.Push(runtime.LeftCurlyBracket); } else if (obj == runtime.LeftSquareBracket) { canExtendThisProseBlock = true; // Do this in extend //parentheticalStack.Push(runtime.LeftSquareBracket); } else if (obj == runtime.RightCurlyBracket) { ProseObject matchingParenthetical = tryPeekParenthetical(); if (matchingParenthetical == null || matchingParenthetical != runtime.LeftCurlyBracket) { throw new PatternMatcherException("Right curly bracket wihtout matching left curly bracket inside @prose block.", this); } // At this point, we agree the curly bracket makes sense, so we pop it's counterpart off the stack. shouldPopParentheticalStack = true; canExtendThisProseBlock = true; } else if (obj == runtime.RightSquareBracket) { ProseObject matchingParenthetical = tryPeekParenthetical(); if (matchingParenthetical == null || matchingParenthetical != runtime.LeftSquareBracket) { throw new PatternMatcherException("Right square bracket without matching left square bracket inside @prose block.", this); } // At this point, we agree the square bracket makes sense, so we pop it's counterpart off the stack. shouldPopParentheticalStack = true; canExtendThisProseBlock = true; } else if (obj == runtime.Quadquote) { // In this case, we count that we are in a text block, but we don't "read it as text". Instead, we just // bundle the symbols in with our prose object and pass it along to be interpreted later. if (inText) { ProseObject matchingParenthetical = tryPeekParenthetical(); if (matchingParenthetical == null || matchingParenthetical != runtime.Quadquote) { // The "" didn't match up with a previous one! throw new PatternMatcherException("Quadquote entagled with other parenthetical.", this); } else { canExtendThisProseBlock = true; shouldToggleInText = true; // inText = false; shouldPopParentheticalStack = true; // Pop off the left "" } } else { // In this case, we treat this as an opening quadquote. canExtendThisProseBlock = true; parentheticalStack.Push(runtime.Quadquote); // Remember the left "" shouldToggleInText = true; // inText = true; } } // When the parenthetical stack is empty, we are allowed to exit the prose block if // we can match the next piece of the pattern. else if (parentheticalStack.Count == 0) { // if (obj == runtime.Period) { // // A period ends a "prose" block unless it is protected by {} or [] or "" "" // // The period does not appear in the block. It is interpreted as ending the sentence. // // So exit reading prose // shouldLeaveMatchingProse = true; // //switchToThisState = MatcherState.MATCHING_OBJECT; // //CURSOR // } else { // Use inheritance to look for an exit! // Look up words which would match if they were in a pattern. List <ProseObject> matchingPatternWords = getMatchingPatternWords(obj); // Look these words up to see if actual patterns exist. canExtendThisProseBlock = (matchingPatternWords.Count != 0); foreach (ProseObject match in matchingPatternWords) { // If it's not a period and the attempt to extend @prose immediately failed, // then we continue matching @prose. If the attempt didn't immediately fail then // the rules say we must leave @prose. if (obj == runtime.Period) // && !babyMatcher.IsntFailed) { canExtendThisProseBlock = false; } if (match == runtime.@prose) { continue; // back to back @prose outlawed. } // Look up the match Trie <ProseObject, List <Phrase> > .Node matchNode = currNode.getChildNode(match); if (matchNode == null) { continue; } // If this pattern can be extended by leaving prose, then do it // Spawn a baby matcher to pursue this pattern PatternMatcher babyMatcher = makeCopyWithStateFromAtWord(match); // Clone ourselves babyMatcher.switchToState_MATCHING_OBJECT(); // Move babyMatcher into the generic state (can accept anything) babyMatcher.while_MATCHING_OBJECT_extendWith(node, matchNode); // Append the new node babyMatchers.Add(babyMatcher); // Eventually return this baby matcher // If it's possible to exit an @prose block, the matcher MUST canExtendThisProseBlock = false; } } // In this case the parenthetical stack is not empty and we have some symbol that // isn't parenthetical (or ""). else { // Add it to this prose block canExtendThisProseBlock = true; } // // Perform updates according to flags // if (shouldToggleInText) { inText = !inText; } if (shouldPopParentheticalStack) { parentheticalStack.Pop(); } if (canExtendThisProseBlock) { // Extend ourselves! // NOTE: We don't change the node we're using! PatternMatcher babyMatcher = makeCopyWithStateFromAtWord(runtime.@prose); // Clone ourselves babyMatcher.objectsInCurrentProseblock = objectsInCurrentProseblock; babyMatcher.while_MATCHING_PROSE_extendWith(node, currNode); babyMatchers.Add(babyMatcher); } else if (shouldLeaveMatchingProse) { throw new Exception("Failboat."); // PatternMatcher babyMatcher = makeCopyWithStateFromAtWord(obj); // Clone ourselves // //babyMatcher.switchToState_MATCHING_OBJECT(); // babyMatcher.while_MATCHING_OBJECT_extendWith(node, ); // babyMatchers.Add(babyMatcher); } return(babyMatchers); }
List <PatternMatcher> while_MATCHING_PATTERN_matchNextObject(PNode node) { List <PatternMatcher> babyMatchers = new List <PatternMatcher>(); ProseObject obj = node.value; // @Pattern won't match periods if (obj == runtime.Period) { return(babyMatchers); } // switch (bracketReaderCount) { case 0: // Check to see if obj is -> :+ or :- if (obj == runtime.RightArrow || obj == runtime.ColonPlus || obj == runtime.ColonMinus) { // If so, then we have to leave matching. See if anything is checking for this symbol Trie <ProseObject, List <Phrase> > .Node childNode = currNode.getChildNode(obj); if (childNode != null) { PatternMatcher babyMatcher = makeCopyWithStateFromAtWord(obj); // Clone ourselves babyMatcher.while_MATCHING_OBJECT_extendWith(node, childNode); babyMatchers.Add(babyMatcher); } } else if (obj == runtime.Period || !(obj is Word)) { return(babyMatchers); } else { PatternMatcher babyMatcher = makeCopyWithStateFromAtWord(runtime.@pattern); babyMatcher.while_MATCHING_PATTERN_extendWith(node, currNode); // Use same node if (babyMatcher.IsntFailed) { babyMatchers.Add(babyMatcher); } } break; case 1: { // In this case, just trust while_..._extendWith to do the right thing. PatternMatcher babyMatcher = makeCopyWithStateFromAtWord(runtime.@pattern); babyMatcher.bracketReaderCount = bracketReaderCount; babyMatcher.while_MATCHING_PATTERN_extendWith(node, currNode); // Use same node if (babyMatcher.IsntFailed) { babyMatchers.Add(babyMatcher); } break; } } return(babyMatchers); }
// Read a new object and maybe switch to reading prose, text, or pattern if necessary. List <PatternMatcher> while_MATCHING_OBJECT_matchNextObject(PNode node) { ProseObject obj = node.value; // Some symbols get special treatment at the beginning or end of if (obj == runtime.Period || obj == runtime.Semicolon && currNode == patternTrie.Root) { } // Get a list of words which, if they appeared in a pattern, would match with this one. List <ProseObject> matchingPatternWords = getMatchingPatternWords(obj); // // For each matchingPatternWord, query the pattern tree to see if // our pattern can be extended any further. // List <PatternMatcher> babyMatchers = new List <PatternMatcher>(16); bool foundAMatch = false; //ProseObject myExtensionObject = null; Trie <ProseObject, List <Phrase> > .Node myExtensionNode = null; foreach (ProseObject objMatch in matchingPatternWords) { ProseObject match = objMatch; //Word match = (Word) objMatch; // Look up the node that would correspond to the pattern word that would match. Trie <ProseObject, List <Phrase> > .Node matchNode = currNode.getChildNode(match); // If we can't find it, then there are no patterns with that matching word, so skip it if (matchNode == null) { continue; } // If we can find it, then we might need to make a new matcher // Since ONE match has to be reserved for THIS, and the other matches spawn new matchers, // we use "foundAMatch" to decide which to do. // if (foundAMatch) // { // Spawn off a baby matcher and transform its state to represent the new possibility. PatternMatcher babyMatcher = this.makeCopyWithStateFromAtWord(match); babyMatcher.while_MATCHING_OBJECT_extendWith(node, matchNode); babyMatchers.Add(babyMatcher); // List this baby matcher foundAMatch = true; // } // else { // // Cache these two so we can use them later. // myExtensionObject = match; // myExtensionNode = matchNode; // foundAMatch = true; // } } // If we found at least one, then we need to tweak ourselves and add ourselves to the babies. // if (foundAMatch) { // this.while_MATCHING_OBJECT_extendWith(node, myExtensionNode); // babyMatchers.Add(this); // } // else { // state = MatcherState.FAILED; // } if (!foundAMatch) { state = MatcherState.FAILED; } return(babyMatchers); }