Подсветка синтаксиса / Алгоритмы лексического анализа

Какой общий алгоритм используется подсветкой синтаксиса? Я реализовал простой подход, используя чередование в регулярном выражении:

STRING_PATTERN | COMMENT_PATTERN | KEYWORD_PATTERNS

Поскольку определение того, является ли что-то строкой или шаблоном, зависит от того, что идет первым:

// This is a "comment"

"This is a // string"

Но с ключевыми словами все становится немного сложнее. Этот подход работает в моей текущей реализации, но я не уверен, что он оптимален.

Другая проблема - это порядок выделения. Если вы выделите числа перед идентификаторами / ключевыми словами, вы можете случайно выделить число в ключевом слове ...

РЕДАКТИРОВАТЬ:

Мой плагин теперь здесь: http://wordpress.org/extend/plugins/crayon-syntax-highlighter/


person Aram Kocharyan    schedule 19.07.2011    source источник


Ответы (1)


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

Вам необходимо изучить генераторы синтаксического анализатора, такие как Antlr, которые - при правильной, однозначной грамматике - способны выдавать вам токены, которые учитывают эти детали. Например. если комментарий определен как «//» до EOL, он вернет токен комментария, который заменит любые строковые символы или что-то внутри.

Стандартный подход для подобных синтаксических анализаторов заключается в чтении в потоке символов (или токенов, более конкретно) по одному, поэтому выделение зависит не от порядка правил, которые вы определяете, а от порядка их появления в потоке.

Например, строка может состоять из двух двойных кавычек и всего, что находится между ними (кроме другой двойной кавычки). Комментарий - это две косые черты и все до конца строки.

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

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

По сути, все сводится к конечным автоматам. Вы можете попробовать создать свой собственный, или вы можете получить что-то вроде Antlr, скормить ему грамматику и позволить ему делать всю вашу работу за вас.

person ChrisC    schedule 19.07.2011
comment
мой подход хорошо сработал для того, что вы упомянули о том, что идет первым, потому что происходит чередование, которое происходит первым, как оператор OR. Я думаю, что попробую сделать это сам, в конце концов, это то, что я намеревался сделать, создавая подсветку синтаксиса. Regex обрабатывает всю логику, которую вы объясняете, например, что считать строкой. Таким же образом легко создавать многострочные комментарии и строки. Мой вопрос был не в том, как найти вхождения токенов, а в том, что с ними делать после того, как они будут найдены. Думаю, я над этим поработаю. - person Aram Kocharyan; 19.07.2011
comment
Хорошо, я понимаю, о чем вы спрашиваете. Опять же, проблема, с которой вы столкнетесь, заключается в том, что у вас есть одно регулярное выражение, которое ищет токены, и одно и то же регулярное выражение вернет совпадение, но НЕ БУДЕТ сообщать вам, какой токен вы получили обратно. Если вы хотите продолжить использование подхода регулярных выражений, вы можете изучить именованные группы (хотя это, как правило, синтаксис, зависящий от платформы, а некоторые языки, например, Java, даже не поддерживают его). Если регулярное выражение может сказать вам, какой именованной группе оно соответствует, вы можете использовать это имя для поиска в таблице, содержащей ваши правила формата выделения (например, ключевое слово - ›жирный шрифт). - person ChrisC; 21.07.2011
comment
Кроме того, хотя они используют грамматический подход к лексированию / синтаксическому анализу, вы можете взглянуть на API Eclipse и XText, чтобы узнать, как они обрабатывают подсветку синтаксиса. Это непросто понять, но это может дать вам некоторые идеи о хорошем четком структурном разделении между синтаксическим анализом и выделением. - person ChrisC; 21.07.2011
comment
Спасибо, Крис, я успешно реализовал метод группировки, поэтому я думаю, что пойду на это. Это просто, и нет необходимости в сложной логике, когда токены найдены. - person Aram Kocharyan; 21.07.2011