Пример #1
0
        private Token ReadNumber(CodeReader reader)
        {
            string number      = "";
            int    tokenLine   = reader.Line;
            int    tokenColumn = reader.Column;

            while (reader.CheckCurrent(char.IsDigit))
            {
                number += reader.Consume();
            }

            if (reader.TryMatch('.'))
            {
                number += '.';
                while (reader.CheckCurrent(char.IsDigit))
                {
                    number += reader.Consume();
                }
            }

            double result;

            if (!double.TryParse(number, out result))
            {
                OnError("Invalid number", tokenLine, tokenColumn);
            }

            return(new Token(number, TokenKind.Number, tokenLine, tokenColumn));
        }
Пример #2
0
        private Token ReadIdentifierOrKeyword(CodeReader reader)
        {
            string identifier  = "";
            int    tokenLine   = reader.Line;
            int    tokenColumn = reader.Column;

            if (!reader.CheckCurrent(IsValidIdentifierStartChar))
            {
                OnError("Invalid identifier name start", tokenLine, tokenColumn);
            }

            identifier += reader.Consume();

            while (reader.CheckCurrent(IsValidIdentifierChar))
            {
                identifier += reader.Consume();
            }

            return(new Token(identifier, IsKeyword(identifier) ? TokenKind.Keyword : TokenKind.Identifier, tokenLine, tokenColumn));
        }
Пример #3
0
        /// <summary>
        /// Separate a string with the code into several tokens specifying the content of the token, the kind and position on the code.
        /// </summary>
        /// <param name="code">A code in a specific language to be tokenized.</param>
        /// <returns>A IEnumerable object with all token decomposition of code.</returns>
        public IEnumerable <Token> GetTokens(string code)
        {
            // Creates a reader of the code. This object allow to consume characters, check conditions and determine whenever a new line or end of file is detected.
            CodeReader reader = new CodeReader(code);

            // If there is no characted on the code we get an empty enumerable.
            if (reader.EndOfFile)
            {
                yield break;
            }


            // Move reader to first character of the code.
            reader.MoveHead();

            // While reader has code to read.
            while (!reader.EndOfFile)
            {
                // save current character to check what kind of token should be read.
                char current = reader.Current;

                // The current character is an instruction-separator char that should be read.
                if (IsSeparatorChar(current))
                {
                    yield return(ReadSeparator(reader));

                    continue;
                }

                // The current character is a white-space character.
                if (IsEmptySpaceChar(current))
                {
                    reader.Consume(); // just consume the white-space character.
                    continue;
                }

                // Current and next characters are slahes, identifying comment starting that should be read.
                if (current == '/' && reader.HasNext && reader.Next == '/')
                {
                    yield return(ReadComment(reader));

                    continue;
                }

                // Current character is a symbol and should be read.
                if (IsSymbol(current))
                {
                    yield return(ReadSymbol(reader));

                    continue;
                }

                // Current character is a text start character so literal text should be read.
                if (IsTextLiteralDelimiterChar(current))
                {
                    yield return(ReadTextLiteral(reader));

                    continue;
                }

                // Current character is a valid identifier begginig that should be read.
                if (IsValidIdentifierStartChar(current))
                {
                    yield return(ReadIdentifierOrKeyword(reader));

                    continue;
                }

                // Current character is a digit, representing a number that should be read.
                if (reader.CheckCurrent(char.IsDigit)) // read a number
                {
                    yield return(ReadNumber(reader));

                    continue;
                }

                // Reaches an unknown character that is returned as a unknown token type.
                yield return(ReadUnknownSymbol(reader));
            }
        }