Regexp для сопоставления строковых литералов Javascript с определенным ключевым словом с использованием Java - PullRequest
3 голосов
/ 10 июля 2009

Я пытаюсь сопоставить фрагменты кода JS и извлечь строковые литералы, содержащие данное ключевое слово, с помощью Java.

После попытки создать собственное регулярное выражение для этого я в итоге изменил это обобщенное строковое литеральное соответствие регулярному выражению (Pattern.COMMENTS, используемый при построении шаблонов в Java):

(["'])
(?:\\?+.)*?
\1

до следующего

(["'])
(?:\\?+.)*?
keyword
(?:\\?+.)*?
\1

Контрольные примеры:

var v1 = "test";
var v2 = "testkeyword";
var v3 = "test"; var v4 = "testkeyword";

Регулярное выражение правильно не соответствует строке 1 и правильно соответствует строке 2.

Однако в строке 3 вместо простого совпадения с «testkeyword» он соответствует чанку

"test"; var v4 = "testkeyword"

что неверно - регулярное выражение соответствовало первой двойной кавычке и не заканчивалось на второй двойной кавычке, вплоть до конца строки.

У кого-нибудь есть идеи, как это исправить?

PS: имейте в виду, что Regexp должен правильно обрабатывать экранированные символы одинарных и двойных кавычек внутри строковых литералов (что уже сделал обобщенный сопоставитель).

Ответы [ 5 ]

3 голосов
/ 10 июля 2009

Как насчет этой модификации:

(?:
    "
    (?:\\"|[^"\r\n])*
    keyword
    (?:\\"|[^"\r\n])*
    "
|
    '
    (?:\\'|[^'\r\n])*
    keyword
    (?:\\'|[^'\r\n])*
    '
)
1 голос
/ 10 июля 2009

После большого пересмотра (см. Историю редактирования, зрители дома :), я считаю, что это мой окончательный ответ:

(?:
    "
    (?:\\?+"|[^"])*
    keyword
    (?:\\?+"|[^"])*
    "
|
    '
    (?:\\?+'|[^'])*
    keyword
    (?:\\?+'|[^'])*
    '
)
0 голосов
/ 10 июля 2009

Грамматика для построения строкового литерала будет выглядеть примерно так:

string-literal ::= quote text quote

text ::= character text
       | character

character ::= non-quote
            | backslash quote

с терминалами без кавычек, обратной косой черты и кавычек.

Грамматика является регулярной, если она не зависит от контекста (т. Е. Левая часть всех правил всегда является одним нетерминалом), а правая часть всех правил всегда либо пустая, либо терминал, либо терминал, за которым следует нетерминал.

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

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

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

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

0 голосов
/ 10 июля 2009

Рассмотрите возможность использования кода из Rhino - JS на Java - для получения реальных строковых литералов.

Или, если вы хотите использовать регулярное выражение, рассмотрите одну находку для всего литерала, а затем вложенный тест, если литерал содержит «ключевое слово».

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

    var v5 =  "test\x6b\u0065yword"

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

0 голосов
/ 10 июля 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...