// Clone the pattern matcher and reconfigure it in a new state based on a word. private PatternMatcher makeCopyWithStateFromAtWord(ProseObject atWord) { PatternMatcher newMatcher = new PatternMatcher(runtime); newMatcher.patternComponentNodes.AddRange(patternComponentNodes); newMatcher.numObjectsMatched = numObjectsMatched; if (currPatternObject != null) { newMatcher.currPatternObject = currPatternObject.clone(); } if (atWord == runtime.@prose) { newMatcher.switchToState_MATCHING_PROSE(); if (parentheticalStack != null) { //newMatcher.parentheticalStack = new Stack<ProseObject>(parentheticalStack); newMatcher.parentheticalStack = new Stack <ProseObject>(); ProseObject[] objs = parentheticalStack.ToArray(); for (int i = objs.Length - 1; i >= 0; i--) { newMatcher.parentheticalStack.Push(objs[i]); } } newMatcher.inText = inText; } else if (atWord == runtime.@text) { newMatcher.switchToState_MATCHING_TEXT(); newMatcher.textMatchingQQcount = textMatchingQQcount; } else if (atWord == runtime.@pattern) { newMatcher.switchToState_MATCHING_PATTERN(); } else { newMatcher.switchToState_MATCHING_OBJECT(); } return(newMatcher); }
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); }
// Clone the pattern matcher and reconfigure it in a new state based on a word. private PatternMatcher makeCopyWithStateFromAtWord(ProseObject atWord) { PatternMatcher newMatcher = new PatternMatcher(runtime); newMatcher.patternComponentNodes.AddRange(patternComponentNodes); newMatcher.numObjectsMatched = numObjectsMatched; if (currPatternObject != null) newMatcher.currPatternObject = currPatternObject.clone(); if (atWord == runtime.@prose) { newMatcher.switchToState_MATCHING_PROSE(); if (parentheticalStack != null) { //newMatcher.parentheticalStack = new Stack<ProseObject>(parentheticalStack); newMatcher.parentheticalStack = new Stack<ProseObject>(); ProseObject[] objs = parentheticalStack.ToArray(); for (int i=objs.Length - 1; i >= 0; i--) newMatcher.parentheticalStack.Push(objs[i]); } newMatcher.inText = inText; } else if (atWord == runtime.@text) { newMatcher.switchToState_MATCHING_TEXT(); newMatcher.textMatchingQQcount = textMatchingQQcount; } else if (atWord == runtime.@pattern) { newMatcher.switchToState_MATCHING_PATTERN(); } else { newMatcher.switchToState_MATCHING_OBJECT(); } return newMatcher; }