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; }