public IProductionRuleCaptureStructure Union(IProductionRuleCaptureStructure second)
        {
            if (this.Count == 0)
            {
                return(second);
            }
            else if (second.Count == 0)
            {
                return(this);
            }
            var result = new ProductionRuleCaptureStructure(this.owner);
            var left   = this.Keys.Except(second.Keys).ToArray();
            var middle = this.Keys.Intersect(second.Keys).ToArray();
            var right  = second.Keys.Except(this.Keys).ToArray();

            foreach (var element in left)
            {
                result._Add(element, this[element]);
            }
            foreach (var element in middle)
            {
                var leftElement   = this[element];
                var rightElement  = second[element];
                var middleElement = leftElement.Union(rightElement);
                result._Add(element, middleElement);
            }
            foreach (var element in right)
            {
                result._Add(element, second[element]);
            }

            if (this.ResultType == second.ResultType)
            {
                result.ResultType = this.ResultType;
            }
            else
            {
                result.ResultType = ResultedDataType.ComplexType;
            }
            result.ResultedTypeName = this.ResultedTypeName ?? second.ResultedTypeName;
            ((ControlledCollection <IProductionRuleSource>)(result.Sources)).AddRange(this.Sources.ToArray());
            ((ControlledCollection <IProductionRuleSource>)(result.Sources)).AddRange(second.Sources.ToArray());
            result.Optional = this.Optional || second.Optional;

            return(result);
        }
        public IProductionRuleCaptureStructure Concat(IProductionRuleCaptureStructuralItem item)
        {
            var k = (from s in item.Sources
                     let sN = s as INamedProductionRuleSource
                              where sN != null && !string.IsNullOrEmpty(sN.Name)
                              select sN).FirstOrDefault();

            if (item.ResultType == ResultedDataType.PassThrough)
            {
                return(this.Union((IProductionRuleCaptureStructure)item));
            }
            else if (k == null)
            {
                return(this);
            }

            var result      = new ProductionRuleCaptureStructure(this.owner);
            int?offsetIndex = null;

            foreach (var element in this)
            {
                if (k.Name == element.Value.Name)
                {
                    if (item.ResultType != ResultedDataType.FlagEnumerationItem)
                    {
                        if (element.Value.BucketIndex == null)
                        {
                            element.Value.BucketIndex = offsetIndex = 1;
                        }
                        else
                        {
                            offsetIndex = element.Value.BucketIndex;
                        }
                        result._Add(element.Value.BucketName, element.Value);
                    }
                    else
                    {
                        result._Add(element.Key, element.Value.Union(item));
                    }
                }
                else
                {
                    result._Add(element.Key, element.Value);
                }
            }
            if (!result.ContainsKey(k.Name))
            {
                if (offsetIndex == null)
                {
                    result._Add(k.Name, item);
                }
                else
                {
                    item.BucketIndex = offsetIndex + 1;
                    result._Add(item.BucketName, item);
                }
            }
            var first = this.Values.FirstOrDefault();

            if (this.Count > 0 && first != null && (first.ResultType == ResultedDataType.FlagEnumerationItem || first.ResultType == ResultedDataType.EnumerationItem))
            {
                if (first.ResultType == ResultedDataType.EnumerationItem)
                {
                    first.ResultType = ResultedDataType.FlagEnumerationItem;
                }
                if (item.ResultType == ResultedDataType.EnumerationItem)
                {
                    item.ResultType = ResultedDataType.FlagEnumerationItem;
                }
            }
            ResultedDataType resultDataType = ResultedDataType.Enumeration;

            foreach (var value in result.Values)
            {
                if (resultDataType == ResultedDataType.Enumeration &&
                    !(value.ResultType == ResultedDataType.EnumerationItem ||
                      value.ResultType == ResultedDataType.FlagEnumerationItem))
                {
                    resultDataType = ResultedDataType.ComplexType;
                }
            }
            result.ResultedTypeName = this.ResultedTypeName;
            result.ResultType       = resultDataType;
            return(result);
        }