Example #1
0
        private static readonly char[] longCommentID2 = { '-', '[', '=' }; //TODO: flawed approach? what if --[=asdfadf]?

        public static List <Token> Tokenize(TextReader textReader)
        {
            Validation.Requires.NotNull(textReader, nameof(textReader));

            TrackableTextReader trackableTextReader = new TrackableTextReader(textReader);

            Token         nextToken;
            List <Trivia> trivia;

            List <Token> tokenList = new List <Token>();

            while (!trackableTextReader.EndOfStream())
            {
                int fullStart = (int)trackableTextReader.Position;
                trivia    = ConsumeTrivia(trackableTextReader);
                nextToken = ReadNextToken(trackableTextReader, trivia, fullStart);
                tokenList.Add(nextToken);

                if (trackableTextReader.EndOfStream() && nextToken.Kind != SyntaxKind.EndOfFile)
                {
                    nextToken = new Token(SyntaxKind.EndOfFile, string.Empty, new List <Trivia>(), nextToken.End, nextToken.End);
                    tokenList.Add(nextToken);
                }
            }

            if (tokenList.Count == 0)
            {
                //If there is an empty program send back an end of file token.
                tokenList.Add(new Token(SyntaxKind.EndOfFile, "", new List <Trivia>(), 0, 0));
            }

            return(tokenList);
        }
Example #2
0
        private static Token ReadNextToken(TrackableTextReader stream, List <Trivia> trivia, int fullStart)
        {
            char nextChar;

            if (stream.EndOfStream())
            {
                return(new Token(SyntaxKind.EndOfFile, "", trivia, fullStart, (int)stream.Position));
            }

            nextChar = stream.Peek();

            // Keyword or Identifier
            if (char.IsLetter(nextChar) || (nextChar == '_'))
            {
                return(ReadAlphaToken(stream, trivia, fullStart));
            }
            // Number
            else if (char.IsDigit(nextChar))
            {
                return(ReadNumberToken(stream, trivia, fullStart));
            }
            // String
            else if (IsQuote(nextChar))
            {
                return(ReadStringToken(nextChar, stream, trivia, fullStart));
            }
            // Punctuation Bracket Operator
            else
            {
                return(ReadSymbolToken(stream, trivia, fullStart));
            }
        }
Example #3
0
        private static Trivia ReadLongComment(TrackableTextReader stream, string commentSoFar, int?level)
        {
            if (level == null)
            {
                throw new ArgumentNullException(nameof(level));
            }

            //TODO: re-write without regex
            Regex closeBracketPattern = new Regex(@"\]={" + level.ToString() + @"}\]");

            while (!closeBracketPattern.IsMatch(commentSoFar) && !stream.EndOfStream())
            {
                commentSoFar += stream.ReadChar();
            }

            return(new Trivia(SyntaxKind.Comment, commentSoFar));
        }
Example #4
0
        public static int CountLevels(bool validateCount, char character, int counter, TrackableTextReader stream, StringBuilder builder)
        {
            int levelCount = counter;

            while (character == '=' && !stream.EndOfStream())
            {
                builder.Append(stream.ReadChar());
                if (validateCount)
                {
                    levelCount--;
                }
                else
                {
                    levelCount++;
                }

                character = stream.Peek();
            }
            return(levelCount);
        }
Example #5
0
        private static Token ReadNumberToken(TrackableTextReader stream, List <Trivia> trivia, int fullStart)
        {
            StringBuilder number             = new StringBuilder();
            int           tokenStartPosition = (int)stream.Position;
            char          next = stream.Peek();

            // TODO: verify only one decimal point

            while (IsValidNumber(next))
            {
                number.Append(stream.ReadChar());
                next = stream.Peek();
            }

            if (IsValidTerminator(next) || stream.EndOfStream())
            {
                return(new Token(SyntaxKind.Number, number.ToString(), trivia, fullStart, tokenStartPosition));
            }
            else
            {
                return(new Token(SyntaxKind.Unknown, number.ToString(), trivia, fullStart, tokenStartPosition)); //TODO: Deal with invalid number/identifier: "234kjs"
            }
        }
