private Node ApplyRulesToSubtree( RuleProcessingContext context, ReadOnlyCollection <ReadOnlyCollection <Rule> > rules, Node subTreeRoot, Node parent, int childIndexInParent) { int num = 0; Dictionary <SubTreeId, SubTreeId> dictionary = new Dictionary <SubTreeId, SubTreeId>(); SubTreeId key; while (true) { ++num; context.PreProcessSubTree(subTreeRoot); key = new SubTreeId(context, subTreeRoot, parent, childIndexInParent); if (!this.m_processedNodeMap.ContainsKey(key)) { if (!dictionary.ContainsKey(key)) { dictionary[key] = key; for (int childIndexInParent1 = 0; childIndexInParent1 < subTreeRoot.Children.Count; ++childIndexInParent1) { Node child = subTreeRoot.Children[childIndexInParent1]; if (RuleProcessor.ShouldApplyRules(child, subTreeRoot)) { subTreeRoot.Children[childIndexInParent1] = this.ApplyRulesToSubtree(context, rules, child, subTreeRoot, childIndexInParent1); } } Node newNode; if (RuleProcessor.ApplyRulesToNode(context, rules, subTreeRoot, out newNode)) { context.PostProcessSubTree(subTreeRoot); subTreeRoot = newNode; } else { goto label_10; } } else { break; } } else { goto label_12; } } this.m_processedNodeMap[key] = key; goto label_12; label_10: this.m_processedNodeMap[key] = key; label_12: context.PostProcessSubTree(subTreeRoot); return(subTreeRoot); }
/// <summary> /// Apply rules to the current subtree in a bottom-up fashion. /// </summary> /// <param name="context">Current rule processing context</param> /// <param name="rules">The look-up table with the rules to be applied</param> /// <param name="subTreeRoot">Current subtree</param> /// <param name="parent">Parent node</param> /// <param name="childIndexInParent">Index of this child within the parent</param> /// <returns>the result of the transformation</returns> private Node ApplyRulesToSubtree( RuleProcessingContext context, ReadOnlyCollection<ReadOnlyCollection<Rule>> rules, Node subTreeRoot, Node parent, int childIndexInParent) { var loopCount = 0; var localProcessedMap = new Dictionary<SubTreeId, SubTreeId>(); SubTreeId subTreeId; while (true) { // Am I looping forever Debug.Assert(loopCount < 12, "endless loops?"); loopCount++; // // We may need to update state regardless of whether this subTree has // changed after it has been processed last. For example, it may be // affected by transformation in its siblings due to external references. // context.PreProcessSubTree(subTreeRoot); subTreeId = new SubTreeId(context, subTreeRoot, parent, childIndexInParent); // Have I seen this subtree already? Just return, if so if (m_processedNodeMap.ContainsKey(subTreeId)) { break; } // Avoid endless loops here - avoid cycles of 2 or more if (localProcessedMap.ContainsKey(subTreeId)) { // mark this subtree as processed m_processedNodeMap[subTreeId] = subTreeId; break; } // Keep track of this one localProcessedMap[subTreeId] = subTreeId; // Walk my children for (var i = 0; i < subTreeRoot.Children.Count; i++) { subTreeRoot.Children[i] = ApplyRulesToSubtree(context, rules, subTreeRoot.Children[i], subTreeRoot, i); } // Apply rules to myself. If no transformations were performed, // then mark this subtree as processed, and break out Node newSubTreeRoot; if (!ApplyRulesToNode(context, rules, subTreeRoot, out newSubTreeRoot)) { Debug.Assert(subTreeRoot == newSubTreeRoot); // mark this subtree as processed m_processedNodeMap[subTreeId] = subTreeId; break; } context.PostProcessSubTree(subTreeRoot); subTreeRoot = newSubTreeRoot; } context.PostProcessSubTree(subTreeRoot); return subTreeRoot; }
/// <summary> /// Apply rules to the current subtree in a bottom-up fashion. /// </summary> /// <param name="context"> Current rule processing context </param> /// <param name="rules"> The look-up table with the rules to be applied </param> /// <param name="subTreeRoot"> Current subtree </param> /// <param name="parent"> Parent node </param> /// <param name="childIndexInParent"> Index of this child within the parent </param> /// <returns> the result of the transformation </returns> private Node ApplyRulesToSubtree( RuleProcessingContext context, ReadOnlyCollection <ReadOnlyCollection <Rule> > rules, Node subTreeRoot, Node parent, int childIndexInParent) { var loopCount = 0; var localProcessedMap = new Dictionary <SubTreeId, SubTreeId>(); SubTreeId subTreeId; while (true) { // Am I looping forever Debug.Assert(loopCount < 12, "endless loops?"); loopCount++; // // We may need to update state regardless of whether this subTree has // changed after it has been processed last. For example, it may be // affected by transformation in its siblings due to external references. // context.PreProcessSubTree(subTreeRoot); subTreeId = new SubTreeId(context, subTreeRoot, parent, childIndexInParent); // Have I seen this subtree already? Just return, if so if (m_processedNodeMap.ContainsKey(subTreeId)) { break; } // Avoid endless loops here - avoid cycles of 2 or more if (localProcessedMap.ContainsKey(subTreeId)) { // mark this subtree as processed m_processedNodeMap[subTreeId] = subTreeId; break; } // Keep track of this one localProcessedMap[subTreeId] = subTreeId; // Walk my children for (var i = 0; i < subTreeRoot.Children.Count; i++) { var childNode = subTreeRoot.Children[i]; if (ShouldApplyRules(childNode, subTreeRoot)) { subTreeRoot.Children[i] = ApplyRulesToSubtree(context, rules, childNode, subTreeRoot, i); } } // Apply rules to myself. If no transformations were performed, // then mark this subtree as processed, and break out Node newSubTreeRoot; if (!ApplyRulesToNode(context, rules, subTreeRoot, out newSubTreeRoot)) { Debug.Assert(subTreeRoot == newSubTreeRoot); // mark this subtree as processed m_processedNodeMap[subTreeId] = subTreeId; break; } context.PostProcessSubTree(subTreeRoot); subTreeRoot = newSubTreeRoot; } context.PostProcessSubTree(subTreeRoot); return(subTreeRoot); }