Digs - Персональная территория

Авторский проект Артема Глазкова
? 
        Версия для печати (цвет)  

Использование материалов
Заметка #12
10 сентября 2005

Раскраска текста


    Собственно то, до чего руки так и не дошли. Уже давно порываюсь написать универсальный компонент-редактор с раскраской текста, но задумка настолько давняя, что браться уже как-то не хочется, особенно когда в голове уже все проработал до мелочей. Вот было бы здорово, если бы появилась такая задача, связанная с моей работой. Точнее, я уже писал раскраску, но это был редактор, ориентированный на подсветку мнемоник ассемблера. Это не тоже самое, что раскраска исходников, где некая единица синтаксиса может растянуться на несколько строк. Например, в Delphi зарезервированные слова read и write выделяются особо, только если они находятся в конструкции property.

    Задача ставится еще и таким образом, чтобы не только раскрасить красиво, но чтобы это еще и работало быстро. Если при добавлении в редакторе символа будет пересчитываться раскраска всего текста, то такой компонент никому не будет нужен.

    Итак, как же хранится текст в редакторе? Текст это массив ссылок на строки. При такой организации строки очень просто добавлять и удалять, а также считать их количество.

    Далее такая идея. Для каждой позиции строки должно наличествовать как бы состояние строки в этом месте. Например, где-то поставили первый символ комментария и все остальные синтаксисы перестают действовать, пока комментарий не закрыли. Или если написали property, то read и write считаются зарезервированными словами, пока не встретится точка с запятой. Т.е. нужно ввести некую структуру, по которой можно понять, какая единица синтаксиса в данный момент присутствует. В простейшем случае это будет набор флагов, каждый из которых будет означать определенное состояние (строковый литерал, комментарий и т.д.).

    Следующий шаг, это написание функции, которая из входной строки будет выделять терм или другую единицу синтаксиса, при этом на вход функции должны подаваться строка, а также структура состояния, о которой ведем речь. Результатом работы функции будет выделенная подстрока соответствующая текущему состоянию, код синтаксической единицы (по этому коду будет производиться раскраска), а также новое состояние. С последним данная функция будет вызвана для оставшейся части строки. Анализ строки в такой функции нужно производить в зависимости от текущего состояния, т.е. если открылся комментарий, то нет смысла идти по строке и выделять зарезервированные слова. Искать нужно непосредственно тег окончания комментария. В принципе, в примере со строкой, можно сразу выделять всю строку как единицу текста.

    Теперь что касается строк. После разбора данной функцией всей строки, остается состояние конца строки. Я предлагаю его хранить в массиве ссылок на строки наравне со ссылкой. А далее придерживаться следующего алгоритма: если после разбора строки последнее состояние совпадает с запомненным, то можно сказать что в строке не произошло существенных изменений и на этом разбор завершается. Если же состояния разные, то это означает, что нужно произвести разбор также следующей строки. И так до тех пор, пока у очередной строки не совпадет конечное состояние разбора с сохраненным состоянием. Ну и, соответственно, перерисовать все строки, которые пересчитали и которые видны на экране.

    Чтобы снизить количество вычислений, можно ввести функцию, которая в заданном состоянии будет сбрасывать флаги тех синтаксисов, которые не могут перейти в следующую строку. Например, строковый литерал и строковый комментарий (тот который распространяется только до конца строки). После получения конечного состояния нужно вызвать данную функцию и только после этого производить сравнение с запомненным.

    В итоге всего, выше сказанного нужно написать класс с двумя описанными виртуальными функциями, а также реализацией алгоритма обращающегося к этим функциям. Сразу после загрузки файла нужно сделать пересчет конечных состояний. Вот собственно и все мысли по этому поводу.

    Вообще вся статья задумывалась, чтобы рассказать про состояние, а про сам разбор я рассказывать не собирался. С этим каждый сам справится. Хотя, если вероятность, что как-нибудь набросаю про это статейку.


© 2005-16, Powered By Digs (Написать письмо, vk)