//This adds the transitions required to make a group trie correspond to the correct quantified regex private RegexTrie <T> joinQuantifiedTrie(MinMaxResult result, RegexTrie <T> startNodeOfCurrentComponent, RegexTrie <T> endNodeOfCurrentComponent, RegexTrie <T> endNodeOfPreviousComponent) { //This is the end node which will be reached by epsilon transition in case of zeroed quantifiers //or quantifiers with a number range of more than one, start node is used for zeroing RegexTrie <T> epsilonEndNode = new RegexTrie <T>(); RegexTrie <T> epsilonStartNode = new RegexTrie <T>(); //This holds the end node used during the loop RegexTrie <T> loopEndNode = endNodeOfCurrentComponent; //Loop from 1 (one occurrence already exists) to max occurrences. If loop index is greater than min, //add epsilon from iteration trie end to final trie end. if (result.minOccurs > 1 || result.maxOccurs > 1) { //This is used as a model for copying, only needs to be calculated if there's a set number of occurrences KeyValuePair <RegexTrie <T>, RegexTrie <T> > trieModel = copyTrie(startNodeOfCurrentComponent, endNodeOfCurrentComponent); //Result of trie copy KeyValuePair <RegexTrie <T>, RegexTrie <T> > trieCopy; for (int index = 2; index <= result.maxOccurs; index++) { if (index <= result.maxOccurs) { //Copy the trie and link it to the end of trie trieCopy = copyTrie(trieModel); loopEndNode.AddEpsilonTransition(trieCopy.Key); //If the index is equal or greater than minoccurs, add epsilon to end node if (result.minOccurs <= index) { trieCopy.Value.AddEpsilonTransition(epsilonEndNode); } //Assign the end node of the copy as the end node of the component loopEndNode = trieCopy.Value; } } } //If there's less than two occurrences, connect the end of the first span of the trie to the epsilon end trie //Do this after the copy loop in order to not disturb the copying. if (result.minOccurs < 2) { endNodeOfCurrentComponent.AddEpsilonTransition(epsilonEndNode); } //If the quantifier is starred, add epsilon from end to start if (result.starred) { endNodeOfCurrentComponent.AddEpsilonTransition(startNodeOfCurrentComponent); } //If the quantifier is zeroed, add an epsilon from epsilon start node //newCurrentTrie if (result.zeroInclusive) { epsilonStartNode.AddEpsilonTransition(startNodeOfCurrentComponent); epsilonStartNode.AddEpsilonTransition(epsilonEndNode); startNodeOfCurrentComponent = epsilonStartNode; } //Connect trie to previous trie endNodeOfPreviousComponent.AddEpsilonTransition(startNodeOfCurrentComponent); return(epsilonEndNode); }
//This checks for a quantifier immediately after the character, and joins the current trie to the end of the //previous trie. Returns a pair of int (to increment string index) and the node to which further tries will be connected private KeyValuePair <int, RegexTrie <T> > checkForQuantifier( string sourceTail, RegexTrie <T> endNodeOfCurrentComponent, RegexTrie <T> startNodeOfCurrentComponent, RegexTrie <T> endNodeOfPreviousComponent, Stack <RegexTrie <T> > commonDestination) { char nextChar; try { nextChar = sourceTail[0]; } catch { //assign a non-special character to trigger the default case nextChar = 'n'; } switch (nextChar) { case '*': { return(new KeyValuePair <int, RegexTrie <T> >(1, joinQuantifiedTrie( new MinMaxResult(1, 1, true, true), startNodeOfCurrentComponent, endNodeOfCurrentComponent, endNodeOfPreviousComponent))); } case '+': { return(new KeyValuePair <int, RegexTrie <T> >(1, joinQuantifiedTrie( new MinMaxResult(1, 1, true, false), startNodeOfCurrentComponent, endNodeOfCurrentComponent, endNodeOfPreviousComponent))); } case '?': { return(new KeyValuePair <int, RegexTrie <T> >(1, joinQuantifiedTrie( new MinMaxResult(1, 1, false, true), startNodeOfCurrentComponent, endNodeOfCurrentComponent, endNodeOfPreviousComponent))); } case '{': { int closeBraceIndex = sourceTail.IndexOf('}'); string quantString = sourceTail.Substring(1, closeBraceIndex - 1); MinMaxResult minMax = findMinMax(quantString); return(new KeyValuePair <int, RegexTrie <T> >(closeBraceIndex + 1, joinQuantifiedTrie( minMax, startNodeOfCurrentComponent, endNodeOfCurrentComponent, endNodeOfPreviousComponent))); } default: { endNodeOfPreviousComponent.AddEpsilonTransition(startNodeOfCurrentComponent); return(new KeyValuePair <int, RegexTrie <T> >(0, endNodeOfCurrentComponent)); } } }