private bool ScanIdentifier_FastPath()

in src/Compilers/CSharp/Portable/Parser/Lexer.cs [1468:1630]


        private bool ScanIdentifier_FastPath(ref TokenInfo info)
        {
            if ((_mode & LexerMode.MaskLexMode) == LexerMode.DebuggerSyntax)
            {
                // Debugger syntax is wonky.  Can't use the fast path for it.
                return false;
            }

            var currentOffset = TextWindow.Offset;
            var characterWindow = TextWindow.CharacterWindow;
            var characterWindowCount = TextWindow.CharacterWindowCount;

            var startOffset = currentOffset;

            while (true)
            {
                if (currentOffset == characterWindowCount)
                {
                    // no more contiguous characters.  Fall back to slow path
                    return false;
                }

                switch (characterWindow[currentOffset])
                {
                    case '&':
                        // CONSIDER: This method is performance critical, so
                        // it might be safer to kick out at the top (as for
                        // LexerMode.DebuggerSyntax).

                        // If we're in a cref, this could be the start of an
                        // xml entity that belongs in the identifier.
                        if (InXmlCrefOrNameAttributeValue)
                        {
                            // Fall back on the slow path.
                            return false;
                        }

                        // Otherwise, end the identifier.
                        goto case '\0';
                    case '\0':
                    case ' ':
                    case '\r':
                    case '\n':
                    case '\t':
                    case '!':
                    case '%':
                    case '(':
                    case ')':
                    case '*':
                    case '+':
                    case ',':
                    case '-':
                    case '.':
                    case '/':
                    case ':':
                    case ';':
                    case '<':
                    case '=':
                    case '>':
                    case '?':
                    case '[':
                    case ']':
                    case '^':
                    case '{':
                    case '|':
                    case '}':
                    case '~':
                    case '"':
                    case '\'':
                        // All of the following characters are not valid in an 
                        // identifier.  If we see any of them, then we know we're
                        // done.
                        var length = currentOffset - startOffset;
                        TextWindow.AdvanceChar(length);
                        info.Text = info.StringValue = TextWindow.Intern(characterWindow, startOffset, length);
                        info.IsVerbatim = false;
                        return true;
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9':
                        if (currentOffset == startOffset)
                        {
                            return false;
                        }
                        else
                        {
                            goto case 'A';
                        }
                    case 'A':
                    case 'B':
                    case 'C':
                    case 'D':
                    case 'E':
                    case 'F':
                    case 'G':
                    case 'H':
                    case 'I':
                    case 'J':
                    case 'K':
                    case 'L':
                    case 'M':
                    case 'N':
                    case 'O':
                    case 'P':
                    case 'Q':
                    case 'R':
                    case 'S':
                    case 'T':
                    case 'U':
                    case 'V':
                    case 'W':
                    case 'X':
                    case 'Y':
                    case 'Z':
                    case '_':
                    case 'a':
                    case 'b':
                    case 'c':
                    case 'd':
                    case 'e':
                    case 'f':
                    case 'g':
                    case 'h':
                    case 'i':
                    case 'j':
                    case 'k':
                    case 'l':
                    case 'm':
                    case 'n':
                    case 'o':
                    case 'p':
                    case 'q':
                    case 'r':
                    case 's':
                    case 't':
                    case 'u':
                    case 'v':
                    case 'w':
                    case 'x':
                    case 'y':
                    case 'z':
                        // All of these characters are valid inside an identifier.
                        // consume it and keep processing.
                        currentOffset++;
                        continue;

                    // case '@':  verbatim identifiers are handled in the slow path
                    // case '\\': unicode escapes are handled in the slow path
                    default:
                        // Any other character is something we cannot handle.  i.e.
                        // unicode chars or an escape.  Just break out and move to
                        // the slow path.
                        return false;
                }
            }
        }