private static RowRecogExprNode Replace(
            RowRecogExprNode optionalParent,
            RowRecogExprNode originalNode,
            IList<RowRecogExprNode> expandedRepeat)
        {
            if (optionalParent == null) {
                var newParentNode = new RowRecogExprNodeConcatenation();
                newParentNode.ChildNodes.AddAll(expandedRepeat);
                return newParentNode;
            }

            // for nested nodes, use a concatenation instead
            if (optionalParent is RowRecogExprNodeNested ||
                optionalParent is RowRecogExprNodeAlteration) {
                var concatenation = new RowRecogExprNodeConcatenation();
                concatenation.ChildNodes.AddAll(expandedRepeat);
                optionalParent.ReplaceChildNode(
                    originalNode,
                    Collections.SingletonList<RowRecogExprNode>(concatenation));
            }
            else {
                // concatenations are simply changed
                optionalParent.ReplaceChildNode(originalNode, expandedRepeat);
            }

            return null;
        }
        private static RowRecogExprNodeAlteration ExpandPermute(
            RowRecogExprNodePermute permute, 
            ExpressionCopier expressionCopier)
        {
            var e = PermutationEnumerator.Create(permute.ChildNodes.Count);
            var parent = new RowRecogExprNodeAlteration();
            foreach (var indexes in e) {
                var concat = new RowRecogExprNodeConcatenation();
                parent.AddChildNode(concat);
                for (var i = 0; i < indexes.Length; i++) {
                    var toCopy = permute.ChildNodes[indexes[i]];
                    var copy = toCopy.CheckedCopy(expressionCopier);
                    concat.AddChildNode(copy);
                }
            }

            return parent;
        }