Example #6
0
        private static Token ReadStringToken(char stringDelimiter, TrackableTextReader stream, List <Trivia> leadingTrivia, int fullStart)
        {
            StringBuilder fullString         = new StringBuilder();
            int           tokenStartPosition = (int)stream.Position;
            SyntaxKind    type = SyntaxKind.String;
            char          nextChar;

            switch (stringDelimiter)
            {
            case '"':
            case '\'':
                fullString.Append(stream.ReadChar());
                nextChar = stream.Peek();
                bool terminateString = false;
                while ((nextChar != stringDelimiter) && !stream.EndOfStream() && !terminateString)
                {
                    fullString.Append(stream.ReadChar());
                    nextChar = stream.Peek();

                    if (nextChar == '\r' || nextChar == '\n')
                    {
                        type            = SyntaxKind.UnterminatedString;
                        terminateString = true;
                    }
                }

                if (nextChar == stringDelimiter || terminateString)
                {
                    fullString.Append(stream.ReadChar());
                    return(new Token(type, fullString.ToString(), leadingTrivia, fullStart, tokenStartPosition));
                }
                else
                {
                    return(new Token(SyntaxKind.EndOfFile, fullString.ToString(), leadingTrivia, fullStart, tokenStartPosition));    //TODO bug... should return a string then a EOF token right?
                }

            case '[':
                fullString.Append(stream.ReadChar());
                int bracketLevel = 0;
                nextChar = stream.Peek();

                bracketLevel = CountLevels(false, nextChar, 0, stream, fullString);
                nextChar     = stream.Peek();

                if (nextChar == '[')
                {
                    fullString.Append(stream.ReadChar());
                    nextChar = stream.Peek();

                    //Lua ignores a new line directly after the opening delimiter of a string.
                    if (nextChar == '\r' || nextChar == '\n')
                    {
                        if (nextChar == '\r')
                        {
                            stream.ReadChar();
                        }

                        if (stream.Peek() == '\n')
                        {
                            stream.ReadChar();
                        }

                        type = SyntaxKind.IgnoreNewLineString;
                    }

                    while (!stream.EndOfStream())
                    {
                        if (nextChar == ']')
                        {
                            fullString.Append(stream.ReadChar());
                            nextChar = stream.Peek();
                            int currentLevel = bracketLevel;

                            currentLevel = CountLevels(true, nextChar, currentLevel, stream, fullString);
                            nextChar     = stream.Peek();

                            if ((nextChar == ']') && (currentLevel == 0))
                            {
                                fullString.Append(stream.ReadChar());
                                return(new Token(type, fullString.ToString(), leadingTrivia, fullStart, tokenStartPosition));
                            }
                        }
                        else
                        {
                            fullString.Append(stream.ReadChar());
                        }
                        nextChar = stream.Peek();
                    }

                    return(new Token(SyntaxKind.UnterminatedString, fullString.ToString(), leadingTrivia, fullStart, tokenStartPosition));
                }
                else
                {
                    if (bracketLevel == 0)
                    {
                        return(new Token(SyntaxKind.OpenBracket, nextChar.ToString(), leadingTrivia, fullStart, tokenStartPosition));
                    }
                    else
                    {
                        // Error, not valid syntax
                        return(new Token(SyntaxKind.Unknown, fullString.ToString(), leadingTrivia, fullStart, tokenStartPosition));
                    }
                }

            default:
                throw new ArgumentOutOfRangeException(nameof(stringDelimiter), "Unrecognized String delimiter");
            }
        }
Example #7
0
        private static readonly char[] longCommentID2 = { '-', '[', '=' }; //TODO: flawed approach? what if --[=asdfadf]?

        public static List<Token> Tokenize(TextReader textReader)
        {
            Validation.Requires.NotNull(textReader, nameof(textReader));

            TrackableTextReader trackableTextReader = new TrackableTextReader(textReader);

            Token nextToken;
            List<Trivia> trivia;

            List<Token> tokenList = new List<Token>();

            while (!trackableTextReader.EndOfStream())
            {
                int fullStart = (int)trackableTextReader.Position;
                trivia = ConsumeTrivia(trackableTextReader);
                nextToken = ReadNextToken(trackableTextReader, trivia, fullStart);
                tokenList.Add(nextToken);

                if (trackableTextReader.EndOfStream() && nextToken.Kind != SyntaxKind.EndOfFile)
                {
                    nextToken = new Token(SyntaxKind.EndOfFile, string.Empty, new List<Trivia>(), nextToken.End, nextToken.End);
                    tokenList.Add(nextToken);
                }
            }

            if (tokenList.Count == 0)
            {
                //If there is an empty program send back an end of file token.
                tokenList.Add(new Token(SyntaxKind.EndOfFile, "", new List<Trivia>(), 0, 0));
            }

            return tokenList;
        }
Example #8
0
        public static int CountLevels(bool validateCount, char character, int counter, TrackableTextReader stream, StringBuilder builder)
        {
            int levelCount = counter;
            while (character == '=' && !stream.EndOfStream())
            {
                builder.Append(stream.ReadChar());
                if (validateCount)
                {
                    levelCount--;
                }
                else
                {
                    levelCount++;
                }

                character = stream.Peek();
            }
            return levelCount;
        }
