// this is to implement partial parsing. it counts {}, (), and []. it stops parsing at the specified type, if outside of nesting.
        // also if last block token equals to the type, it will stop at the outer level. (i.e. last })
        private static List <ZScriptToken> ReadEverythingUntil(ZScriptTokenizer t, ZScriptTokenType type, bool eofIsOk, bool skipWhitespace)
        {
            List <ZScriptToken> tokens = new List <ZScriptToken>();

            int levelCurly  = 0;
            int levelSquare = 0;
            int levelParen  = 0;

            while (true)
            {
                if (skipWhitespace)
                {
                    t.SkipWhitespace();
                }

                long cpos = t.Reader.BaseStream.Position;

                ZScriptToken token = t.ReadToken();
                if (token == null)
                {
                    if (!eofIsOk)
                    {
                        throw new ShaderCompileException("Expected {0} or token, got <EOF>", type);
                    }
                    break;
                }

                // if this is the end token, don't check anything -- just return
                if (levelCurly == 0 && levelSquare == 0 && levelParen == 0 && token.Type == type)
                {
                    // rewind and return token list
                    t.Reader.BaseStream.Position = cpos;
                    break;
                }

                switch (token.Type)
                {
                case ZScriptTokenType.OpenCurly:
                    levelCurly++;
                    break;

                case ZScriptTokenType.CloseCurly:
                    levelCurly--;
                    break;

                case ZScriptTokenType.OpenParen:
                    levelParen++;
                    break;

                case ZScriptTokenType.CloseParen:
                    levelParen--;
                    break;

                case ZScriptTokenType.OpenSquare:
                    levelSquare++;
                    break;

                case ZScriptTokenType.CloseSquare:
                    levelSquare--;
                    break;
                }

                tokens.Add(token);
            }

            return(tokens);
        }