Пример #1
0
        /// <summary>
        /// Parses tdta contents into tokens. Throws a generic exception if unrecognized tokens are encountered
        /// </summary>
        /// <param name="r"></param>
        /// <returns></returns>
        public static Token nextToken(PsdBinaryReader r)
        {
            if (!r.CanReadByte())
            {
                return(null);
            }

            char c = r.ReadAsciiChars(1)[0];

            switch (c)
            {
            case '(': return(new Token(parseBinary(r)));                    //Binary data. Leading and trailing parens are stripped, and escaped parens are restored to normal.

            case '[': return(new Token(TokenType.StartList, c.ToString())); // [ opening list char

            case ']': return(new Token(TokenType.EndList, c.ToString()));   //Closing list char
            }
            //<< opening dict
            //>> closing dict
            if (c == '<' || c == '>')
            {
                char c2 = r.ReadAsciiChars(1)[0];
                if (c2 != c)
                {
                    throw new TdTaParseException("Unrecognized token: " + c + c2, r);
                }

                if (c == '<')
                {
                    return(new Token(TokenType.StartDict, "<<"));
                }
                else
                {
                    return(new Token(TokenType.EndDict, ">>"));
                }
            }
            //Dict key (Any non-whitespace, non-[]<> sequence allowed following forward slash)
            if (c == '/')
            {
                StringBuilder sb = new StringBuilder(40);
                while (r.CanReadByte())
                {
                    //Peek at the next char to see if it is whitespace
                    char pc = (char)r.PeekChar();
                    if (Char.IsWhiteSpace(pc) || pc == '\n' || pc == '[' || pc == ']' || pc == '<' || pc == '>')
                    {
                        //We're done.
                        //Strip the leading slash, create token with name
                        return(new Token(TokenType.MapKey, sb.ToString()));
                    }
                    else
                    {
                        //A valid char, append it.
                        sb.Append(r.ReadChar());
                    }
                }
            }
            //Integer or double. Ends at whitespace, newline, ], or >
            if (Char.IsDigit(c) || c == '-' || c == '.')
            {
                StringBuilder sb = new StringBuilder(40);
                sb.Append(c);
                while (r.CanReadByte())
                {
                    //Peek at the next char to see if it is whitespace
                    char pc = (char)r.PeekChar();
                    if (Char.IsWhiteSpace(pc) || pc == '\n' || pc == ']' || pc == '>')
                    {
                        //We're done. Find out what kind of number it is.
                        string s = sb.ToString();
                        //If it has a decimal, it's a double
                        if (s.Contains('.'))
                        {
                            return(new Token(TokenType.Double, double.Parse(s, floatingPointStyle, NumberFormatInfo.InvariantInfo)));
                        }
                        else
                        {
                            return(new Token(TokenType.Integer, int.Parse(s, NumberStyles.Integer, NumberFormatInfo.InvariantInfo)));
                        }
                    }
                    else if (Char.IsDigit(c) || c == '-' || c == '.')
                    {
                        //A valid char, append it.
                        sb.Append(r.ReadChar());
                    }
                    else
                    {
                        //Unrecognized char in numeric sq
                        throw new TdTaParseException("Unrecognized character in numeric sequence: " + sb.ToString() + pc, r);
                    }
                }
            }
            //Boolean (true|false) parsing
            if (c == 't' || c == 'T' || c == 'f' || c == 'F')
            {
                string s  = c.ToString() + r.ReadChar().ToString() + r.ReadChar().ToString() + r.ReadChar().ToString();
                char   pc = (char)r.PeekChar();
                if (s.Equals("true", StringComparison.OrdinalIgnoreCase))
                {
                    return(new Token(TokenType.Boolean, true));
                }
                else if (s.Equals("fals", StringComparison.OrdinalIgnoreCase) && (pc == 'e' || pc == 'E'))
                {
                    r.ReadChar(); //discard 'e'
                    return(new Token(TokenType.Boolean, false));
                }
                else
                {
                    throw new TdTaParseException("Unrecognized boolean value: " + s + pc, r);
                }
            }
            //Whitespace parsing
            if (Char.IsWhiteSpace(c) || c == '\n')
            {
                StringBuilder sb = new StringBuilder(40);
                sb.Append(c);
                while (r.CanReadByte())
                {
                    //Peek at the next char to see if it is whitespace
                    char pc = (char)r.PeekChar();
                    if (Char.IsWhiteSpace(pc) || pc == '\n')
                    {
                        sb.Append(r.ReadChar());
                    }
                    else
                    {
                        //We done.
                        break;
                    }
                }
                return(new Token(TokenType.Whitespace, sb.ToString()));
            }
            throw new TdTaParseException("Unrecognized token: " + c, r);
        }