Example #9
0
        private static Token ReadStringToken(char stringDelimiter, TrackableTextReader stream, List<Trivia> leadingTrivia, int fullStart)
        {
            StringBuilder fullString = new StringBuilder();
            int tokenStartPosition = (int)stream.Position;
            SyntaxKind type = SyntaxKind.String;
            char nextChar;

            switch (stringDelimiter)
            {
                case '"':
                case '\'':
                    fullString.Append(stream.ReadChar());
                    nextChar = stream.Peek();
                    bool terminateString = false;
                    while ((nextChar != stringDelimiter) && !stream.EndOfStream() && !terminateString)
                    {
                        fullString.Append(stream.ReadChar());
                        nextChar = stream.Peek();

                        if (nextChar == '\r' || nextChar == '\n')
                        {
                            type = SyntaxKind.UnterminatedString;
                            terminateString = true;
                        }
                    }

                    if (nextChar == stringDelimiter || terminateString)
                    {
                        fullString.Append(stream.ReadChar());
                        return new Token(type, fullString.ToString(), leadingTrivia, fullStart, tokenStartPosition);
                    }
                    else
                    {
                        return new Token(SyntaxKind.EndOfFile, fullString.ToString(), leadingTrivia, fullStart, tokenStartPosition); //TODO bug... should return a string then a EOF token right?
                    }

                case '[':
                    fullString.Append(stream.ReadChar());
                    int bracketLevel = 0;
                    nextChar = stream.Peek();

                    bracketLevel = CountLevels(false, nextChar, 0, stream, fullString);
                    nextChar = stream.Peek();

                    if (nextChar == '[')
                    {
                        fullString.Append(stream.ReadChar());
                        nextChar = stream.Peek();

                        //Lua ignores a new line directly after the opening delimiter of a string.
                        if (nextChar == '\r' || nextChar == '\n')
                        {
                            if (nextChar == '\r')
                                stream.ReadChar();
                            if (stream.Peek() == '\n')
                                stream.ReadChar();
                            type = SyntaxKind.IgnoreNewLineString;
                        }

                        while (!stream.EndOfStream())
                        {
                            if (nextChar == ']')
                            {
                                fullString.Append(stream.ReadChar());
                                nextChar = stream.Peek();
                                int currentLevel = bracketLevel;

                                currentLevel = CountLevels(true, nextChar, currentLevel, stream, fullString);
                                nextChar = stream.Peek();

                                if ((nextChar == ']') && (currentLevel == 0))
                                {
                                    fullString.Append(stream.ReadChar());
                                    return new Token(type, fullString.ToString(), leadingTrivia, fullStart, tokenStartPosition);
                                }
                            }
                            else
                            {
                                fullString.Append(stream.ReadChar());
                            }
                            nextChar = stream.Peek();
                        }

                        return new Token(SyntaxKind.UnterminatedString, fullString.ToString(), leadingTrivia, fullStart, tokenStartPosition);
                    }
                    else
                    {
                        if (bracketLevel == 0)
                        {
                            return new Token(SyntaxKind.OpenBracket, nextChar.ToString(), leadingTrivia, fullStart, tokenStartPosition);
                        }
                        else
                        {
                            // Error, not valid syntax
                            return new Token(SyntaxKind.Unknown, fullString.ToString(), leadingTrivia, fullStart, tokenStartPosition);
                        }
                    }
                default:
                    throw new ArgumentOutOfRangeException(nameof(stringDelimiter), "Unrecognized String delimiter");
            }
        }
Example #10
0
        private static Token ReadNumberToken(TrackableTextReader stream, List<Trivia> trivia, int fullStart)
        {
            StringBuilder number = new StringBuilder();
            int tokenStartPosition = (int)stream.Position;
            char next = stream.Peek();
            // TODO: verify only one decimal point

            while (IsValidNumber(next))
            {
                number.Append(stream.ReadChar());
                next = stream.Peek();
            }

            if (IsValidTerminator(next) || stream.EndOfStream())
            {
                return new Token(SyntaxKind.Number, number.ToString(), trivia, fullStart, tokenStartPosition);
            }
            else
            {
                return new Token(SyntaxKind.Unknown, number.ToString(), trivia, fullStart, tokenStartPosition); //TODO: Deal with invalid number/identifier: "234kjs"
            }
        }
Example #11
0
        private static Token ReadNextToken(TrackableTextReader stream, List<Trivia> trivia, int fullStart)
        {
            char nextChar;

            if (stream.EndOfStream())
            {
                return new Token(SyntaxKind.EndOfFile, "", trivia, fullStart, (int)stream.Position);
            }

            nextChar = stream.Peek();

            // Keyword or Identifier
            if (char.IsLetter(nextChar) || (nextChar == '_'))
            {
                return ReadAlphaToken(stream, trivia, fullStart);
            }
            // Number
            else if (char.IsDigit(nextChar))
            {
                return ReadNumberToken(stream, trivia, fullStart);
            }
            // String
            else if (IsQuote(nextChar))
            {
                return ReadStringToken(nextChar, stream, trivia, fullStart);
            }
            // Punctuation Bracket Operator
            else
            {
                return ReadSymbolToken(stream, trivia, fullStart);
            }
        }
Example #12
0
        private static Trivia ReadLongComment(TrackableTextReader stream, string commentSoFar, int? level)
        {
            if (level == null)
            {
                throw new ArgumentNullException(nameof(level));
            }

            //TODO: re-write without regex
            Regex closeBracketPattern = new Regex(@"\]={" + level.ToString() + @"}\]");

            while (!closeBracketPattern.IsMatch(commentSoFar) && !stream.EndOfStream())
            {
                commentSoFar += stream.ReadChar();
            }

            return new Trivia(SyntaxKind.Comment, commentSoFar);
        }