Пример #1
0
        private Token ReadNew()
        {
            CommentMode comment = CommentMode.None;
            int         readInt;
            Token       tmpToken;

            while ((readInt = _source.Read()) >= 0)
            {
                // Handle comment mode
                if (comment == CommentMode.Line)
                {
                    if (readInt == '\n' || readInt == '\r')
                    {
                        comment = CommentMode.None;
                    }
                    continue;
                }
                else if (comment == CommentMode.Block)
                {
                    if (readInt == '*')
                    {
                        if ((readInt = _source.Read()) == '/')
                        {
                            comment = CommentMode.None;
                        }
                        else if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                    }
                    continue;
                }

                // Skip whitespaces
                if (char.IsWhiteSpace((char)readInt))
                {
                    continue;
                }

                long position = _source.Position;
                switch (readInt)
                {
                case '+':
                    switch (readInt = _source.Read())
                    {
                    case '+': return(new Token(TokenType.OperatorIncrement, position));

                    case '=': return(new Token(TokenType.OperatorAssignPlus, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorPlus, position));
                    }

                case '-':
                    switch (readInt = _source.Read())
                    {
                    case '-': return(new Token(TokenType.OperatorDecrement, position));

                    case '=': return(new Token(TokenType.OperatorAssignMinus, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorMinus, position));
                    }

                case '*':
                    switch (readInt = _source.Read())
                    {
                    case '=': return(new Token(TokenType.OperatorAssignTimes, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorTimes, position));
                    }

                case '/':
                    switch (readInt = _source.Read())
                    {
                    case '=': return(new Token(TokenType.OperatorAssignDivide, position));

                    case '/':
                        comment = CommentMode.Line;
                        break;

                    case '*':
                        comment = CommentMode.Block;
                        break;

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorDivide, position));
                    }
                    break;

                case '%':
                    switch (readInt = _source.Read())
                    {
                    case '=': return(new Token(TokenType.OperatorAssignModulo, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorModulo, position));
                    }

                case '(': return(new Token(TokenType.BracketLeft, position));

                case ')': return(new Token(TokenType.BracketRight, position));

                case '[': return(new Token(TokenType.SquareBracketLeft, position));

                case ']': return(new Token(TokenType.SquareBracketRight, position));

                case '{': return(new Token(TokenType.CurlyBracketLeft, position));

                case '}': return(new Token(TokenType.CurlyBracketRight, position));

                case ';': return(new Token(TokenType.EndOfInstruction, position));

                case ',': return(new Token(TokenType.Comma, position));

                case '.':
                    // It might be a floating point number (in fact, iff it is follows by a digit)
                    int nextInt = _source.Read();
                    if (nextInt >= 0)
                    {
                        _source.PushBack(nextInt);
                        if (char.IsDigit((char)nextInt))
                        {
                            // Since the next character is a digit, ProcessNumber_Float() cannot return null
                            return(ProcessNumber_Float(position, new StringBuilder(), readInt));
                        }
                    }
                    return(new Token(TokenType.Period, position));

                case ':':
                    switch (readInt = _source.Read())
                    {
                    case ':': return(new Token(TokenType.DoubleColon, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.Colon, position));
                    }

                case '<':
                    switch (readInt = _source.Read())
                    {
                    case '<':
                        if ((readInt = _source.Read()) == '=')
                        {
                            return(new Token(TokenType.OperatorAssignLeftShift, position));
                        }
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorLeftShift, position));

                    case '=': return(new Token(TokenType.OperatorLessThanEqual, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorLessThan, position));
                    }

                case '>':
                    switch (readInt = _source.Read())
                    {
                    case '>':
                        if ((readInt = _source.Read()) == '=')
                        {
                            return(new Token(TokenType.OperatorAssignRightShift, position));
                        }
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorRightShift, position));

                    case '=': return(new Token(TokenType.OperatorMoreThanEqual, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorMoreThan, position));
                    }

                case '!':
                    switch (readInt = _source.Read())
                    {
                    case '=': return(new Token(TokenType.OperatorNotEqual, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorLogicalNot, position));
                    }

                case '~': return(new Token(TokenType.OperatorBitwiseNot, position));

                case '&':
                    switch (readInt = _source.Read())
                    {
                    case '&': return(new Token(TokenType.OperatorLogicalAnd, position));

                    case '=': return(new Token(TokenType.OperatorAssignBitwiseAnd, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorBitwiseAnd, position));
                    }

                case '|':
                    switch (readInt = _source.Read())
                    {
                    case '|': return(new Token(TokenType.OperatorLogicalOr, position));

                    case '=': return(new Token(TokenType.OperatorAssignBitwiseOr, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorBitwiseOr, position));
                    }

                case '^':
                    switch (readInt = _source.Read())
                    {
                    case '=': return(new Token(TokenType.OperatorAssignBitwiseXor, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorBitwiseXor, position));
                    }

                case '=':
                    switch (readInt = _source.Read())
                    {
                    case '=': return(new Token(TokenType.OperatorEqual, position));

                    default:
                        if (readInt >= 0)
                        {
                            _source.PushBack(readInt);
                        }
                        return(new Token(TokenType.OperatorAssign, position));
                    }

                case '\'':
                    switch (readInt = _source.Read())
                    {
                    case '\'':
                        throw new SyntaxException(_source.Position, "Empty character");

                    case '\\':
                        switch (readInt = _source.Read())
                        {
                        case '0': readInt = 0; break;

                        case '\'': break;

                        case '\\': break;

                        case 'n': readInt = '\n'; break;

                        case 'r': readInt = '\r'; break;

                        case 't': readInt = '\t'; break;

                        default:
                            throw new SyntaxException(_source.Position, "Unrecognized escape sequence");
                        }
                        break;
                    }
                    if (_source.Read() != '\'')
                    {
                        throw new SyntaxException(_source.Position, "Too many characters");
                    }
                    return(new ValuedToken <string>(TokenType.DecInt, position, readInt.ToString()));

                default:
                    if ((tmpToken = ProcessNumber(readInt)) != null)
                    {
                        return(tmpToken);
                    }
                    if ((tmpToken = ProcessName(readInt)) != null)
                    {
                        return(tmpToken);
                    }
                    if ((tmpToken = ProcessString(readInt)) != null)
                    {
                        return(tmpToken);
                    }
                    throw new SyntaxException(_source.Position, "Unrecognized character: " + (char)readInt);
                }
            }

            // We reached the end
            return(new Token(TokenType.EndOfDocument, _source.Position + 1));
        }