private bool ProcessIdentifier()
        {
            var type = TinyhandAtomType.Identifier;

            if (this.ValueSpan[0] == TinyhandConstants.AtSign)
            { // @ Special Identifier
                type           = TinyhandAtomType.SpecialIdentifier;
                this.ValueSpan = this.ValueSpan.Slice(1);
                this.AddPosition(1);

                if (this.ValueSpan.Length == 0)
                {
                    return(false);
                }

                var b = this.ValueSpan[0];
                if (TinyhandHelper.IsDigit(b) || b == (byte)'+' || b == (byte)'-')
                { // Number
                    this.ThrowException("An identifier can not begin with a digit.");
                }
            }

            this.AtomType = type;

            return(true);
        }
        private bool ReadQuote()
        {
            this.AddPosition(1); // Skip quote.

            if (this.Remaining >= 2 && this.buffer[this.Position] == TinyhandConstants.Quote && this.buffer[this.Position + 1] == TinyhandConstants.Quote)
            {                        // """Triple quoted string""". Multi-line literal.
                this.AddPosition(2); // Skip 2 quotes.
                var stringSpan = this.buffer.Slice(this.Position);
                var length     = this.Get3QuotedStringLength(stringSpan);
                this.ValueSpan = stringSpan.Slice(0, length);

                this.AddPosition(length + 3); // String + 3 quotes.
                this.AtomType  = TinyhandAtomType.Value_String;
                this.ValueLong = 1;           // Triple quoted.
            }
            else
            { // "single line string"
                var stringSpan = this.buffer.Slice(this.Position);
                var length     = this.GetQuotedStringLength(stringSpan);
                this.ValueSpan = TinyhandHelper.GetUnescapedSpan(stringSpan.Slice(0, length));

                this.AddPosition(length + 1); // String + quote.
                this.AtomType = TinyhandAtomType.Value_String;
            }
            return(true);
        }
        /// <summary>
        /// Read one tinyhand symbol at a time.
        /// </summary>
        /// <returns>True if the read is successful. False if no data is available (AtomType is set to None).</returns>
        public bool Read()
        {
            this.InitializeValue();

            if (this.SkipWhiteSpace())
            { // Separator, (Comment, LineFeed)
                return(true);
            }
            if (this.Position >= this.Length)
            { // No data left.
                return(false);
            }

            var b = this.Current;

            this.AtomLineNumber         = this.lineNumber;
            this.AtomBytePositionInLine = this.bytePositionInLine;
            switch (b)
            {
            case TinyhandConstants.OpenBrace:     // {
                this.AtomType  = TinyhandAtomType.StartGroup;
                this.ValueSpan = this.buffer.Slice(this.Position, 1);
                this.AddPosition(1);
                return(true);

            case TinyhandConstants.CloseBrace:     // }
                this.AtomType  = TinyhandAtomType.EndGroup;
                this.ValueSpan = this.buffer.Slice(this.Position, 1);
                this.AddPosition(1);
                return(true);

            case TinyhandConstants.Quote:     // "string"
                return(this.ReadQuote());

            case TinyhandConstants.EqualsSign:     // =
                this.AtomType  = TinyhandAtomType.Assignment;
                this.ValueSpan = this.buffer.Slice(this.Position, 1);
                this.AddPosition(1);
                return(true);

            case TinyhandConstants.Slash:     // "//" or "/*"
                this.AtomType = TinyhandAtomType.Comment;
                this.ReadComment();
                return(true);

            default:  // Number, Binary, Modifier/Value, Identifier/Limited identifier
                if (TinyhandHelper.IsDigit(b) || b == (byte)'+' || b == (byte)'-')
                {     // Number
                    return(this.ReadNumber());
                }

                if (b == (byte)'b' && this.Remaining >= 2 && this.buffer[this.Position + 1] == TinyhandConstants.Quote)
                {     // Binary b"Base64"
                    return(this.ReadBinary());
                }

                this.ReadRawString();
                if (this.ValueSpan.Length == 0)
                {
                    goto Unexpected_Symbol;
                }

                if (this.ProcessValue())
                {
                    this.AddPosition(this.ValueSpan.Length);
                    return(true);
                }

                if (this.ProcessModifier())
                {
                    this.AddPosition(this.ValueSpan.Length);
                    return(true);
                }

                if (this.ProcessIdentifier())
                {
                    this.AddPosition(this.ValueSpan.Length);
                    return(true);
                }

Unexpected_Symbol:
                this.ThrowUnexpectedCharacterException(b);
                break;
            }

            return(false);
        }