/// <summary>
        /// Reads an OpenLisp.NET list expression.
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="openLispList"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        public static OpenLispVal ReadList(TokensReader reader, OpenLispList openLispList, char start, char end)
        {
            string token = reader.Next();

            if (token[0] == start)
            {
                while ((token = reader.Peek()) != null && token[0] != end)
                {
                    openLispList.Conj(ReadForm(reader));
                }

                if (token == null)
                {
                    throw new ParseError("expected '" + end + "', got EOF");
                }
                reader.Next();

                return(openLispList);
            }

            throw new ParseError("expected '" + start + "'");
        }
        /// <summary>
        /// This static method recursively processes
        /// OpenLisp.NET forms and tokenizes them.
        /// </summary>
        /// <param name="reader"></param>
        /// <returns></returns>
        public static OpenLispVal ReadForm(TokensReader reader)
        {
            string token = reader.Peek();

            if (token == null)
            {
                throw new OpenLispContinue();
            }

            OpenLispVal form = null;

            switch (token)
            {
            case "'":
                reader.Next();
                return(new OpenLispList(new OpenLispSymbol("quote"),
                                        ReadForm(reader)));

            case "`":
                reader.Next();
                return(new OpenLispList(new OpenLispSymbol("quasiquote"),
                                        ReadForm(reader)));

            case "~":
                reader.Next();
                return(new OpenLispList(new OpenLispSymbol("unquote"),
                                        ReadForm(reader)));

            case "~@":
                reader.Next();
                return(new OpenLispList(new OpenLispSymbol("splice-unquote"),
                                        ReadForm(reader)));

            case "^":
                reader.Next();
                OpenLispVal meta = ReadForm(reader);
                return(new OpenLispList(new OpenLispSymbol("with-meta"),
                                        ReadForm(reader),
                                        meta));

            case "@":
                reader.Next();
                return(new OpenLispList(new OpenLispSymbol("deref"),
                                        ReadForm(reader)));

            case "(": form = ReadList(reader, new OpenLispList(), '(', ')'); break;

            case ")": throw new ParseError("unexpected ')'");

            case "[": form = ReadList(reader, new OpenLispVector(), '[', ']'); break;

            case "]": throw new ParseError("unexpected ']'");

            case "{": form = ReadHashMap(reader); break;

            case "}": throw new ParseError("unexpected '}'");

            default: form = ReadAtom(reader); break;
            }
            return(form);
        }