object IAstVisitor.Visit(Sequence sequence)
 {
     return Visit(sequence);
 }
        protected virtual object Visit(Sequence sequence)
        {
            Type targetType = this._targetType.Peek();
            object ret;

            if (targetType.IsArray)
            {
                Type elementType = targetType.GetElementType();
                Array newArray = Array.CreateInstance(elementType, sequence.Elements.Length);

                this._targetType.Push(elementType);
                for (int elemNum = 0; elemNum < sequence.Elements.Length; elemNum++)
                {
                    AstNode element = sequence.Elements[elemNum];

                    ValueError[] elementErrors = null;
                    using (ErrorCollector errors = new ErrorCollector(this))
                    {
                        object value = element.Visit(this);
                        if (errors.Count == 0)
                            newArray.SetValue(value, elemNum);

                        elementErrors = errors.ToArray();
                    }
                    this.RaiseError(elementErrors);
                }
                this._targetType.Pop();

                ret = newArray;
            }
            else
            {
                Type realType;
                if (targetType.IsInterface)
                    realType = OnResolveInterfaceType(targetType);
                else
                    realType = targetType;

                ret = Activator.CreateInstance(realType);

                MethodInfo[] addMethods =
                    realType.GetMethods(BindingFlags.Public | BindingFlags.Instance)
                            .Where(a => StringComparer.InvariantCultureIgnoreCase.Equals(a.Name, "Add"))
                            .ToArray();

                for (int elemNum = 0; elemNum < sequence.Elements.Length; elemNum++)
                {
                    List<ValueError> elementErrors = new List<ValueError>();
                    bool success = false;

                    for (int addNum = 0; addNum < addMethods.Length; addNum++)
                    {
                        ParameterInfo[] addParams = addMethods[addNum].GetParameters();

                        if (addParams.Length != 1)
                            continue;

                        this._targetType.Push(addParams[0].ParameterType);
                        using (ErrorCollector errors = new ErrorCollector(this))
                        {
                            object value = sequence.Elements[elemNum].Visit(this);

                            if (errors.Count == 0)
                            {
                                try
                                {
                                    addMethods[addNum].Invoke(ret, new[] {value});
                                    success = true;
                                    break;
                                }
                                catch (Exception ex)
                                {
                                    this.RaiseError(new AddError(addMethods[addNum],
                                                                 new[] {value},
                                                                 new[] {sequence.Elements[elemNum]},
                                                                 ex));
                                }
                            }

                            elementErrors.AddRange(errors);
                        }
                        this._targetType.Pop();
                    }

                    if (!success)
                    {
                        this.RaiseError(elementErrors);
                    }
                }
            }

            return ret;
        }
        protected virtual AstNode GetAstNode(IEnumerator<Token> enumerator)
        {
            AstNode ret;
            switch (enumerator.Current.Type)
            {
                case TokenType.ParameterName:
                    ret = new ParameterName(enumerator.Current,
                                            enumerator.Current.Value);
                    enumerator.MoveNext();
                    break;
                case TokenType.SwitchParameter:
                    Token token = enumerator.Current;
                    enumerator.MoveNext();
                    ret = new SwitchParameter(token,
                                              token.Value,
                                              this.GetAstNode(enumerator));
                    break;
                case TokenType.NumericValue:
                    ret = new LiteralValue(
                                            enumerator.Current,
                                            LiteralValueType.Numeric,
                                            enumerator.Current.Value);
                    enumerator.MoveNext();
                    break;
                case TokenType.StringValue:
                    ret = new LiteralValue(
                                            enumerator.Current,
                                            LiteralValueType.String,
                                            enumerator.Current.Value);
                    enumerator.MoveNext();
                    break;
                case TokenType.BoolValue:
                    ret = new LiteralValue(
                                            enumerator.Current,
                                            LiteralValueType.Boolean,
                                            enumerator.Current.Value);
                    enumerator.MoveNext();
                    break;
                case TokenType.NullValue:
                    ret = new LiteralValue(
                                            enumerator.Current,
                                            LiteralValueType.Null,
                                            enumerator.Current.Value);
                    enumerator.MoveNext();
                    break;
                case TokenType.ListStart:
                    ret = this.GetSequence(enumerator);
                    break;
                case TokenType.DictionaryStart:
                    ret = this.GetAssocArray(enumerator);
                    break;
                //case TokenType.DictionaryValueSeperator:
                //case TokenType.DictionaryKeySeperator:
                case TokenType.DictionaryEnd:
                //case TokenType.ListValueSeperator:
                case TokenType.ListEnd:
                    throw new Exception("Invalid token sequence.");

                default:
                    throw new ArgumentOutOfRangeException();
            }

            if (enumerator.Current.Type == TokenType.ListValueSeperator)
            {
                enumerator.MoveNext();

                AstNode obj = this.GetAstNode(enumerator);
                if (obj is Sequence)
                {
                    var list = new List<AstNode>(((Sequence) obj).Elements);
                    list.Add(ret);
                    ret = new Sequence(ret.SourceInfo, list);
                }
                else
                {
                    ret = new Sequence(ret.SourceInfo, new[] {ret, obj});
                }
            }

            return ret;
        }