void Push(char ch)
        {
            if (readPreprocessorExpression)
            {
                wordBuf.Append(ch);
            }

            if (inside.HasFlag(Inside.VerbatimString) && pc == '"' && ch != '"')
            {
                inside &= ~Inside.String;
            }
            switch (ch)
            {
            case '#':
                if (IsLineStart)
                {
                    inside = Inside.PreProcessor;
                }
                break;

            case '/':
                if (IsInStringOrChar || IsInPreProcessorComment)
                {
                    break;
                }
                if (pc == '/')
                {
                    if (inside.HasFlag(Inside.Comment))
                    {
                        inside |= Inside.DocComment;
                    }
                    else
                    {
                        inside |= Inside.Comment;
                    }
                }
                break;

            case '*':
                if (IsInStringOrChar || IsInComment || IsInPreProcessorComment)
                {
                    break;
                }
                if (pc == '/')
                {
                    inside |= Inside.MultiLineComment;
                }
                break;

            case '\t':
                var nextTabStop = (col - 1 + textEditorOptions.IndentSize) / textEditorOptions.IndentSize;
                col = 1 + nextTabStop * textEditorOptions.IndentSize;
                return;

            case '\r':

                if (readPreprocessorExpression)
                {
                    if (!eval(wordBuf.ToString()))
                    {
                        inside |= Inside.PreProcessorComment;
                    }
                }

                inside &= ~(Inside.Comment | Inside.String | Inside.CharLiteral | Inside.PreProcessor);
                CheckKeyword(wordBuf.ToString());
                wordBuf.Length = 0;
                if (addContinuation)
                {
                    indent.Push(IndentType.Continuation);
                }
                thisLineindent             = indent.Clone();
                addContinuation            = false;
                IsLineStart                = true;
                readPreprocessorExpression = false;
                col = 1;
                line++;
                break;

            case '\n':
                if (pc == '\r')
                {
                    break;
                }
                goto case '\r';

            case '"':
                if (IsInComment || IsInPreProcessorComment)
                {
                    break;
                }
                if (inside.HasFlag(Inside.String))
                {
                    if (pc != '\\')
                    {
                        inside &= ~Inside.String;
                    }
                    break;
                }

                if (pc == '@')
                {
                    inside |= Inside.VerbatimString;
                }
                else
                {
                    inside |= Inside.String;
                }
                break;

            case '<':
            case '[':
            case '(':
                if (IsInComment || IsInStringOrChar || IsInPreProcessorComment)
                {
                    break;
                }
                parenStack.Push(new TextLocation(line, col));
                popNextParenBlock = true;
                indent.Push(IndentType.Block);
                break;

            case '>':
            case ']':
            case ')':
                if (IsInComment || IsInStringOrChar || IsInPreProcessorComment)
                {
                    break;
                }
                if (popNextParenBlock)
                {
                    parenStack.Pop();
                }
                indent.Pop();
                indent.ExtraSpaces = 0;
                break;

            case ',':
                if (IsInComment || IsInStringOrChar || IsInPreProcessorComment)
                {
                    break;
                }
                if (parenStack.Count > 0 && parenStack.Peek().Line == line)
                {
                    indent.Pop();
                    popNextParenBlock  = false;
                    indent.ExtraSpaces = parenStack.Peek().Column - 1 - thisLineindent.CurIndent;
                }
                break;

            case '{':
                if (IsInComment || IsInStringOrChar || IsInPreProcessorComment)
                {
                    break;
                }
                currentBody = nextBody;
                if (indent.Count > 0 && indent.Peek() == IndentType.Continuation)
                {
                    indent.Pop();
                }
                addContinuation = false;
                AddIndentation(currentBody);
                break;

            case '}':
                if (IsInComment || IsInStringOrChar || IsInPreProcessorComment)
                {
                    break;
                }
                indent.Pop();
                if (indent.Count > 0 && indent.Peek() == IndentType.Continuation)
                {
                    indent.Pop();
                }
                break;

            case ';':
                if (IsInComment || IsInStringOrChar || IsInPreProcessorComment)
                {
                    break;
                }
                if (indent.Count > 0 && indent.Peek() == IndentType.Continuation)
                {
                    indent.Pop();
                }
                break;

            case '\'':
                if (IsInComment || inside.HasFlag(Inside.String) || IsInPreProcessorComment)
                {
                    break;
                }
                if (inside.HasFlag(Inside.CharLiteral))
                {
                    if (pc != '\\')
                    {
                        inside &= ~Inside.CharLiteral;
                    }
                }
                else
                {
                    inside &= Inside.CharLiteral;
                }
                break;
            }

            if (!IsInComment && !IsInStringOrChar && !readPreprocessorExpression)
            {
                if ((wordBuf.Length == 0 ? char.IsLetter(ch) : char.IsLetterOrDigit(ch)) || ch == '_')
                {
                    wordBuf.Append(ch);
                }
                else
                {
                    if (inside.HasFlag(Inside.PreProcessor))
                    {
                        if (wordBuf.ToString() == "endif")
                        {
                            inside &= ~Inside.PreProcessorComment;
                        }
                        else if (wordBuf.ToString() == "if")
                        {
                            readPreprocessorExpression = true;
                        }
                        else if (wordBuf.ToString() == "elif")
                        {
                            inside &= ~Inside.PreProcessorComment;
                            readPreprocessorExpression = true;
                        }
                    }
                    else
                    {
                        CheckKeyword(wordBuf.ToString());
                    }
                    wordBuf.Length = 0;
                }
            }
            if (addContinuation)
            {
                indent.Push(IndentType.Continuation);
                addContinuation = false;
            }
            IsLineStart &= ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r';
            pc           = ch;
            if (ch != '\n' && ch != '\r')
            {
                col++;
            }
        }