public CodeBlockNode AddNode(IAbstractSyntaxTree lexerNode)
        {
            switch (lexerNode.Type)
            {
            case Lexer.TokenType.WhileLoop:
                return(AddNode(WhileBlock.Parse(this, lexerNode)));

            case Lexer.TokenType.ConditionalSentence:
                return(AddNode(ConditionBlockNode.Parse(this, lexerNode)));

            case Lexer.TokenType.CodeBlockNode:
                return(AddNode(CodeBlockNode.Parse(this, lexerNode)));

            case Lexer.TokenType.ForLoop:
                return(AddNode(ForLoopNode.Parse(this, lexerNode)));

            case Lexer.TokenType.ForEachLoop:
                return(AddNode(ForEachNode.Parse(this, lexerNode)));

            case Lexer.TokenType.StatementWithEndOfLine:
                if (lexerNode.Children.Count == 2)
                {
                    return(AddStatement(lexerNode.Children[0]));
                }
                else
                {
                    //empty statement a.k.a ";"
                    return(this);
                }

            case Lexer.TokenType.UnknownNode:
                ErrorCode.InvalidStructure.ReportAndThrow(Parser.GetSequencePoint(lexerNode), "Could not parse as a statement");
                return(null);   //unreachable

            default:
                ErrorCode.InvalidStructure.ReportAndThrow(Parser.GetSequencePoint(lexerNode), "Unexpected node {0} in while parsing code block", lexerNode.Type);
                return(null);   //unreachable
            }
        }
        public static ForEachNode Parse(ContextNode context, IAbstractSyntaxTree lexerNode)
        {
            //For + LeftParenthesis + ForEachDeclaration + In + Value + RightParenthesis + CodeConstruct),
            Contract.Requires(lexerNode.Type == Lexer.TokenType.ForEachLoop);

            var instance = new ForEachNode(context, context.Parser.GetSequencePoint(lexerNode));

            var collection = ExpressionNode.Parse(context, lexerNode.Children[4]);

            if (!collection.IsGettable)
            {
                ErrorCode.NotAnRValue.ReportAndThrow(collection.SequencePoint, "collection must be a gettable expression");
            }
            if (collection.ExpressionReturnType.IsTypeless())
            {
                ErrorCode.InvalidForEachCollection.ReportAndThrow(collection.SequencePoint, "collection must not be a typeless expression");
            }
            var collectionElementType = collection.ExpressionReturnType.GetEnumerableElementType();

            if (collectionElementType == null)
            {
                ErrorCode.InvalidForEachCollection.ReportAndThrow(collection.SequencePoint, "Cannot iterate over expression type {0}", collection.ExpressionReturnType);
            }

            var declaration = LoopVariableDeclaration.Parse(context, lexerNode.Children[2], collectionElementType);

            if (!collectionElementType.IsAssignableTo(declaration.Variable.VariableType))
            {
                ErrorCode.TypeMismatch.ReportAndThrow(declaration.SequencePoint, "Cannot assign collection elements of type {0} to {1}", collectionElementType, declaration.Variable.VariableType);
            }

            instance.collection = collection;
            instance.variable   = declaration;

            instance.body = CodeBlockNode.Parse(instance, lexerNode.Children[6]);

            return(instance);
        }